* [RFC PATCH 5/9] arm64/kprobes: Invoke pre/post handlers inside instrumentation
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
The kprobe pre_handler() and post_handler() are arbitrary instrumentable
code and can themselves trace, fault, or hit other kprobes. They are
the only parts of the kprobe debug exception flow that legitimately
need instrumentation.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/include/asm/kprobes.h | 9 +++------
arch/arm64/kernel/probes/kprobes.c | 22 ++++++++++++++++++----
2 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 35ce2c94040e..a694f7d34f45 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -48,11 +48,8 @@ void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
#endif /* CONFIG_KPROBES */
-int __kprobes kprobe_brk_handler(struct pt_regs *regs,
- unsigned long esr);
-int __kprobes kprobe_ss_brk_handler(struct pt_regs *regs,
- unsigned long esr);
-int __kprobes kretprobe_brk_handler(struct pt_regs *regs,
- unsigned long esr);
+int noinstr kprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
+int noinstr kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr);
+int noinstr kretprobe_brk_handler(struct pt_regs *regs, unsigned long esr);
#endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1b12341b2af3..e9fa66fa4217 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -301,8 +301,11 @@ post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_reg
}
/* call post handler */
kcb->kprobe_status = KPROBE_HIT_SSDONE;
+
+ instrumentation_begin();
if (cur->post_handler)
cur->post_handler(cur, regs, 0);
+ instrumentation_end();
reset_current_kprobe();
}
@@ -359,24 +362,28 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
return 0;
}
-int __kprobes
+int noinstr
kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
{
struct kprobe *p, *cur_kprobe;
struct kprobe_ctlblk *kcb;
unsigned long addr = instruction_pointer(regs);
+ bool handled;
kcb = get_kprobe_ctlblk();
cur_kprobe = kprobe_running();
+ instrumentation_begin();
p = get_kprobe((kprobe_opcode_t *) addr);
if (WARN_ON_ONCE(!p)) {
+ instrumentation_end();
/*
* Something went wrong. This BRK used an immediate reserved
* for kprobes, but we couldn't find any corresponding probe.
*/
return DBG_HOOK_ERROR;
}
+ instrumentation_end();
if (cur_kprobe) {
/* Hit a kprobe inside another kprobe */
@@ -387,6 +394,10 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
set_current_kprobe(p);
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+ instrumentation_begin();
+ handled = p->pre_handler && p->pre_handler(p, regs);
+ instrumentation_end();
+
/*
* If we have no pre-handler or it returned 0, we
* continue with normal processing. If we have a
@@ -394,7 +405,7 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
* modify the execution path and not need to single-step
* Let's just reset current kprobe and exit.
*/
- if (!p->pre_handler || !p->pre_handler(p, regs))
+ if (!handled)
setup_singlestep(p, regs, kcb, 0);
else
reset_current_kprobe();
@@ -403,7 +414,7 @@ kprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
return DBG_HOOK_HANDLED;
}
-int __kprobes
+int noinstr
kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
{
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -422,13 +433,16 @@ kprobe_ss_brk_handler(struct pt_regs *regs, unsigned long esr)
return DBG_HOOK_ERROR;
}
-int __kprobes
+int noinstr
kretprobe_brk_handler(struct pt_regs *regs, unsigned long esr)
{
if (regs->pc != (unsigned long)__kretprobe_trampoline)
return DBG_HOOK_ERROR;
+ instrumentation_begin();
regs->pc = kretprobe_trampoline_handler(regs, (void *)regs->regs[29]);
+ instrumentation_end();
+
return DBG_HOOK_HANDLED;
}
--
2.47.3
^ permalink raw reply related
* [RFC PATCH 4/9] arm64/kprobes: Make the single-step machinery noinstr
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
Convert the core of the arm64 kprobe single-step flow to noinstr:
save_previous_kprobe(), restore_previous_kprobe(), set_current_kprobe(),
kprobes_save_local_irqflag(), kprobes_restore_local_irqflag(),
setup_singlestep(), reenter_kprobe() and post_kprobe_handler().
These functions only touch per-cpu state, pt_regs and DAIF, except for:
- kprobes_inc_nmissed_count(), which is generic and instrumentable; add
an arm64-local wrapper that calls it bounded by
instrumentation_begin()/end();
- the instruction simulation path in setup_singlestep(), whose decode
handlers are instrumentable; bound arch_simulate_insn() with an
instrumentation window;
- the unrecoverable-reentry pr_warn()/dump_kprobe()/BUG() path and the
default WARN_ON(), both bounded with instrumentation windows.
The __kprobes attribute (notrace + .kprobes.text) is replaced by
noinstr, which is a strict superset for these functions.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/kernel/probes/kprobes.c | 39 ++++++++++++++++++------------
1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 4e0efad5caf2..1b12341b2af3 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -14,6 +14,7 @@
#include <linux/extable.h>
#include <linux/kasan.h>
#include <linux/kernel.h>
+#include <linux/instrumentation.h>
#include <linux/kprobes.h>
#include <linux/sched/debug.h>
#include <linux/set_memory.h>
@@ -39,7 +40,7 @@
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
-static void __kprobes
+static void noinstr
post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *);
void *alloc_insn_page(void)
@@ -170,7 +171,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
}
}
-static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void noinstr save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -184,7 +185,7 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->prev_kprobe.saved_irqflag = kcb->saved_irqflag;
}
-static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void noinstr restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -197,7 +198,7 @@ static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
kcb->saved_irqflag = kcb->prev_kprobe.saved_irqflag;
}
-static void __kprobes set_current_kprobe(struct kprobe *p)
+static void noinstr set_current_kprobe(struct kprobe *p)
{
__this_cpu_write(current_kprobe, p);
}
@@ -207,23 +208,23 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
* simple and avoid nesting exceptions. Interrupts do have to be disabled since
* the kprobe state is per-CPU and doesn't get migrated.
*/
-static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
- struct pt_regs *regs)
+static void noinstr kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
+ struct pt_regs *regs)
{
kcb->saved_irqflag = regs->pstate & DAIF_MASK;
regs->pstate |= DAIF_MASK;
}
-static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
- struct pt_regs *regs)
+static void noinstr kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
+ struct pt_regs *regs)
{
regs->pstate &= ~DAIF_MASK;
regs->pstate |= kcb->saved_irqflag;
}
-static void __kprobes setup_singlestep(struct kprobe *p,
- struct pt_regs *regs,
- struct kprobe_ctlblk *kcb, int reenter)
+static void noinstr setup_singlestep(struct kprobe *p,
+ struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb, int reenter)
{
unsigned long slot;
@@ -244,13 +245,15 @@ static void __kprobes setup_singlestep(struct kprobe *p,
instruction_pointer_set(regs, slot);
} else {
/* insn simulation */
+ instrumentation_begin();
arch_simulate_insn(p, regs);
+ instrumentation_end();
}
}
-static int __kprobes reenter_kprobe(struct kprobe *p,
- struct pt_regs *regs,
- struct kprobe_ctlblk *kcb)
+static int noinstr reenter_kprobe(struct kprobe *p,
+ struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
{
switch (kcb->kprobe_status) {
case KPROBE_HIT_SSDONE:
@@ -262,23 +265,29 @@ static int __kprobes reenter_kprobe(struct kprobe *p,
* recoverable one-level reentry, so handle it in the same way as
* reentry from KPROBE_HIT_ACTIVE or KPROBE_HIT_SSDONE.
*/
+ instrumentation_begin();
kprobes_inc_nmissed_count(p);
+ instrumentation_end();
setup_singlestep(p, regs, kcb, 1);
break;
case KPROBE_REENTER:
+ instrumentation_begin();
pr_warn("Failed to recover from reentered kprobes.\n");
dump_kprobe(p);
BUG();
+ instrumentation_end();
break;
default:
+ instrumentation_begin();
WARN_ON(1);
+ instrumentation_end();
return 0;
}
return 1;
}
-static void __kprobes
+static void noinstr
post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_regs *regs)
{
/* return addr restore if non-branching insn */
--
2.47.3
^ permalink raw reply related
* [RFC PATCH 6/9] arm64/kprobes: Make kprobe_fault_handler() noinstr
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
kprobe_fault_handler() is reached from do_page_fault() when a fault
happens while a kprobe single-step is armed. Everything it calls (the
save/restore helpers, kprobes_restore_local_irqflag(),
reset_current_kprobe(), register access) is noinstr after the previous
patch, and being called from an instrumentable caller into a noinstr
callee is fine.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/kernel/probes/kprobes.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index e9fa66fa4217..4172998d48d9 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -310,7 +310,7 @@ post_kprobe_handler(struct kprobe *cur, struct kprobe_ctlblk *kcb, struct pt_reg
reset_current_kprobe();
}
-int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
+int noinstr kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
--
2.47.3
^ permalink raw reply related
* [RFC PATCH 9/9] arm64/debug: Mark debug exception helpers __always_inline
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas, Dennis Zhou,
Tejun Heo, Christoph Lameter, Oleg Nesterov, Naveen N Rao,
David S. Miller, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org,
linux-trace-kernel@vger.kernel.org, llvm@lists.linux.dev
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
Static inline should be enough to actually inline functions for most
compilers, but my Clang-19 somehow thinks it's better to outline them.
These tiny helpers then live in normal .text sections instead of
.noinstr sections, violating noinstr.
Mark them __always_inline so the compiler can never outline them.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/include/asm/esr.h | 2 +-
arch/arm64/include/asm/percpu.h | 2 +-
arch/arm64/include/asm/preempt.h | 4 ++--
arch/arm64/include/asm/ptrace.h | 4 ++--
arch/arm64/kernel/debug-monitors.c | 2 +-
include/linux/kprobes.h | 8 ++++----
6 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index f816f5d77f1a..a75bfdb7e5fe 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -437,7 +437,7 @@
#ifndef __ASSEMBLER__
#include <asm/types.h>
-static inline unsigned long esr_brk_comment(unsigned long esr)
+static __always_inline unsigned long esr_brk_comment(unsigned long esr)
{
return esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;
}
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index b57b2bb00967..d4cae47fde8c 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -29,7 +29,7 @@ static inline unsigned long __hyp_my_cpu_offset(void)
return read_sysreg(tpidr_el2);
}
-static inline unsigned long __kern_my_cpu_offset(void)
+static __always_inline unsigned long __kern_my_cpu_offset(void)
{
unsigned long off;
diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h
index 932ea4b62042..326f221c3f56 100644
--- a/arch/arm64/include/asm/preempt.h
+++ b/arch/arm64/include/asm/preempt.h
@@ -41,14 +41,14 @@ static inline bool test_preempt_need_resched(void)
return !current_thread_info()->preempt.need_resched;
}
-static inline void __preempt_count_add(int val)
+static __always_inline void __preempt_count_add(int val)
{
u32 pc = READ_ONCE(current_thread_info()->preempt.count);
pc += val;
WRITE_ONCE(current_thread_info()->preempt.count, pc);
}
-static inline void __preempt_count_sub(int val)
+static __always_inline void __preempt_count_sub(int val)
{
u32 pc = READ_ONCE(current_thread_info()->preempt.count);
pc -= val;
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 39582511ad72..460726224299 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -336,11 +336,11 @@ static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
struct task_struct;
int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task);
-static inline unsigned long instruction_pointer(struct pt_regs *regs)
+static __always_inline unsigned long instruction_pointer(struct pt_regs *regs)
{
return regs->pc;
}
-static inline void instruction_pointer_set(struct pt_regs *regs,
+static __always_inline void instruction_pointer_set(struct pt_regs *regs,
unsigned long val)
{
regs->pc = val;
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index a970ab6327cd..66cb8151f5df 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -146,7 +146,7 @@ postcore_initcall(debug_monitors_init);
/*
* Single step API and exception handling.
*/
-static void set_user_regs_spsr_ss(struct user_pt_regs *regs)
+static __always_inline void set_user_regs_spsr_ss(struct user_pt_regs *regs)
{
regs->pstate |= DBG_SPSR_SS;
}
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8c4f3bb24429..5880445ed0f0 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -384,17 +384,17 @@ static inline void kprobe_ftrace_kill(void) {}
struct kprobe *get_kprobe(void *addr);
/* kprobe_running() will just return the current_kprobe on this CPU */
-static inline struct kprobe *kprobe_running(void)
+static __always_inline struct kprobe *kprobe_running(void)
{
return __this_cpu_read(current_kprobe);
}
-static inline void reset_current_kprobe(void)
+static __always_inline void reset_current_kprobe(void)
{
__this_cpu_write(current_kprobe, NULL);
}
-static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
+static __always_inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
{
return this_cpu_ptr(&kprobe_ctlblk);
}
@@ -449,7 +449,7 @@ static inline struct kprobe *get_kprobe(void *addr)
{
return NULL;
}
-static inline struct kprobe *kprobe_running(void)
+static __always_inline struct kprobe *kprobe_running(void)
{
return NULL;
}
--
2.47.3
^ permalink raw reply related
* [RFC PATCH 8/9] arm64/kprobes: Drop the XOL single-step fault PC check
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
With the armed single-step window closed (the whole path noinstr, and
every piece of instrumentable code confined to instrumentation windows
that run in KPROBE_HIT_ACTIVE/HIT_SSDONE state), no code other than the
XOL instruction itself can execute while the state is KPROBE_HIT_SS or
KPROBE_REENTER. A page fault taken in those states therefore necessarily
originates from the XOL instruction, and the faulting-PC comparison is
redundant; revert to handling all such faults as single-step faults (as
before commit 879a6754d3d1).
The simulated-kprobe early bail is kept: simulated probes have no XOL
slot and execute (inside an instrumentation window) in debug trap
context, so a fault there can still come from the simulation handlers
and must not be treated as a single-step fault.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/kernel/probes/kprobes.c | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1658b6acd803..73bbbcdbbfe5 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -309,18 +309,6 @@ int noinstr kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
switch (kcb->kprobe_status) {
case KPROBE_HIT_SS:
case KPROBE_REENTER:
- /*
- * A page fault taken while in KPROBE_HIT_SS or
- * KPROBE_REENTER state is only attributable to kprobe
- * single-stepping if the faulting PC points to the
- * current kprobe's XOL instruction. If the fault occurred
- * elsewhere (e.g. in perf or tracing code invoked from the
- * debug exception path), leave it for the normal page fault
- * handler to process.
- */
- if (instruction_pointer(regs) != (unsigned long)cur->ainsn.xol_insn)
- break;
-
/*
* We are here because the instruction being single
* stepped caused a page fault. We reset the current
--
2.47.3
^ permalink raw reply related
* [RFC PATCH 2/9] arm64/entry: Make debug_exception_enter/exit() noinstr
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
Commit 879a6754d3d11e30af24b7dc486f561510d62641 ran into a crash because
debug_exception_enter/exit() triggered page faults caused by perf dwarf
call graph tracing. That patch was a band-aid on top. Instead of trying
to band-aid all possible paths that can happen during instrumentation or
perf tracing, simply make both functions noinstr.
Drop the RCU_LOCKDEP_WARN(): arm64_enter_el1_dbg() runs first and
enters NMI context via ct_nmi_enter(), so RCU is always watching by the
time debug_exception_enter() runs.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/kernel/entry-common.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 466529cce1c3..f06b5e2437cd 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -293,20 +293,26 @@ static __always_inline void fpsimd_syscall_exit(void)
* accidentally schedule in exception context and it will force a warning
* if we somehow manage to schedule by accident.
*/
-static void debug_exception_enter(struct pt_regs *regs)
+static void noinstr debug_exception_enter(struct pt_regs *regs)
{
- preempt_disable();
-
- /* This code is a bit fragile. Test it. */
- RCU_LOCKDEP_WARN(!rcu_is_watching(), "exception_enter didn't work");
+ /*
+ * debug_exception_enter/exit() can be quite delicate. The normal
+ * preempt_disable/enable() can be instrumented or traced by perf,
+ * which leads to a can of worms including triggering page faults.
+ *
+ * Instead of trying to make all of them work properly here, just
+ * open-code the simpler version of preempt_disable/enable() and make
+ * enter/exit() both noinstr to avoid the entire complexity.
+ */
+ __preempt_count_inc();
+ barrier();
}
-NOKPROBE_SYMBOL(debug_exception_enter);
-static void debug_exception_exit(struct pt_regs *regs)
+static void noinstr debug_exception_exit(struct pt_regs *regs)
{
- preempt_enable_no_resched();
+ barrier();
+ __preempt_count_dec();
}
-NOKPROBE_SYMBOL(debug_exception_exit);
UNHANDLED(el1t, 64, sync)
UNHANDLED(el1t, 64, irq)
--
2.47.3
^ permalink raw reply related
* [RFC PATCH 3/9] arm64/debug-monitors: Make do_el1_brk64()/do_el1_softstep() noinstr
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
Convert do_el1_brk64(), do_el1_softstep() and call_el1_break_hook() to
noinstr. The kprobe and kretprobe BRK handlers (converted to noinstr in
the following patches) are dispatched directly. Every other BRK handler
are ordinary instrumentable code and now run bounded by
instrumentation_begin()/end().
With this, everything on the el1 debug exception path from the vectors
down to the kprobe handlers is noinstr, and instrumentation only runs
inside explicit instrumentation windows.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/kernel/debug-monitors.c | 74 +++++++++++++++++-------------
1 file changed, 41 insertions(+), 33 deletions(-)
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 29307642f4c9..a970ab6327cd 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -11,6 +11,7 @@
#include <linux/debugfs.h>
#include <linux/hardirq.h>
#include <linux/init.h>
+#include <linux/instrumentation.h>
#include <linux/ptrace.h>
#include <linux/kprobes.h>
#include <linux/stat.h>
@@ -193,59 +194,65 @@ void do_el0_softstep(unsigned long esr, struct pt_regs *regs)
user_rewind_single_step(current);
}
-void do_el1_softstep(unsigned long esr, struct pt_regs *regs)
+void noinstr do_el1_softstep(unsigned long esr, struct pt_regs *regs)
{
- if (kgdb_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
+ int handled;
+
+ instrumentation_begin();
+ handled = kgdb_single_step_handler(regs, esr);
+ instrumentation_end();
+
+ if (handled == DBG_HOOK_HANDLED)
return;
+ instrumentation_begin();
pr_warn("Unexpected kernel single-step exception at EL1\n");
+ instrumentation_end();
/*
* Re-enable stepping since we know that we will be
* returning to regs.
*/
set_regs_spsr_ss(regs);
}
-NOKPROBE_SYMBOL(do_el1_softstep);
-static int call_el1_break_hook(struct pt_regs *regs, unsigned long esr)
+static int noinstr call_el1_break_hook(struct pt_regs *regs, unsigned long esr)
{
- if (esr_brk_comment(esr) == BUG_BRK_IMM)
- return bug_brk_handler(regs, esr);
-
- if (IS_ENABLED(CONFIG_CFI) && esr_is_cfi_brk(esr))
- return cfi_brk_handler(regs, esr);
-
- if (esr_brk_comment(esr) == FAULT_BRK_IMM)
- return reserved_fault_brk_handler(regs, esr);
-
- if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
- (esr_brk_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
- return kasan_brk_handler(regs, esr);
-
- if (IS_ENABLED(CONFIG_UBSAN_TRAP) && esr_is_ubsan_brk(esr))
- return ubsan_brk_handler(regs, esr);
-
- if (IS_ENABLED(CONFIG_KGDB)) {
- if (esr_brk_comment(esr) == KGDB_DYN_DBG_BRK_IMM)
- return kgdb_brk_handler(regs, esr);
- if (esr_brk_comment(esr) == KGDB_COMPILED_DBG_BRK_IMM)
- return kgdb_compiled_brk_handler(regs, esr);
- }
+ unsigned long comment = esr_brk_comment(esr);
+ int ret = DBG_HOOK_ERROR;
if (IS_ENABLED(CONFIG_KPROBES)) {
- if (esr_brk_comment(esr) == KPROBES_BRK_IMM)
+ if (comment == KPROBES_BRK_IMM)
return kprobe_brk_handler(regs, esr);
- if (esr_brk_comment(esr) == KPROBES_BRK_SS_IMM)
+ if (comment == KPROBES_BRK_SS_IMM)
return kprobe_ss_brk_handler(regs, esr);
}
if (IS_ENABLED(CONFIG_KRETPROBES) &&
- esr_brk_comment(esr) == KRETPROBES_BRK_IMM)
+ comment == KRETPROBES_BRK_IMM)
return kretprobe_brk_handler(regs, esr);
- return DBG_HOOK_ERROR;
+ instrumentation_begin();
+ if (comment == BUG_BRK_IMM)
+ ret = bug_brk_handler(regs, esr);
+ else if (IS_ENABLED(CONFIG_CFI) && esr_is_cfi_brk(esr))
+ ret = cfi_brk_handler(regs, esr);
+ else if (comment == FAULT_BRK_IMM)
+ ret = reserved_fault_brk_handler(regs, esr);
+ else if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) &&
+ (comment & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
+ ret = kasan_brk_handler(regs, esr);
+ else if (IS_ENABLED(CONFIG_UBSAN_TRAP) && esr_is_ubsan_brk(esr))
+ ret = ubsan_brk_handler(regs, esr);
+ else if (IS_ENABLED(CONFIG_KGDB)) {
+ if (comment == KGDB_DYN_DBG_BRK_IMM)
+ ret = kgdb_brk_handler(regs, esr);
+ else if (comment == KGDB_COMPILED_DBG_BRK_IMM)
+ ret = kgdb_compiled_brk_handler(regs, esr);
+ }
+ instrumentation_end();
+
+ return ret;
}
-NOKPROBE_SYMBOL(call_el1_break_hook);
/*
* We have already unmasked interrupts and enabled preemption
@@ -261,14 +268,15 @@ void do_el0_brk64(unsigned long esr, struct pt_regs *regs)
send_user_sigtrap(TRAP_BRKPT);
}
-void do_el1_brk64(unsigned long esr, struct pt_regs *regs)
+void noinstr do_el1_brk64(unsigned long esr, struct pt_regs *regs)
{
if (call_el1_break_hook(regs, esr) == DBG_HOOK_HANDLED)
return;
+ instrumentation_begin();
die("Oops - BRK", regs, esr);
+ instrumentation_end();
}
-NOKPROBE_SYMBOL(do_el1_brk64);
#ifdef CONFIG_COMPAT
void do_bkpt32(unsigned long esr, struct pt_regs *regs)
--
2.47.3
^ permalink raw reply related
* [RFC PATCH 1/9] arm64/entry: Bound certain debug exception paths in instrumentation windows
From: Hongyan Xia @ 2026-07-27 12:25 UTC (permalink / raw)
To: Will Deacon, Masami Hiramatsu, Catalin Marinas
Cc: Jiazi Li, Pu Hu, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1785153469.git.hongyan.xia@transsion.com>
From: Hongyan Xia <hongyan.xia@transsion.com>
The el1 debug exception handlers are noinstr, but their payload calls
(do_breakpoint(), do_watchpoint(), try_step_suspended_breakpoints()
and the Cortex-A76 erratum handler) are ordinary instrumentable code.
Mark the boundaries explicitly with instrumentation_begin()/end(), in
the same style as x86 exception entries.
The BRK handlers (do_el1_brk64(), do_el1_softstep()) will be dealt with
in later patches.
Signed-off-by: Hongyan Xia <hongyan.xia@transsion.com>
---
arch/arm64/kernel/entry-common.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index ceb4eb11232a..466529cce1c3 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -6,6 +6,7 @@
*/
#include <linux/context_tracking.h>
+#include <linux/instrumentation.h>
#include <linux/irq-entry-common.h>
#include <linux/kasan.h>
#include <linux/linkage.h>
@@ -380,7 +381,9 @@ static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
state = arm64_enter_el1_dbg(regs);
debug_exception_enter(regs);
+ instrumentation_begin();
do_breakpoint(esr, regs);
+ instrumentation_end();
debug_exception_exit(regs);
arm64_exit_el1_dbg(regs, state);
}
@@ -388,9 +391,15 @@ static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
static void noinstr el1_softstp(struct pt_regs *regs, unsigned long esr)
{
irqentry_state_t state;
+ bool handled;
state = arm64_enter_el1_dbg(regs);
- if (!cortex_a76_erratum_1463225_debug_handler(regs)) {
+
+ instrumentation_begin();
+ handled = cortex_a76_erratum_1463225_debug_handler(regs);
+ instrumentation_end();
+
+ if (!handled) {
debug_exception_enter(regs);
/*
* After handling a breakpoint, we suspend the breakpoint
@@ -398,7 +407,11 @@ static void noinstr el1_softstp(struct pt_regs *regs, unsigned long esr)
* If we are stepping a suspended breakpoint there's nothing more to do:
* the single-step is complete.
*/
- if (!try_step_suspended_breakpoints(regs))
+ instrumentation_begin();
+ handled = try_step_suspended_breakpoints(regs);
+ instrumentation_end();
+
+ if (!handled)
do_el1_softstep(esr, regs);
debug_exception_exit(regs);
}
@@ -413,7 +426,9 @@ static void noinstr el1_watchpt(struct pt_regs *regs, unsigned long esr)
state = arm64_enter_el1_dbg(regs);
debug_exception_enter(regs);
+ instrumentation_begin();
do_watchpoint(far, esr, regs);
+ instrumentation_end();
debug_exception_exit(regs);
arm64_exit_el1_dbg(regs, state);
}
--
2.47.3
^ permalink raw reply related
* Re: [v2 1/2] soc: fsl: dpio: Use scope-based resource management in dpaa2_io_store_create()
From: Markus Elfring @ 2026-07-27 12:24 UTC (permalink / raw)
To: Ioana Ciornei, linux-arm-kernel, linuxppc-dev
Cc: Christophe Leroy, Roy Pledge, LKML, kernel-janitors
In-Reply-To: <y2h44um2grcbecnpkck44cvudugha6df2itq2uy5y46whxjouh@yy2kebig3ia5>
>> Scope-based resource management became supported for some
>> programming interfaces by contributions of Peter Zijlstra on 2023-05-26.
>> See also the commit 54da6a0924311c7cf5015533991e44fb8eb12773 ("locking:
>> Introduce __cleanup() based infrastructure").
>>
>> * Thus use the attribute “__free(kfree)”.
>>
>> * Reduce the scope for the local variable “ret”.
>
> Please don't. Let all the variables be defined at the start of each function.
Do we stumble on another coding style preferences conflict here?
https://elixir.bootlin.com/linux/v7.2-rc4/source/include/linux/cleanup.h#L142-L146
>> * Omit two kfree() calls accordingly.
>>
>> * Omit the local variable “size” (for another memory allocation).
>
> Please remove this change, not related to the intention of the patch.
What does hinder to perform the required size determination as a direct parameter
for a kzalloc() call?
Regards,
Markus
^ permalink raw reply
* [PATCH] arm64: versal-net: Add retention state for cpu idle
From: Jay Buddhabhatti @ 2026-07-27 12:18 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, michal.simek
Cc: devicetree, linux-arm-kernel, linux-kernel, git, Jay Buddhabhatti
Remove the sleep state and replace it with a retention state for CPU idle.
The sleep state powers down the CPU core, and the wake-up time cannot be
guaranteed because the firmware may be busy handling other tasks at the time
of the wake-up request. This leads to unpredictable and potentially high
wake-up latency during CPU idle.
Replace the sleep state with a retention state to avoid this dependency on
firmware. The retention state uses a PSCI suspend parameter of 0: the
core simply executes WFI and retains its context without being powered off.
Since wake-up from WFI is handled entirely in hardware, it is effectively
immediate (a few cycles) and does not depend on firmware availability.
As the core is not powered down, the local timer is retained and
"local-timer-stop" is dropped. The entry/exit latency and min-residency
are set to the nominal minimum (1 us), allowing the cpuidle governor to
select the state even for very short idle windows.
Signed-off-by: Jay Buddhabhatti <jay.buddhabhatti@amd.com>
---
arch/arm64/boot/dts/xilinx/versal-net.dtsi | 43 +++++++++++-----------
1 file changed, 21 insertions(+), 22 deletions(-)
diff --git a/arch/arm64/boot/dts/xilinx/versal-net.dtsi b/arch/arm64/boot/dts/xilinx/versal-net.dtsi
index 15f767608e67..792bed588ae1 100644
--- a/arch/arm64/boot/dts/xilinx/versal-net.dtsi
+++ b/arch/arm64/boot/dts/xilinx/versal-net.dtsi
@@ -103,7 +103,7 @@ cpu0: cpu@0 {
enable-method = "psci";
reg = <0>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -133,7 +133,7 @@ cpu100: cpu@100 {
enable-method = "psci";
reg = <0x100>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -163,7 +163,7 @@ cpu200: cpu@200 {
enable-method = "psci";
reg = <0x200>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -193,7 +193,7 @@ cpu300: cpu@300 {
enable-method = "psci";
reg = <0x300>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -223,7 +223,7 @@ cpu10000: cpu@10000 {
enable-method = "psci";
reg = <0x10000>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -253,7 +253,7 @@ cpu10100: cpu@10100 {
enable-method = "psci";
reg = <0x10100>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -283,7 +283,7 @@ cpu10200: cpu@10200 {
enable-method = "psci";
reg = <0x10200>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -313,7 +313,7 @@ cpu10300: cpu@10300 {
enable-method = "psci";
reg = <0x10300>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -343,7 +343,7 @@ cpu20000: cpu@20000 {
enable-method = "psci";
reg = <0x20000>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -373,7 +373,7 @@ cpu20100: cpu@20100 {
enable-method = "psci";
reg = <0x20100>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -403,7 +403,7 @@ cpu20200: cpu@20200 {
enable-method = "psci";
reg = <0x20200>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -433,7 +433,7 @@ cpu20300: cpu@20300 {
enable-method = "psci";
reg = <0x20300>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -463,7 +463,7 @@ cpu30000: cpu@30000 {
enable-method = "psci";
reg = <0x30000>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -493,7 +493,7 @@ cpu30100: cpu@30100 {
enable-method = "psci";
reg = <0x30100>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -523,7 +523,7 @@ cpu30200: cpu@30200 {
enable-method = "psci";
reg = <0x30200>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -553,7 +553,7 @@ cpu30300: cpu@30300 {
enable-method = "psci";
reg = <0x30300>;
operating-points-v2 = <&cpu_opp_table>;
- cpu-idle-states = <&CPU_SLEEP_0>;
+ cpu-idle-states = <&CPU_RETENTION_0>;
d-cache-size = <0x10000>; /* 64kB */
d-cache-line-size = <64>;
/* 4 ways set associativity */
@@ -636,13 +636,12 @@ llc: l4-cache { /* LLC inside CMN */
idle-states {
entry-method = "psci";
- CPU_SLEEP_0: cpu-sleep-0 {
+ CPU_RETENTION_0: cpu-retention-0 {
compatible = "arm,idle-state";
- arm,psci-suspend-param = <0x40000000>;
- local-timer-stop;
- entry-latency-us = <300>;
- exit-latency-us = <600>;
- min-residency-us = <10000>;
+ arm,psci-suspend-param = <0>;
+ entry-latency-us = <1>;
+ exit-latency-us = <1>;
+ min-residency-us = <1>;
};
};
};
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 0/9] ACPI: use named initializers for acpi_device_id
From: Rafael J. Wysocki (Intel) @ 2026-07-27 12:15 UTC (permalink / raw)
To: Pawel Zalewski (The Capable Hub)
Cc: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny, linux-acpi, linux-kernel,
linux-pci, linux-arm-kernel, nvdimm
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
On Mon, Jul 27, 2026 at 2:10 PM Pawel Zalewski (The Capable Hub)
<pzalewski@thegoodpenguin.co.uk> wrote:
>
> This series is converting lists that contain the acpi_device_id
> struct, which is defined in the include/linux/device-id/acpi.h
> to makes use of named initializers (which they do not use currently).
> This work is part of the on going effort in the kernel associated
> with device-ids [1]
>
> The plan is to convert acpi_device_id::driver_data to have an anonymous
> union, similarly to what was introduced for PCI and I2C device ID tables.
> The goal is to increase type-safety (as most of the existing casts are gone),
> to improve readability and to make use intent a bit more clear:
>
> ```
> union {
> kernel_ulong_t driver_data;
> const void *driver_data_ptr;
> }
> ```
>
> But for that to work all lists containing the structs need to use named
> initializers first. I already have patches that implement this and touching
> a lot of kernel subsystmes that use the acpi_device_id struct and that list
> keeps on growing. Therefore, I have decided to split the series per every
> subsystem into:
> - pre-clean-ups that convert the lists to use named initializers
> - actual implementations that make some of the modules use the new driver_data_ptr
>
> That way the task can be fragmented into manageable and independent
> chunks of work and makes this effort easier to review.
>
> Tested builds on arm64 and x86-64 in Yocto on 7.2-rc5
>
> [1] https://lore.kernel.org/all/cover.1780048925.git.u.kleine-koenig@baylibre.com/
>
> Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
> ---
> Pawel Zalewski (The Capable Hub) (9):
> ACPI: use a named initializer for acpi_device_id
> ACPI: drop unused assignment of acpi_device_id::driver_data
> ACPI: pci: drop unused assignment of acpi_device_id::driver_data
> ACPI: ghes-nvidia: use a named initializer for acpi_device_id::id
> ACPI: amba: drop unused assignment of acpi_device_id::driver_data
> ACPI: dptf: drop unused assignment of acpi_device_id::driver_data
> ACPI: nfit: core: drop unused assignment of acpi_device_id::driver_data
> ACPI: x86: use a named initializer for acpi_device_id::id
> ACPI: use a named initializer for acpi_device_id::id
>
> drivers/acpi/ac.c | 4 +-
> drivers/acpi/acpi_apd.c | 42 ++--
> drivers/acpi/acpi_memhotplug.c | 4 +-
> drivers/acpi/acpi_pad.c | 4 +-
> drivers/acpi/acpi_platform.c | 13 +-
> drivers/acpi/acpi_pnp.c | 514 +++++++++++++++++++-------------------
> drivers/acpi/acpi_processor.c | 8 +-
> drivers/acpi/acpi_tad.c | 4 +-
> drivers/acpi/acpi_video.c | 2 +-
> drivers/acpi/apei/ghes-nvidia.c | 2 +-
> drivers/acpi/arm64/amba.c | 6 +-
> drivers/acpi/battery.c | 8 +-
> drivers/acpi/button.c | 12 +-
> drivers/acpi/container.c | 8 +-
> drivers/acpi/dptf/dptf_pch_fivr.c | 14 +-
> drivers/acpi/dptf/dptf_power.c | 38 +--
> drivers/acpi/ec.c | 6 +-
> drivers/acpi/evged.c | 4 +-
> drivers/acpi/fan_core.c | 2 +-
> drivers/acpi/hed.c | 4 +-
> drivers/acpi/nfit/core.c | 4 +-
> drivers/acpi/pci_link.c | 4 +-
> drivers/acpi/pci_root.c | 4 +-
> drivers/acpi/pfr_telemetry.c | 4 +-
> drivers/acpi/pfr_update.c | 4 +-
> drivers/acpi/processor_driver.c | 6 +-
> drivers/acpi/sbs.c | 4 +-
> drivers/acpi/sbshc.c | 6 +-
> drivers/acpi/scan.c | 46 ++--
> drivers/acpi/thermal.c | 4 +-
> drivers/acpi/tiny-power-button.c | 6 +-
> drivers/acpi/video_detect.c | 4 +-
> drivers/acpi/x86/cmos_rtc.c | 2 +-
> drivers/acpi/x86/lpss.c | 54 ++--
> drivers/acpi/x86/s2idle.c | 14 +-
> drivers/acpi/x86/utils.c | 16 +-
> include/linux/acpi.h | 8 +-
> 37 files changed, 443 insertions(+), 446 deletions(-)
> ---
So we can talk about this after 7.3-rc1 is out.
Thanks!
^ permalink raw reply
* Re: [v2 2/2] soc: fsl: dpio: Use scope-based resource management in dpaa2_io_create()
From: Markus Elfring @ 2026-07-27 12:14 UTC (permalink / raw)
To: Dan Carpenter, linux-arm-kernel, linuxppc-dev
Cc: Christophe Leroy, Ioana Ciornei, Roy Pledge, LKML,
kernel-janitors
In-Reply-To: <amdB2K43gRBDhBPI@stanley.mountain>
>> Scope-based resource management became supported for some
>> programming interfaces by contributions of Peter Zijlstra on 2023-05-26.
>> See also the commit 54da6a0924311c7cf5015533991e44fb8eb12773 ("locking:
>> Introduce __cleanup() based infrastructure").
>>
>> * Thus use the attribute “__free(kfree)”.
>>
>> * Omit two kfree() calls accordingly.
>>
>> * Reduce the scopes for the local variables “obj”
>> and “qman_256_cycles_per_ns”.
>
> Why? No one does this except bcachefs and that was removed.
Have you still got development difficulties with scope reductions for
selected local variables?
https://elixir.bootlin.com/linux/v7.2-rc4/source/include/linux/cleanup.h#L142-L146
Regards,
Markus
^ permalink raw reply
* [PATCH 8/9] ACPI: x86: use a named initializer for acpi_device_id::id
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
Use a named initializer for the acpi_device_id::id field for
readability. Also drop setting the list terminator fields
explicitly and unify the type of the list terminator to be
a single space between the brackets.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/x86/cmos_rtc.c | 2 +-
drivers/acpi/x86/lpss.c | 54 ++++++++++++++++++++++-----------------------
drivers/acpi/x86/s2idle.c | 14 ++++++------
drivers/acpi/x86/utils.c | 16 +++++++-------
4 files changed, 43 insertions(+), 43 deletions(-)
diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c
index ced334e19896..d9891b00d090 100644
--- a/drivers/acpi/x86/cmos_rtc.c
+++ b/drivers/acpi/x86/cmos_rtc.c
@@ -18,7 +18,7 @@
#include "../internal.h"
static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
- { "ACPI000E", 1 }, /* ACPI Time and Alarm Device (TAD) */
+ { .id = "ACPI000E", .driver_data = 1 }, /* ACPI Time and Alarm Device (TAD) */
ACPI_CMOS_RTC_IDS
};
diff --git a/drivers/acpi/x86/lpss.c b/drivers/acpi/x86/lpss.c
index 0171eef00484..50b6db40bb18 100644
--- a/drivers/acpi/x86/lpss.c
+++ b/drivers/acpi/x86/lpss.c
@@ -351,41 +351,41 @@ static const struct x86_cpu_id lpss_cpu_ids[] = {
static const struct acpi_device_id acpi_lpss_device_ids[] = {
/* Generic LPSS devices */
- { "INTL9C60", LPSS_ADDR(lpss_dma_desc) },
+ { .id = "INTL9C60", .driver_data = LPSS_ADDR(lpss_dma_desc) },
/* Lynxpoint LPSS devices */
- { "INT33C0", LPSS_ADDR(lpt_spi_dev_desc) },
- { "INT33C1", LPSS_ADDR(lpt_spi_dev_desc) },
- { "INT33C2", LPSS_ADDR(lpt_i2c_dev_desc) },
- { "INT33C3", LPSS_ADDR(lpt_i2c_dev_desc) },
- { "INT33C4", LPSS_ADDR(lpt_uart_dev_desc) },
- { "INT33C5", LPSS_ADDR(lpt_uart_dev_desc) },
- { "INT33C6", LPSS_ADDR(lpt_sdio_dev_desc) },
+ { .id = "INT33C0", .driver_data = LPSS_ADDR(lpt_spi_dev_desc) },
+ { .id = "INT33C1", .driver_data = LPSS_ADDR(lpt_spi_dev_desc) },
+ { .id = "INT33C2", .driver_data = LPSS_ADDR(lpt_i2c_dev_desc) },
+ { .id = "INT33C3", .driver_data = LPSS_ADDR(lpt_i2c_dev_desc) },
+ { .id = "INT33C4", .driver_data = LPSS_ADDR(lpt_uart_dev_desc) },
+ { .id = "INT33C5", .driver_data = LPSS_ADDR(lpt_uart_dev_desc) },
+ { .id = "INT33C6", .driver_data = LPSS_ADDR(lpt_sdio_dev_desc) },
/* BayTrail LPSS devices */
- { "80860F09", LPSS_ADDR(byt_pwm_dev_desc) },
- { "80860F0A", LPSS_ADDR(byt_uart_dev_desc) },
- { "80860F0E", LPSS_ADDR(byt_spi_dev_desc) },
- { "80860F14", LPSS_ADDR(byt_sdio_dev_desc) },
- { "80860F41", LPSS_ADDR(byt_i2c_dev_desc) },
+ { .id = "80860F09", .driver_data = LPSS_ADDR(byt_pwm_dev_desc) },
+ { .id = "80860F0A", .driver_data = LPSS_ADDR(byt_uart_dev_desc) },
+ { .id = "80860F0E", .driver_data = LPSS_ADDR(byt_spi_dev_desc) },
+ { .id = "80860F14", .driver_data = LPSS_ADDR(byt_sdio_dev_desc) },
+ { .id = "80860F41", .driver_data = LPSS_ADDR(byt_i2c_dev_desc) },
/* Braswell LPSS devices */
- { "80862286", LPSS_ADDR(lpss_dma_desc) },
- { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
- { "80862289", LPSS_ADDR(bsw_pwm2_dev_desc) },
- { "8086228A", LPSS_ADDR(bsw_uart_dev_desc) },
- { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
- { "808622C0", LPSS_ADDR(lpss_dma_desc) },
- { "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) },
+ { .id = "80862286", .driver_data = LPSS_ADDR(lpss_dma_desc) },
+ { .id = "80862288", .driver_data = LPSS_ADDR(bsw_pwm_dev_desc) },
+ { .id = "80862289", .driver_data = LPSS_ADDR(bsw_pwm2_dev_desc) },
+ { .id = "8086228A", .driver_data = LPSS_ADDR(bsw_uart_dev_desc) },
+ { .id = "8086228E", .driver_data = LPSS_ADDR(bsw_spi_dev_desc) },
+ { .id = "808622C0", .driver_data = LPSS_ADDR(lpss_dma_desc) },
+ { .id = "808622C1", .driver_data = LPSS_ADDR(bsw_i2c_dev_desc) },
/* Broadwell LPSS devices */
- { "INT3430", LPSS_ADDR(lpt_spi_dev_desc) },
- { "INT3431", LPSS_ADDR(lpt_spi_dev_desc) },
- { "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) },
- { "INT3433", LPSS_ADDR(lpt_i2c_dev_desc) },
- { "INT3434", LPSS_ADDR(lpt_uart_dev_desc) },
- { "INT3435", LPSS_ADDR(lpt_uart_dev_desc) },
- { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) },
+ { .id = "INT3430", .driver_data = LPSS_ADDR(lpt_spi_dev_desc) },
+ { .id = "INT3431", .driver_data = LPSS_ADDR(lpt_spi_dev_desc) },
+ { .id = "INT3432", .driver_data = LPSS_ADDR(lpt_i2c_dev_desc) },
+ { .id = "INT3433", .driver_data = LPSS_ADDR(lpt_i2c_dev_desc) },
+ { .id = "INT3434", .driver_data = LPSS_ADDR(lpt_uart_dev_desc) },
+ { .id = "INT3435", .driver_data = LPSS_ADDR(lpt_uart_dev_desc) },
+ { .id = "INT3436", .driver_data = LPSS_ADDR(lpt_sdio_dev_desc) },
{ }
};
diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
index b6b1dd76a06b..64c4e10e71a1 100644
--- a/drivers/acpi/x86/s2idle.c
+++ b/drivers/acpi/x86/s2idle.c
@@ -33,8 +33,8 @@ module_param(check_lps0_constraints, bool, 0644);
MODULE_PARM_DESC(check_lps0_constraints, "Check LPS0 device constraints");
static const struct acpi_device_id lps0_device_ids[] = {
- {"PNP0D80", },
- {"", },
+ { .id = "PNP0D80" },
+ { }
};
/* Microsoft platform agnostic UUID */
@@ -431,11 +431,11 @@ static const struct amd_lps0_hid_device_data amd_cezanne = {
};
static const struct acpi_device_id amd_hid_ids[] = {
- {"AMD0004", (kernel_ulong_t)&amd_picasso, },
- {"AMD0005", (kernel_ulong_t)&amd_picasso, },
- {"AMDI0005", (kernel_ulong_t)&amd_picasso, },
- {"AMDI0006", (kernel_ulong_t)&amd_cezanne, },
- {}
+ { .id = "AMD0004", .driver_data = (kernel_ulong_t)&amd_picasso },
+ { .id = "AMD0005", .driver_data = (kernel_ulong_t)&amd_picasso },
+ { .id = "AMDI0005", .driver_data = (kernel_ulong_t)&amd_picasso },
+ { .id = "AMDI0006", .driver_data = (kernel_ulong_t)&amd_cezanne },
+ { }
};
static int lps0_device_attach(struct acpi_device *adev,
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index 418951639f51..35580d77d8af 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -463,14 +463,14 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
- { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
- { "10EC5651", 0 }, /* RealTek ALC5651 audio codec */
- { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
- { "INT33F5", 0 }, /* TI Dollar Cove PMIC */
- { "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
- { "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */
- { "NPCE69A", 0 }, /* Asus Transformer keyboard dock */
- {}
+ { .id = "10EC5640" }, /* RealTek ALC5640 audio codec */
+ { .id = "10EC5651" }, /* RealTek ALC5651 audio codec */
+ { .id = "INT33F4" }, /* X-Powers AXP288 PMIC */
+ { .id = "INT33F5" }, /* TI Dollar Cove PMIC */
+ { .id = "INT33FD" }, /* Intel Crystal Cove PMIC */
+ { .id = "INT34D3" }, /* Intel Whiskey Cove PMIC */
+ { .id = "NPCE69A" }, /* Asus Transformer keyboard dock */
+ { }
};
bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
--
2.43.0
^ permalink raw reply related
* [PATCH 9/9] ACPI: use a named initializer for acpi_device_id::id
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
Use a named initializer for the acpi_device_id::id field for
readability and drop setting the list terminator fields
explicitly as well to be consistent with the rest of the kernel
code.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
include/linux/acpi.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 60ab50cb8930..b34b483d99f5 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -805,10 +805,10 @@ int acpi_mrrm_max_mem_region(void);
#endif
#define ACPI_CMOS_RTC_IDS \
- { "PNP0B00", }, \
- { "PNP0B01", }, \
- { "PNP0B02", }, \
- { "", }
+ { .id = "PNP0B00" }, \
+ { .id = "PNP0B01" }, \
+ { .id = "PNP0B02" }, \
+ { }
extern bool cmos_rtc_platform_device_present;
--
2.43.0
^ permalink raw reply related
* [PATCH 7/9] ACPI: nfit: core: drop unused assignment of acpi_device_id::driver_data
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
This module sets the acpi_device_id::driver_data to 0 but
the field is not actually used within the module, we can
just drop it from the table.
While we are at it - used a named initializer for the
acpi_device_id::id field to increase readability and
drop explicitly setting the list terminator fields.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/nfit/core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index cb771d9cadb2..5732df5d53f0 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -3515,8 +3515,8 @@ void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event)
EXPORT_SYMBOL_GPL(__acpi_nfit_notify);
static const struct acpi_device_id acpi_nfit_ids[] = {
- { "ACPI0012", 0 },
- { "", 0 },
+ { .id = "ACPI0012" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, acpi_nfit_ids);
--
2.43.0
^ permalink raw reply related
* [PATCH 6/9] ACPI: dptf: drop unused assignment of acpi_device_id::driver_data
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
These modules set the acpi_device_id::driver_data to 0 but
the field is not actually used within the module, we can
just drop it from the table.
While we are at it - used a named initializer for the
acpi_device_id::id field to increase readability and
drop explicitly setting the list terminator fields.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/dptf/dptf_pch_fivr.c | 14 +++++++-------
drivers/acpi/dptf/dptf_power.c | 38 +++++++++++++++++++-------------------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/drivers/acpi/dptf/dptf_pch_fivr.c b/drivers/acpi/dptf/dptf_pch_fivr.c
index 8d7e555929d3..d23867f70b28 100644
--- a/drivers/acpi/dptf/dptf_pch_fivr.c
+++ b/drivers/acpi/dptf/dptf_pch_fivr.c
@@ -147,13 +147,13 @@ static void pch_fivr_remove(struct platform_device *pdev)
}
static const struct acpi_device_id pch_fivr_device_ids[] = {
- {"INTC1045", 0},
- {"INTC1049", 0},
- {"INTC1064", 0},
- {"INTC106B", 0},
- {"INTC10A3", 0},
- {"INTC10D7", 0},
- {"", 0},
+ { .id = "INTC1045" },
+ { .id = "INTC1049" },
+ { .id = "INTC1064" },
+ { .id = "INTC106B" },
+ { .id = "INTC10A3" },
+ { .id = "INTC10D7" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, pch_fivr_device_ids);
diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c
index 55ccbb8ddbe3..065831bce8c0 100644
--- a/drivers/acpi/dptf/dptf_power.c
+++ b/drivers/acpi/dptf/dptf_power.c
@@ -224,25 +224,25 @@ static void dptf_power_remove(struct platform_device *pdev)
}
static const struct acpi_device_id int3407_device_ids[] = {
- {"INT3407", 0},
- {"INT3532", 0},
- {"INTC1047", 0},
- {"INTC1050", 0},
- {"INTC1060", 0},
- {"INTC1061", 0},
- {"INTC1065", 0},
- {"INTC1066", 0},
- {"INTC106C", 0},
- {"INTC106D", 0},
- {"INTC10A4", 0},
- {"INTC10A5", 0},
- {"INTC10D8", 0},
- {"INTC10D9", 0},
- {"INTC1100", 0},
- {"INTC1101", 0},
- {"INTC10F7", 0},
- {"INTC10F8", 0},
- {"", 0},
+ { .id = "INT3407" },
+ { .id = "INT3532" },
+ { .id = "INTC1047" },
+ { .id = "INTC1050" },
+ { .id = "INTC1060" },
+ { .id = "INTC1061" },
+ { .id = "INTC1065" },
+ { .id = "INTC1066" },
+ { .id = "INTC106C" },
+ { .id = "INTC106D" },
+ { .id = "INTC10A4" },
+ { .id = "INTC10A5" },
+ { .id = "INTC10D8" },
+ { .id = "INTC10D9" },
+ { .id = "INTC1100" },
+ { .id = "INTC1101" },
+ { .id = "INTC10F7" },
+ { .id = "INTC10F8" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, int3407_device_ids);
--
2.43.0
^ permalink raw reply related
* [PATCH 5/9] ACPI: amba: drop unused assignment of acpi_device_id::driver_data
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
This module sets the acpi_device_id::driver_data to 0 but
the field is not actually used within the module, we can
just drop it from the table.
While we are at it - used a named initializer for the
acpi_device_id::id field to increase readability and
drop explicitly setting the list terminator fields.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/arm64/amba.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/arm64/amba.c b/drivers/acpi/arm64/amba.c
index 1350083bce5f..e32b37a2126d 100644
--- a/drivers/acpi/arm64/amba.c
+++ b/drivers/acpi/arm64/amba.c
@@ -20,9 +20,9 @@
#include "init.h"
static const struct acpi_device_id amba_id_list[] = {
- {"ARMH0061", 0}, /* PL061 GPIO Device */
- {"ARMH0330", 0}, /* ARM DMA Controller DMA-330 */
- {"", 0},
+ { .id = "ARMH0061" }, /* PL061 GPIO Device */
+ { .id = "ARMH0330" }, /* ARM DMA Controller DMA-330 */
+ { }
};
static void amba_register_dummy_clk(void)
--
2.43.0
^ permalink raw reply related
* [PATCH 3/9] ACPI: pci: drop unused assignment of acpi_device_id::driver_data
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
These modules set the acpi_device_id::driver_data to 0 but
the field is not actually used within the module, we can
just drop it from the table.
While we are at it - used a named initializer for the
acpi_device_id::id field to increase readability and
drop explicitly setting the list terminator fields.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/pci_link.c | 4 ++--
drivers/acpi/pci_root.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index e6ed13aee48d..276dd36aaf23 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -36,8 +36,8 @@ static int acpi_pci_link_add(struct acpi_device *device,
static void acpi_pci_link_remove(struct acpi_device *device);
static const struct acpi_device_id link_device_ids[] = {
- {"PNP0C0F", 0},
- {"", 0},
+ { .id = "PNP0C0F" },
+ { }
};
static struct acpi_scan_handler pci_link_handler = {
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 4c06c3ffd0cb..a129cb0c0a36 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -40,8 +40,8 @@ static int acpi_pci_root_scan_dependent(struct acpi_device *adev)
| OSC_PCI_MSI_SUPPORT)
static const struct acpi_device_id root_device_ids[] = {
- {"PNP0A03", 0},
- {"", 0},
+ { .id = "PNP0A03" },
+ { }
};
static struct acpi_scan_handler pci_root_handler = {
--
2.43.0
^ permalink raw reply related
* [PATCH 2/9] ACPI: drop unused assignment of acpi_device_id::driver_data
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
These modules set the acpi_device_id::driver_data to 0 but
the field is not actually used within the module, we can
just drop it from the table.
While we are at it - use a named initializer for the
acpi_device_id fields and drop setting the list
terminator fields explicitly as well.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/ac.c | 4 ++--
drivers/acpi/acpi_memhotplug.c | 4 ++--
drivers/acpi/acpi_pad.c | 4 ++--
drivers/acpi/acpi_tad.c | 4 ++--
drivers/acpi/battery.c | 8 +++-----
drivers/acpi/container.c | 8 ++++----
drivers/acpi/ec.c | 6 +++---
drivers/acpi/hed.c | 4 ++--
drivers/acpi/processor_driver.c | 6 +++---
drivers/acpi/sbs.c | 4 ++--
drivers/acpi/sbshc.c | 6 +++---
drivers/acpi/thermal.c | 4 ++--
drivers/acpi/tiny-power-button.c | 6 +++---
drivers/acpi/video_detect.c | 4 ++--
14 files changed, 35 insertions(+), 37 deletions(-)
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index f19d6dd43473..d6f162fe7ea4 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -32,8 +32,8 @@ MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");
static const struct acpi_device_id ac_device_ids[] = {
- {"ACPI0003", 0},
- {"", 0},
+ {.id = "ACPI0003" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 1d7dfe4ee9a6..cf27765ed4d7 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -21,8 +21,8 @@
#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
static const struct acpi_device_id memory_device_ids[] = {
- {ACPI_MEMORY_DEVICE_HID, 0},
- {"", 0},
+ { .id = ACPI_MEMORY_DEVICE_HID },
+ { }
};
#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index dc6d0091d17c..9af3b8bce686 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -438,8 +438,8 @@ static void acpi_pad_remove(struct platform_device *pdev)
}
static const struct acpi_device_id pad_device_ids[] = {
- {"ACPI000C", 0},
- {"", 0},
+ { .id = "ACPI000C" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, pad_device_ids);
diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c
index fc43df083738..7a2a5167e8ec 100644
--- a/drivers/acpi/acpi_tad.c
+++ b/drivers/acpi/acpi_tad.c
@@ -885,8 +885,8 @@ static int acpi_tad_probe(struct platform_device *pdev)
}
static const struct acpi_device_id acpi_tad_ids[] = {
- {"ACPI000E", 0},
- {}
+ { .id = "ACPI000E" },
+ { }
};
static struct platform_driver acpi_tad_driver = {
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index f5e0eb299610..30b42967e625 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -56,12 +56,10 @@ module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
static const struct acpi_device_id battery_device_ids[] = {
- {"PNP0C0A", 0},
-
+ { .id = "PNP0C0A"},
/* Microsoft Surface Go 3 */
- {"MSHW0146", 0},
-
- {"", 0},
+ { .id = "MSHW0146"},
+ { }
};
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index f138a433554a..9997915233e1 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -15,10 +15,10 @@
#include "internal.h"
static const struct acpi_device_id container_device_ids[] = {
- {"ACPI0004", 0},
- {"PNP0A05", 0},
- {"PNP0A06", 0},
- {"", 0},
+ { .id = "ACPI0004" },
+ { .id = "PNP0A05" },
+ { .id = "PNP0A06" },
+ { }
};
#ifdef CONFIG_ACPI_CONTAINER
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 64ad4cfa6208..fd62a455db2a 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1794,9 +1794,9 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
}
static const struct acpi_device_id ec_device_ids[] = {
- {"PNP0C09", 0},
- {ACPI_ECDT_HID, 0},
- {"", 0},
+ { .id = "PNP0C09" },
+ { .id = ACPI_ECDT_HID },
+ { }
};
/*
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index 48562f53d3ab..6789ec567d21 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -17,8 +17,8 @@
#include <acpi/hed.h>
static const struct acpi_device_id acpi_hed_ids[] = {
- {"PNP0C33", 0},
- {"", 0},
+ { .id = "PNP0C33" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, acpi_hed_ids);
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index cda8fd720000..c11cd0e3367f 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -36,9 +36,9 @@ MODULE_LICENSE("GPL");
static int acpi_processor_stop(struct device *dev);
static const struct acpi_device_id processor_device_ids[] = {
- {ACPI_PROCESSOR_OBJECT_HID, 0},
- {ACPI_PROCESSOR_DEVICE_HID, 0},
- {"", 0},
+ { .id = ACPI_PROCESSOR_OBJECT_HID },
+ { .id = ACPI_PROCESSOR_DEVICE_HID },
+ { }
};
MODULE_DEVICE_TABLE(acpi, processor_device_ids);
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 86b7c7975852..354304c2c307 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -45,8 +45,8 @@ MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
#define ACPI_SBS_BLOCK_MAX 32
static const struct acpi_device_id sbs_device_ids[] = {
- {"ACPI0002", 0},
- {"", 0},
+ { .id = "ACPI0002" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index c0ffa267f96c..ac628212c048 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -33,9 +33,9 @@ static int acpi_smbus_hc_probe(struct platform_device *pdev);
static void acpi_smbus_hc_remove(struct platform_device *pdev);
static const struct acpi_device_id sbs_device_ids[] = {
- {"ACPI0001", 0},
- {"ACPI0005", 0},
- {"", 0},
+ { .id = "ACPI0001" },
+ { .id = "ACPI0005" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index dd7666c176a0..189011733956 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -920,8 +920,8 @@ static const struct dev_pm_ops acpi_thermal_pm_ops = {
#endif /* CONFIG_PM_SLEEP */
static const struct acpi_device_id thermal_device_ids[] = {
- {ACPI_THERMAL_HID, 0},
- {"", 0},
+ { .id = ACPI_THERMAL_HID },
+ { }
};
MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
diff --git a/drivers/acpi/tiny-power-button.c b/drivers/acpi/tiny-power-button.c
index 92516ef84b02..5acb53090ff3 100644
--- a/drivers/acpi/tiny-power-button.c
+++ b/drivers/acpi/tiny-power-button.c
@@ -14,9 +14,9 @@ module_param(power_signal, int, 0644);
MODULE_PARM_DESC(power_signal, "Power button sends this signal to init");
static const struct acpi_device_id tiny_power_button_device_ids[] = {
- { ACPI_BUTTON_HID_POWER, 0 },
- { ACPI_BUTTON_HID_POWERF, 0 },
- { "", 0 },
+ { .id = ACPI_BUTTON_HID_POWER },
+ { .id = ACPI_BUTTON_HID_POWERF },
+ { }
};
MODULE_DEVICE_TABLE(acpi, tiny_power_button_device_ids);
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 458efa4fe9d4..e135f29d4093 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -68,8 +68,8 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
struct pci_dev *dev;
static const struct acpi_device_id video_ids[] = {
- {ACPI_VIDEO_HID, 0},
- {"", 0},
+ { .id = ACPI_VIDEO_HID },
+ { }
};
if (acpi_dev && !acpi_match_device_ids(acpi_dev, video_ids)) {
--
2.43.0
^ permalink raw reply related
* [PATCH 0/9] ACPI: use named initializers for acpi_device_id
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
This series is converting lists that contain the acpi_device_id
struct, which is defined in the include/linux/device-id/acpi.h
to makes use of named initializers (which they do not use currently).
This work is part of the on going effort in the kernel associated
with device-ids [1]
The plan is to convert acpi_device_id::driver_data to have an anonymous
union, similarly to what was introduced for PCI and I2C device ID tables.
The goal is to increase type-safety (as most of the existing casts are gone),
to improve readability and to make use intent a bit more clear:
```
union {
kernel_ulong_t driver_data;
const void *driver_data_ptr;
}
```
But for that to work all lists containing the structs need to use named
initializers first. I already have patches that implement this and touching
a lot of kernel subsystmes that use the acpi_device_id struct and that list
keeps on growing. Therefore, I have decided to split the series per every
subsystem into:
- pre-clean-ups that convert the lists to use named initializers
- actual implementations that make some of the modules use the new driver_data_ptr
That way the task can be fragmented into manageable and independent
chunks of work and makes this effort easier to review.
Tested builds on arm64 and x86-64 in Yocto on 7.2-rc5
[1] https://lore.kernel.org/all/cover.1780048925.git.u.kleine-koenig@baylibre.com/
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
Pawel Zalewski (The Capable Hub) (9):
ACPI: use a named initializer for acpi_device_id
ACPI: drop unused assignment of acpi_device_id::driver_data
ACPI: pci: drop unused assignment of acpi_device_id::driver_data
ACPI: ghes-nvidia: use a named initializer for acpi_device_id::id
ACPI: amba: drop unused assignment of acpi_device_id::driver_data
ACPI: dptf: drop unused assignment of acpi_device_id::driver_data
ACPI: nfit: core: drop unused assignment of acpi_device_id::driver_data
ACPI: x86: use a named initializer for acpi_device_id::id
ACPI: use a named initializer for acpi_device_id::id
drivers/acpi/ac.c | 4 +-
drivers/acpi/acpi_apd.c | 42 ++--
drivers/acpi/acpi_memhotplug.c | 4 +-
drivers/acpi/acpi_pad.c | 4 +-
drivers/acpi/acpi_platform.c | 13 +-
drivers/acpi/acpi_pnp.c | 514 +++++++++++++++++++-------------------
drivers/acpi/acpi_processor.c | 8 +-
drivers/acpi/acpi_tad.c | 4 +-
drivers/acpi/acpi_video.c | 2 +-
drivers/acpi/apei/ghes-nvidia.c | 2 +-
drivers/acpi/arm64/amba.c | 6 +-
drivers/acpi/battery.c | 8 +-
drivers/acpi/button.c | 12 +-
drivers/acpi/container.c | 8 +-
drivers/acpi/dptf/dptf_pch_fivr.c | 14 +-
drivers/acpi/dptf/dptf_power.c | 38 +--
drivers/acpi/ec.c | 6 +-
drivers/acpi/evged.c | 4 +-
drivers/acpi/fan_core.c | 2 +-
drivers/acpi/hed.c | 4 +-
drivers/acpi/nfit/core.c | 4 +-
drivers/acpi/pci_link.c | 4 +-
drivers/acpi/pci_root.c | 4 +-
drivers/acpi/pfr_telemetry.c | 4 +-
drivers/acpi/pfr_update.c | 4 +-
drivers/acpi/processor_driver.c | 6 +-
drivers/acpi/sbs.c | 4 +-
drivers/acpi/sbshc.c | 6 +-
drivers/acpi/scan.c | 46 ++--
drivers/acpi/thermal.c | 4 +-
drivers/acpi/tiny-power-button.c | 6 +-
drivers/acpi/video_detect.c | 4 +-
drivers/acpi/x86/cmos_rtc.c | 2 +-
drivers/acpi/x86/lpss.c | 54 ++--
drivers/acpi/x86/s2idle.c | 14 +-
drivers/acpi/x86/utils.c | 16 +-
include/linux/acpi.h | 8 +-
37 files changed, 443 insertions(+), 446 deletions(-)
---
base-commit: 48a5a7ab8d6ab7090564339e039c421f315de912
change-id: 20260724-acpi-refactor-f4efc2f44203
Best regards,
--
Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
^ permalink raw reply
* Re: [PATCH v2 2/2] soc: fsl: dpio: Use scope-based resource management in dpaa2_io_create()
From: Ioana Ciornei @ 2026-07-27 12:09 UTC (permalink / raw)
To: Markus Elfring
Cc: linux-arm-kernel, linuxppc-dev, Christophe Leroy, Roy Pledge,
LKML, kernel-janitors
In-Reply-To: <f47abd6e-9337-404c-a24f-39a9dd7454d2@web.de>
On Mon, Jul 06, 2026 at 12:40:09PM +0200, Markus Elfring wrote:
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Mon, 6 Jul 2026 11:18:39 +0200
>
> Scope-based resource management became supported for some
> programming interfaces by contributions of Peter Zijlstra on 2023-05-26.
> See also the commit 54da6a0924311c7cf5015533991e44fb8eb12773 ("locking:
> Introduce __cleanup() based infrastructure").
>
> * Thus use the attribute “__free(kfree)”.
>
> * Omit two kfree() calls accordingly.
>
> * Reduce the scopes for the local variables “obj”
> and “qman_256_cycles_per_ns”.
Remove these changes. All variables should be defined at the start of
the function, especially since there is no strong reason not to.
Ioana
^ permalink raw reply
* Re: [PATCH v2 1/2] soc: fsl: dpio: Use scope-based resource management in dpaa2_io_store_create()
From: Ioana Ciornei @ 2026-07-27 12:08 UTC (permalink / raw)
To: Markus Elfring
Cc: linux-arm-kernel, linuxppc-dev, Christophe Leroy, Roy Pledge,
LKML, kernel-janitors
In-Reply-To: <6607bb4e-a747-4791-b93f-f82f26e4a334@web.de>
On Mon, Jul 06, 2026 at 12:38:08PM +0200, Markus Elfring wrote:
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Mon, 6 Jul 2026 10:34:43 +0200
>
> Scope-based resource management became supported for some
> programming interfaces by contributions of Peter Zijlstra on 2023-05-26.
> See also the commit 54da6a0924311c7cf5015533991e44fb8eb12773 ("locking:
> Introduce __cleanup() based infrastructure").
>
> * Thus use the attribute “__free(kfree)”.
>
> * Reduce the scope for the local variable “ret”.
Please don't. Let all the variables be defined at the start of each
function.
>
> * Omit two kfree() calls accordingly.
>
> * Omit the local variable “size” (for another memory allocation).
Please remove this change, not related to the intention of the patch.
Ioana
^ permalink raw reply
* [PATCH net-next v2] net: phylink: add phylink_pcs_loopback() method for PCS loopback support
From: Zxyan Zhu @ 2026-07-27 12:07 UTC (permalink / raw)
To: andrew+netdev, rmk+kernel, alexandre.torgue
Cc: davem, edumazet, kuba, pabeni, hkallweit1, mcoquelin.stm32,
maxime.chevallier, netdev, linux-stm32, linux-arm-kernel,
linux-kernel, Zxyan Zhu
Some Ethernet MAC drivers (such as stmmac) need to perform PCS-level
loopback for selftest purposes when no external PHY is present. Add a
new phylink_pcs_loopback() method that allows MAC drivers to request
PCS loopback mode through the phylink framework.
Implement the pcs_loopback callback in the stmmac integrated PCS
using the GMAC_AN_CTRL_ELE register bit. Add a helper function
stmmac_selftest_get_pcs() in stmmac selftests to unify PCS lookup
across glue driver PCS and integrated PCS. Update the selftest
enable/disable paths to use the new helper.
Signed-off-by: Zxyan Zhu <zxyan0222@gmail.com>
---
.../net/ethernet/stmicro/stmmac/stmmac_pcs.c | 17 +++++++
.../stmicro/stmmac/stmmac_selftests.c | 51 ++++++++++++++++---
drivers/net/phy/phylink.c | 19 +++++++
include/linux/phylink.h | 16 ++++++
4 files changed, 95 insertions(+), 8 deletions(-)
v2:
- Implement pcs_loopback callback in stmmac integrated PCS using
GMAC_AN_CTRL_ELE register bit.
- Add stmmac_selftest_get_pcs() helper to unify PCS lookup across glue
driver PCS and integrated PCS.
- Add NULL check in phylink_pcs_loopback() wrapper.
v1: https://lore.kernel.org/netdev/20260724085224.3321663-1-zxyan0222@gmail.com/
Note on loopback direction:
The pcs_loopback callback uses a simple enable/disable boolean, matching
the existing phy_loopback() API. Direction is not needed at this level:
selftest loopback is always host-side (TX looped back to RX). The
future ethtool user-space loopback API can handle direction selection
at a higher layer.
Note on phylink_set_loopback() vs phylink_pcs_loopback():
This patch follows the same pattern as phy_loopback() - a direct
callback on the PCS object. Keeping the API minimal avoids introducing
a new phylink-level loopback abstraction with location enumeration
before Björn's ethtool loopback series lands upstream. Once that
series is merged, phylink_pcs_loopback() can serve as a building block
for a higher-level phylink_set_loopback() if needed.
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
index df37af5ab837..90a21a2f7e87 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
@@ -168,6 +168,22 @@ static void dwmac_integrated_pcs_an_restart(struct phylink_pcs *pcs)
}
}
+static int dwmac_integrated_pcs_loopback(struct phylink_pcs *pcs, bool enable)
+{
+ struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs);
+ void __iomem *an_control = spcs->base + GMAC_AN_CTRL(0);
+ u32 ctrl;
+
+ ctrl = readl(an_control);
+ if (enable)
+ ctrl |= GMAC_AN_CTRL_ELE;
+ else
+ ctrl &= ~GMAC_AN_CTRL_ELE;
+ writel(ctrl, an_control);
+
+ return 0;
+}
+
static const struct phylink_pcs_ops dwmac_integrated_pcs_ops = {
.pcs_inband_caps = dwmac_integrated_pcs_inband_caps,
.pcs_enable = dwmac_integrated_pcs_enable,
@@ -175,6 +191,7 @@ static const struct phylink_pcs_ops dwmac_integrated_pcs_ops = {
.pcs_get_state = dwmac_integrated_pcs_get_state,
.pcs_config = dwmac_integrated_pcs_config,
.pcs_an_restart = dwmac_integrated_pcs_an_restart,
+ .pcs_loopback = dwmac_integrated_pcs_loopback,
};
void stmmac_integrated_pcs_irq(struct stmmac_priv *priv, u32 status,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
index 29e824bd90ca..77a457b2fa5c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
@@ -19,6 +19,7 @@
#include <net/udp.h>
#include <net/tc_act/tc_gact.h>
#include "stmmac.h"
+#include "stmmac_pcs.h"
struct stmmachdr {
__be32 version;
@@ -374,23 +375,51 @@ static int stmmac_test_mac_loopback(struct stmmac_priv *priv)
return __stmmac_test_loopback(priv, &attr);
}
+static struct phylink_pcs *stmmac_selftest_get_pcs(struct stmmac_priv *priv)
+{
+ /* Try glue driver's PCS first, then the integrated PCS. */
+ if (priv->hw->phylink_pcs)
+ return priv->hw->phylink_pcs;
+
+ if (priv->integrated_pcs)
+ return &priv->integrated_pcs->pcs;
+
+ return NULL;
+}
+
static int stmmac_test_phy_loopback(struct stmmac_priv *priv)
{
struct stmmac_packet_attrs attr = { };
+ struct phylink_pcs *pcs;
int ret;
- if (!priv->dev->phydev)
- return -EOPNOTSUPP;
+ if (priv->dev->phydev) {
+ ret = phy_loopback(priv->dev->phydev, true, 0);
+ if (ret)
+ return ret;
- ret = phy_loopback(priv->dev->phydev, true, 0);
- if (ret)
+ attr.dst = priv->dev->dev_addr;
+ ret = __stmmac_test_loopback(priv, &attr);
+
+ phy_loopback(priv->dev->phydev, false, 0);
return ret;
+ }
- attr.dst = priv->dev->dev_addr;
- ret = __stmmac_test_loopback(priv, &attr);
+ /* Use PCS loopback for interfaces without an external PHY. */
+ pcs = stmmac_selftest_get_pcs(priv);
+ if (pcs) {
+ ret = phylink_pcs_loopback(pcs, true);
+ if (ret)
+ return ret;
- phy_loopback(priv->dev->phydev, false, 0);
- return ret;
+ attr.dst = priv->dev->dev_addr;
+ ret = __stmmac_test_loopback(priv, &attr);
+
+ phylink_pcs_loopback(pcs, false);
+ return ret;
+ }
+
+ return -EOPNOTSUPP;
}
static int stmmac_test_mmc(struct stmmac_priv *priv)
@@ -1986,6 +2015,9 @@ void stmmac_selftest_run(struct net_device *dev,
ret = -EOPNOTSUPP;
if (dev->phydev)
ret = phy_loopback(dev->phydev, true, 0);
+ else
+ ret = phylink_pcs_loopback(stmmac_selftest_get_pcs(priv),
+ true);
if (!ret)
break;
fallthrough;
@@ -2019,6 +2051,9 @@ void stmmac_selftest_run(struct net_device *dev,
ret = -EOPNOTSUPP;
if (dev->phydev)
ret = phy_loopback(dev->phydev, false, 0);
+ else
+ ret = phylink_pcs_loopback(stmmac_selftest_get_pcs(priv),
+ false);
if (!ret)
break;
fallthrough;
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 59dfe35afa54..69242caffaef 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -997,6 +997,25 @@ int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs)
}
EXPORT_SYMBOL_GPL(phylink_pcs_pre_init);
+/**
+ * phylink_pcs_loopback() - Enable or disable loopback at the PCS
+ * @pcs: a pointer to a &struct phylink_pcs.
+ * @enable: true to enable loopback, false to disable
+ *
+ * Enable or disable loopback mode at the PCS level. This is used by MAC
+ * drivers for selftest purposes when no external PHY is present.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+int phylink_pcs_loopback(struct phylink_pcs *pcs, bool enable)
+{
+ if (pcs && pcs->ops->pcs_loopback)
+ return pcs->ops->pcs_loopback(pcs, enable);
+
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(phylink_pcs_loopback);
+
static void phylink_mac_config(struct phylink *pl,
const struct phylink_link_state *state)
{
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 2bc0db3d52ac..66c7016d4acd 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -518,6 +518,7 @@ struct phylink_pcs {
* the MAC.
* @pcs_pre_init: configure PCS components necessary for MAC hardware
* initialization e.g. RX clock for stmmac.
+ * @pcs_loopback: enable/disable loopback mode at the PCS.
*/
struct phylink_pcs_ops {
int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
@@ -542,6 +543,7 @@ struct phylink_pcs_ops {
void (*pcs_disable_eee)(struct phylink_pcs *pcs);
void (*pcs_enable_eee)(struct phylink_pcs *pcs);
int (*pcs_pre_init)(struct phylink_pcs *pcs);
+ int (*pcs_loopback)(struct phylink_pcs *pcs, bool enable);
};
#if 0 /* For kernel-doc purposes only. */
@@ -717,8 +719,22 @@ void pcs_enable_eee(struct phylink_pcs *pcs);
*/
int pcs_pre_init(struct phylink_pcs *pcs);
+/**
+ * pcs_loopback() - Enable or disable loopback at the PCS
+ * @pcs: a pointer to a &struct phylink_pcs.
+ * @enable: true to enable loopback, false to disable
+ *
+ * Enable or disable loopback mode at the PCS level. This is used by MAC
+ * drivers for selftest purposes when no external PHY is present.
+ *
+ * Returns 0 on success, or a negative error code on failure.
+ */
+int pcs_loopback(struct phylink_pcs *pcs, bool enable);
+
#endif
+int phylink_pcs_loopback(struct phylink_pcs *pcs, bool enable);
+
struct phylink *phylink_create(struct phylink_config *,
const struct fwnode_handle *,
phy_interface_t,
base-commit: 1df10cef2d1e7f9f2fb7eddb67fc70d3abf101f9
--
2.34.1
^ permalink raw reply related
* [PATCH v3 2/2] iommu/arm-smmu-v3: Add HAFT support for SVA
From: Robin Murphy @ 2026-07-27 12:03 UTC (permalink / raw)
To: will, catalin.marinas, joro; +Cc: jpb, jgg, iommu, linux-arm-kernel
In-Reply-To: <cover.1785153415.git.robin.murphy@arm.com>
Since table access flags cannot be software-managed, if process
pagetables are using HAFT then SVA must require the SMMU to support and
enable it too, otherwise page aging is liable to get out of whack.
For unbinding, we can't disable HAFT atomically with HA as might be
desired, but luckily we can get away with just not disabling HA either.
Cc: <stable@vger.kernel.org>
Fixes: 62df5870ebf7 ("arm64: Enable ARCH_HAS_NONLEAF_PMD_YOUNG")
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
v3: Make all HTTU settings unconditional WRT mm.
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 24 +++++++++++--------
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 9 ++++++-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 +++
3 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 1ed8a6f29dc4..4cd60d3c450a 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -92,16 +92,6 @@ void arm_smmu_make_sva_cd(struct arm_smmu_cd *target,
target->data[1] = cpu_to_le64(virt_to_phys(mm->pgd) &
CTXDESC_CD_1_TTB0_MASK);
-
- /*
- * Enable Hardware Access and Dirty updates (DBM) if supported.
- * This is safe to enable by default, as PTE_WRITE and PTE_DBM
- * share the same bit.
- */
- if (master->smmu->features & ARM_SMMU_FEAT_HA)
- target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HA);
- if (master->smmu->features & ARM_SMMU_FEAT_HD)
- target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HD);
} else {
target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_EPD0);
@@ -114,6 +104,17 @@ void arm_smmu_make_sva_cd(struct arm_smmu_cd *target,
target->data[0] &=
cpu_to_le64(~(CTXDESC_CD_0_S | CTXDESC_CD_0_R));
}
+ /*
+ * Enable Hardware Access and Dirty updates (DBM) if supported. This is
+ * safe to enable by default, as PTE_WRITE and PTE_DBM share the same bit,
+ * while the EPD0 config can't get as far as fetching any PTEs anyway.
+ */
+ if (master->smmu->features & ARM_SMMU_FEAT_HA)
+ target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HA);
+ if (master->smmu->features & ARM_SMMU_FEAT_HD)
+ target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HD);
+ if (master->smmu->features & ARM_SMMU_FEAT_HAFT && system_supports_haft())
+ target->data[1] |= cpu_to_le64(CTXDESC_CD_1_HAFT);
/*
* MAIR value is pretty much constant and global, so we can just get it
@@ -211,6 +212,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
if (system_supports_bbml2_noabort())
feat_mask |= ARM_SMMU_FEAT_BBML2;
+ if (system_supports_haft())
+ feat_mask |= ARM_SMMU_FEAT_HAFT;
+
if ((smmu->features & feat_mask) != feat_mask)
return false;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index a10affb483a4..14e5b3f08962 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4921,10 +4921,14 @@ static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu)
static void arm_smmu_get_httu(struct arm_smmu_device *smmu, u32 reg)
{
- u32 fw_features = smmu->features & (ARM_SMMU_FEAT_HA | ARM_SMMU_FEAT_HD);
+ u32 fw_features = smmu->features & (ARM_SMMU_FEAT_HA | ARM_SMMU_FEAT_HD |
+ ARM_SMMU_FEAT_HAFT);
u32 hw_features = 0;
switch (FIELD_GET(IDR0_HTTU, reg)) {
+ case IDR0_HTTU_ACCESS_DIRTY_HAFT:
+ hw_features |= ARM_SMMU_FEAT_HAFT;
+ fallthrough;
case IDR0_HTTU_ACCESS_DIRTY:
hw_features |= ARM_SMMU_FEAT_HD;
fallthrough;
@@ -5256,6 +5260,9 @@ static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
smmu->features |= ARM_SMMU_FEAT_COHERENCY;
switch (FIELD_GET(ACPI_IORT_SMMU_V3_HTTU_OVERRIDE, iort_smmu->flags)) {
+ case IDR0_HTTU_ACCESS_DIRTY_HAFT:
+ smmu->features |= ARM_SMMU_FEAT_HAFT;
+ fallthrough;
case IDR0_HTTU_ACCESS_DIRTY:
smmu->features |= ARM_SMMU_FEAT_HD;
fallthrough;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index c909c9a88538..61a7df5afb99 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -40,6 +40,7 @@ struct arm_vsmmu;
#define IDR0_HTTU GENMASK(7, 6)
#define IDR0_HTTU_ACCESS 1
#define IDR0_HTTU_ACCESS_DIRTY 2
+#define IDR0_HTTU_ACCESS_DIRTY_HAFT 3
#define IDR0_COHACC (1 << 4)
#define IDR0_TTF GENMASK(3, 2)
#define IDR0_TTF_AARCH64 2
@@ -369,6 +370,7 @@ static inline unsigned int arm_smmu_cdtab_l2_idx(unsigned int ssid)
#define CTXDESC_CD_0_ASET (1UL << 47)
#define CTXDESC_CD_0_ASID GENMASK_ULL(63, 48)
+#define CTXDESC_CD_1_HAFT (1UL << 3)
#define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(51, 4)
/*
@@ -921,6 +923,7 @@ struct arm_smmu_device {
#define ARM_SMMU_FEAT_HD (1 << 22)
#define ARM_SMMU_FEAT_S2FWB (1 << 23)
#define ARM_SMMU_FEAT_BBML2 (1 << 24)
+#define ARM_SMMU_FEAT_HAFT (1 << 25)
u32 features;
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
--
2.54.0.dirty
^ permalink raw reply related
* [PATCH v3 1/2] arm64: Add override for MMFR1.HAFDBS
From: Robin Murphy @ 2026-07-27 12:03 UTC (permalink / raw)
To: will, catalin.marinas, joro; +Cc: jpb, jgg, iommu, linux-arm-kernel
In-Reply-To: <cover.1785153415.git.robin.murphy@arm.com>
In general it might be nice to have the ability to disable hardware
access/dirty bit management for debugging or performance comparison
purposes without having to rebuild the kernel. However once FEAT_HAFT
comes into the picture we also start to have a real functional concern
where the decision to use HAFT based on the boot CPUs can prevent SVA
or late-onlining if SMMUs/CPUs are later found to lack HAFT support.
To that end, add the appropriate MMFR1 override, with an easy "nohaft"
alias for the significant case, partly since the feature/field naming
isn't the most obvious, but also so it could potentially be redirected
in future if someone wanted to attempt a higher-level means of turning
off just HAFT usage independently from FEAT_HDBSS.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
v3: No change.
Documentation/admin-guide/kernel-parameters.txt | 3 +++
arch/arm64/kernel/pi/idreg-override.c | 2 ++
2 files changed, 5 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index b5493a7f8f22..7f23e5b8dc44 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -565,6 +565,9 @@ Kernel parameters
arm64.nogcs [ARM64] Unconditionally disable Guarded Control Stack
support
+ arm64.nohaft [ARM64] Unconditionally disable Hardware managed Access
+ Flag for Table descriptors support
+
arm64.nomops [ARM64] Unconditionally disable Memory Copy and Memory
Set instructions support
diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c
index bc57b290e5e7..0e051fec5afe 100644
--- a/arch/arm64/kernel/pi/idreg-override.c
+++ b/arch/arm64/kernel/pi/idreg-override.c
@@ -64,6 +64,7 @@ static const struct ftr_set_desc mmfr1 __prel64_initconst = {
.override = &id_aa64mmfr1_override,
.fields = {
FIELD("vh", ID_AA64MMFR1_EL1_VH_SHIFT, mmfr1_vh_filter),
+ FIELD("hafdbs", ID_AA64MMFR1_EL1_HAFDBS_SHIFT, NULL),
{}
},
};
@@ -246,6 +247,7 @@ static const struct {
{ "arm64.nomte", "id_aa64pfr1.mte=0" },
{ "nokaslr", "arm64_sw.nokaslr=1" },
{ "rodata=off", "arm64_sw.rodataoff=1" },
+ { "arm64.nohaft", "id_aa64mmfr1.hafdbs=2" },
{ "arm64.nolva", "id_aa64mmfr2.varange=0" },
{ "arm64.no32bit_el0", "id_aa64pfr0.el0=1" },
{ "arm64.nompam", "id_aa64pfr0.mpam=0 id_aa64pfr1.mpam_frac=0" },
--
2.54.0.dirty
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox