* [PATCH v5 3/8] arm64/runtime-const: Introduce runtime_const_mask_32()
From: K Prateek Nayak @ 2026-06-30 4:55 UTC (permalink / raw)
To: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
Sebastian Andrzej Siewior, Catalin Marinas, Will Deacon
Cc: Darren Hart, Davidlohr Bueso, André Almeida, linux-arch,
linux-kernel, Samuel Holland, Charlie Jenkins, K Prateek Nayak,
linux-arm-kernel, linux-riscv, linux-s390, Jisheng Zhang
In-Reply-To: <20260630045531.3939-1-kprateek.nayak@amd.com>
Futex hash computation requires a mask operation with read-only after
init data that will be converted to a runtime constant in the subsequent
commit.
Introduce runtime_const_mask_32 to further optimize the mask operation
in the futex hash computation hot path. Since all the current use-cases
are of the form GENMASK(n, 0), with n > 0, a single:
ubfx w0, w0, #0, #widthm1 // w0 = w0 [widthm1:0]
instruction is used for amd64 to improve instruction dinsity and
performance.
"Arm A-profile A64 Instruction Set Architecture" manual, Sec.
"A64 -- Base Instructions" [1] for UBFX instruction highlights the
immediate "width" is encoded as width minus 1 in imms (Bits [15:10])
which is patched by __runtime_fixup_mask() once the mask is known.
If a future use case arises that needs to tackle arbitrary mask,
consider using:
movz w1, #lo16, lsl #0
movk w1, #hi16, lsl #16
to patch the 32-bit mask in the asm block and return "__ret & (val)"
from runtime_const_mask_32() which allows compiler to further optimize
the logical and operation. __runtime_fixup_ptr() already patches a
"movz, + movk lsl #16" sequence which can be reused when the need
arises.
A possible implementation for this alternate scheme can be found at [2].
Assisted-by: Claude:claude-sonnet-4-6
Suggested-by: Samuel Holland <samuel.holland@sifive.com>
Suggested-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
Link: https://developer.arm.com/documentation/ddi0602/2026-03/Base-Instructions/ [1]
Link: https://lore.kernel.org/lkml/20260430094730.31624-4-kprateek.nayak@amd.com/ [2]
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
changelog v4..v5:
o Pivoted to using the UBFX instruction for masking since the futex
use-case use masks of form 2^n - 1 (n > 1) since there was enough
interest to improve instruction density for ARM64 and RISC-V.
(Charlie, Samuel on v2)
o Dropped Catalin's tag as a result of changed approach.
---
arch/arm64/include/asm/runtime-const.h | 46 ++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/arch/arm64/include/asm/runtime-const.h b/arch/arm64/include/asm/runtime-const.h
index 838145bc289d2..371c9a4bc2d4b 100644
--- a/arch/arm64/include/asm/runtime-const.h
+++ b/arch/arm64/include/asm/runtime-const.h
@@ -36,6 +36,17 @@
:"r" (0u+(val))); \
__ret; })
+#define runtime_const_mask_32(val, sym) ({ \
+ unsigned long __ret; \
+ asm_inline("1:\t" \
+ "ubfx %w0, %w1, #0, #32\n\t" \
+ ".pushsection runtime_mask_" #sym ",\"a\"\n\t" \
+ ".long 1b - .\n\t" \
+ ".popsection" \
+ :"=r" (__ret) \
+ :"r" (0u+(val))); \
+ __ret; })
+
#define runtime_const_init(type, sym) do { \
extern s32 __start_runtime_##type##_##sym[]; \
extern s32 __stop_runtime_##type##_##sym[]; \
@@ -73,6 +84,41 @@ static inline void __runtime_fixup_shift(void *where, unsigned long val)
aarch64_insn_patch_text_nosync(p, insn);
}
+static inline void __runtime_fixup_mask(void *where, unsigned long val)
+{
+ unsigned int width = __fls(val) + 1;
+ __le32 *p = where;
+ u32 insn;
+
+ /*
+ * XXX: Current implementation only supports patching masks of
+ * form GENMASK(n, 0) (n >= 0) using a single UBFX instruction
+ * to improve performance, density, and covers all the current
+ * use-cases.
+ *
+ * When the need arises to support any generic mask, and this
+ * BUG_ON() is tripped, consider using a:
+ *
+ * movz %w0, #imm16
+ * movk %w0, #imm16, lsl #16
+ *
+ * sequence to load the 32bit const mask, and perform a logical
+ * and outside the asm block before returning the result. Fixup
+ * can simply reuse the existing __runtime_fixup_16() to patch
+ * the individual mov instructions.
+ */
+ BUG_ON(!val || width > 32 || (GENMASK(width - 1, 0) != val));
+
+ /*
+ * The width of the mask is encoded as (width - 1) in imms
+ * which is 6 bits starting at bit #10.
+ */
+ insn = le32_to_cpu(*p);
+ insn &= 0xffff03ff;
+ insn |= ((width - 1) & 0x1f) << 10;
+ aarch64_insn_patch_text_nosync(p, insn);
+}
+
static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
unsigned long val, s32 *start, s32 *end)
{
--
2.34.1
^ permalink raw reply related
* [PATCH v5 4/8] riscv/runtime-const: Replace open-coded placeholder with RUNTIME_MAGIC
From: K Prateek Nayak @ 2026-06-30 4:55 UTC (permalink / raw)
To: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
Sebastian Andrzej Siewior, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: Darren Hart, Davidlohr Bueso, André Almeida, linux-arch,
linux-kernel, Samuel Holland, Charlie Jenkins, K Prateek Nayak,
linux-arm-kernel, linux-riscv, linux-s390, Alexandre Ghiti,
Jisheng Zhang, Guo Ren
In-Reply-To: <20260630045531.3939-1-kprateek.nayak@amd.com>
Define the placeholder used for lui + addi[w] patching sequence as
RUNTIME_MAGIC and use that instead of open coding the constants in the
inline assembly.
No functional changes intended.
Suggested-by: Guo Ren <guoren@kernel.org>
Reviewed-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
Tested-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
changelog v4..v5:
o Collected tags from Charlie (Thanks a ton!)
---
arch/riscv/include/asm/runtime-const.h | 38 ++++++++++++++------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/arch/riscv/include/asm/runtime-const.h b/arch/riscv/include/asm/runtime-const.h
index 900db0a103d05..1ce02605d2e43 100644
--- a/arch/riscv/include/asm/runtime-const.h
+++ b/arch/riscv/include/asm/runtime-const.h
@@ -15,21 +15,23 @@
#include <linux/uaccess.h>
+#define RUNTIME_MAGIC __ASM_STR(0x89ABCDEF)
+
#ifdef CONFIG_32BIT
-#define runtime_const_ptr(sym) \
-({ \
- typeof(sym) __ret; \
- asm_inline(".option push\n\t" \
- ".option norvc\n\t" \
- "1:\t" \
- "lui %[__ret],0x89abd\n\t" \
- "addi %[__ret],%[__ret],-0x211\n\t" \
- ".option pop\n\t" \
- ".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \
- ".long 1b - .\n\t" \
- ".popsection" \
- : [__ret] "=r" (__ret)); \
- __ret; \
+#define runtime_const_ptr(sym) \
+({ \
+ typeof(sym) __ret; \
+ asm_inline(".option push\n\t" \
+ ".option norvc\n\t" \
+ "1:\t" \
+ "lui %[__ret], %%hi(" RUNTIME_MAGIC ")\n\t" \
+ "addi %[__ret],%[__ret], %%lo(" RUNTIME_MAGIC ")\n\t" \
+ ".option pop\n\t" \
+ ".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \
+ ".long 1b - .\n\t" \
+ ".popsection" \
+ : [__ret] "=r" (__ret)); \
+ __ret; \
})
#else
/*
@@ -46,10 +48,10 @@
".option push\n\t" \
".option norvc\n\t" \
"1:\t" \
- "lui %[__ret],0x89abd\n\t" \
- "lui %[__tmp],0x1234\n\t" \
- "addiw %[__ret],%[__ret],-0x211\n\t" \
- "addiw %[__tmp],%[__tmp],0x567\n\t" \
+ "lui %[__ret], %%hi(" RUNTIME_MAGIC ")\n\t" \
+ "lui %[__tmp], %%hi(" RUNTIME_MAGIC ")\n\t" \
+ "addiw %[__ret],%[__ret], %%lo(" RUNTIME_MAGIC ")\n\t" \
+ "addiw %[__tmp],%[__tmp], %%lo(" RUNTIME_MAGIC ")\n\t" \
#define RISCV_RUNTIME_CONST_64_BASE \
"slli %[__tmp],%[__tmp],32\n\t" \
--
2.34.1
^ permalink raw reply related
* [PATCH v5 5/8] riscv/runtime-const: Introduce runtime_const_mask_32()
From: K Prateek Nayak @ 2026-06-30 4:55 UTC (permalink / raw)
To: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
Sebastian Andrzej Siewior, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: Darren Hart, Davidlohr Bueso, André Almeida, linux-arch,
linux-kernel, Samuel Holland, Charlie Jenkins, K Prateek Nayak,
linux-arm-kernel, linux-riscv, linux-s390, Alexandre Ghiti,
Jisheng Zhang
In-Reply-To: <20260630045531.3939-1-kprateek.nayak@amd.com>
Futex hash computation requires a mask operation with read-only after
init data that will be converted to a runtime constant in the subsequent
commit.
Introduce runtime_const_mask_32 to further optimize the mask operation
in the futex hash computation hot path. Since all the current use-cases
are of the form GENMASK(n, 0), with n > 0, following sequence:
srli a0, a1, imm
slli a0, a0, imm
is used for RISC-V where imm = (31 - width) to improve instruction
density and performance.
"The RISC-V Instruction Set Manual, Volume I - Unprivileged
Architecture" [1] Sec. 2.4.1 "Integer Register-Immediate Instructions"
notes the immediate shift for SRLI and SLLI are 5 bits wide starting at
bit #10. __runtime_fixup_shift() is reused to patch the immediate shifts
for the two instructions.
If a future use case arises that needs to tackle arbitrary mask,
consider using:
lui a0, 0x12346 # upper; +0x800 then >>12 for correct rounding
addi a0, a0, 0x678 # lower 12 bits
to patch the 32-bit mask in the asm block and return "__ret & (val)"
from runtime_const_mask_32() which allows compiler to further optimize
the logical and operation. __runtime_fixup_ptr() already patches a
lui + addi sequence which can be reused when the need arises.
A possible implementation for this alternate scheme can be found at [2].
Assisted-by: Claude:claude-sonnet-4-5
Suggested-by: Samuel Holland <samuel.holland@sifive.com>
Suggested-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
Link: https://docs.riscv.org/reference/isa/_attachments/riscv-unprivileged.pdf [1]
Link: https://lore.kernel.org/lkml/20260430094730.31624-6-kprateek.nayak@amd.com/ [2]
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
changelog v4..v5:
o Pivoted to SRLI + SLLI sequence for mask operation to extract the
lower bits for improved instruction desnity (Charlie, Samuel on v2).
---
arch/riscv/include/asm/asm.h | 1 +
arch/riscv/include/asm/runtime-const.h | 44 ++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h
index e9e8ba83e632f..b8bf842d4c136 100644
--- a/arch/riscv/include/asm/asm.h
+++ b/arch/riscv/include/asm/asm.h
@@ -34,6 +34,7 @@
#define SZREG __REG_SEL(8, 4)
#define LGREG __REG_SEL(3, 2)
#define SRLI __REG_SEL(srliw, srli)
+#define SLLI __REG_SEL(slliw, slli)
#if __SIZEOF_POINTER__ == 8
#ifdef __ASSEMBLER__
diff --git a/arch/riscv/include/asm/runtime-const.h b/arch/riscv/include/asm/runtime-const.h
index 1ce02605d2e43..dbf96c937dbb9 100644
--- a/arch/riscv/include/asm/runtime-const.h
+++ b/arch/riscv/include/asm/runtime-const.h
@@ -159,6 +159,23 @@
__ret; \
})
+#define runtime_const_mask_32(val, sym) \
+({ \
+ u32 __ret; \
+ asm_inline(".option push\n\t" \
+ ".option norvc\n\t" \
+ "1:\t" \
+ SLLI " %[__ret],%[__val],12\n\t" \
+ SRLI " %[__ret],%[__ret],12\n\t" \
+ ".option pop\n\t" \
+ ".pushsection runtime_mask_" #sym ",\"a\"\n\t" \
+ ".long 1b - .\n\t" \
+ ".popsection" \
+ : [__ret] "=r" (__ret) \
+ : [__val] "r" (val)); \
+ __ret; \
+})
+
#define runtime_const_init(type, sym) do { \
extern s32 __start_runtime_##type##_##sym[]; \
extern s32 __stop_runtime_##type##_##sym[]; \
@@ -262,6 +279,33 @@ static inline void __runtime_fixup_shift(void *where, unsigned long val)
mutex_unlock(&text_mutex);
}
+static inline void __runtime_fixup_mask(void *where, unsigned long val)
+{
+ unsigned int width = __fls(val) + 1;
+
+ /*
+ * XXX: Current implementation only supports patching masks of
+ * form GENMASK(width, 0) (width >= 0) using a SRLI + SLLI
+ * sequence instead of LUI + ADDI + AND sequence to improve
+ * performance, density, and covers all the current use-cases.
+ *
+ * When the need arises to support any generic mask, and this
+ * BUG_ON() is tripped, consider using a:
+ *
+ * lui %[__ret], #imm16
+ * addi %[__ret], #imm16
+ *
+ * sequence to load the 32bit const mask, and perform a logical
+ * and outside the asm block before returning the result. Fixup
+ * can simply reuse the existing __runtime_fixup_32() to patch
+ * the LUI + ADDI sequence.
+ */
+ BUG_ON(!val || width > 31 || (GENMASK(width - 1, 0) != val));
+
+ __runtime_fixup_shift(where, 32 - width);
+ __runtime_fixup_shift(where + 4, 32 - width);
+}
+
static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
unsigned long val, s32 *start, s32 *end)
{
--
2.34.1
^ permalink raw reply related
* [PATCH v5 6/8] s390/runtime-const: Introduce runtime_const_mask_32()
From: K Prateek Nayak @ 2026-06-30 4:55 UTC (permalink / raw)
To: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
Sebastian Andrzej Siewior, Heiko Carstens, Vasily Gorbik,
Alexander Gordeev
Cc: Darren Hart, Davidlohr Bueso, André Almeida, linux-arch,
linux-kernel, Samuel Holland, Charlie Jenkins, K Prateek Nayak,
linux-arm-kernel, linux-riscv, linux-s390, Christian Borntraeger,
Sven Schnelle
In-Reply-To: <20260630045531.3939-1-kprateek.nayak@amd.com>
Futex hash computation requires a mask operation with read-only after
init data that will be converted to a runtime constant in the subsequent
commit.
Introduce runtime_const_mask_32 to further optimize the mask operation
in the futex hash computation hot path.
GCC generates a:
nilf %r1,<imm32>
to tackle arbitrary 32-bit masks and the same is implemented here.
Immediate patching pattern for __runtime_fixup_mask() has been adopted
from __runtime_fixup_ptr().
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
changelog v4..v5:
o No changes.
---
arch/s390/include/asm/runtime-const.h | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/arch/s390/include/asm/runtime-const.h b/arch/s390/include/asm/runtime-const.h
index 17878b1d048cf..7b71156031ecb 100644
--- a/arch/s390/include/asm/runtime-const.h
+++ b/arch/s390/include/asm/runtime-const.h
@@ -33,6 +33,20 @@
__ret; \
})
+#define runtime_const_mask_32(val, sym) \
+({ \
+ unsigned int __ret = (val); \
+ \
+ asm_inline( \
+ "0: nilf %[__ret],12\n" \
+ ".pushsection runtime_mask_" #sym ",\"a\"\n" \
+ ".long 0b - .\n" \
+ ".popsection" \
+ : [__ret] "+d" (__ret) \
+ : : "cc"); \
+ __ret; \
+})
+
#define runtime_const_init(type, sym) do { \
extern s32 __start_runtime_##type##_##sym[]; \
extern s32 __stop_runtime_##type##_##sym[]; \
@@ -43,12 +57,12 @@
__stop_runtime_##type##_##sym); \
} while (0)
-/* 32-bit immediate for iihf and iilf in bits in I2 field */
static inline void __runtime_fixup_32(u32 *p, unsigned int val)
{
s390_kernel_write(p, &val, sizeof(val));
}
+/* 32-bit immediate for iihf and iilf in bits in I2 field */
static inline void __runtime_fixup_ptr(void *where, unsigned long val)
{
__runtime_fixup_32(where + 2, val >> 32);
@@ -65,6 +79,12 @@ static inline void __runtime_fixup_shift(void *where, unsigned long val)
s390_kernel_write(where, &insn, sizeof(insn));
}
+/* 32-bit immediate for nilf in bits in I2 field */
+static inline void __runtime_fixup_mask(void *where, unsigned long val)
+{
+ __runtime_fixup_32(where + 2, val);
+}
+
static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
unsigned long val, s32 *start, s32 *end)
{
--
2.34.1
^ permalink raw reply related
* [PATCH v5 7/8] asm-generic/runtime-const: Add dummy runtime_const_mask_32()
From: K Prateek Nayak @ 2026-06-30 4:55 UTC (permalink / raw)
To: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
Sebastian Andrzej Siewior
Cc: Darren Hart, Davidlohr Bueso, André Almeida, linux-arch,
linux-kernel, Samuel Holland, Charlie Jenkins, K Prateek Nayak,
linux-arm-kernel, linux-riscv, linux-s390
In-Reply-To: <20260630045531.3939-1-kprateek.nayak@amd.com>
From: Peter Zijlstra <peterz@infradead.org>
Add a dummy runtime_const_mask_32() for all the architectures that do
not support runtime-const.
Link: https://patch.msgid.link/20260227161841.GH606826@noisy.programming.kicks-ass.net
Not-yet-signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
changelog v4..v5:
o No changes.
---
include/asm-generic/runtime-const.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/asm-generic/runtime-const.h b/include/asm-generic/runtime-const.h
index 6704994595145..03e6e3e02401e 100644
--- a/include/asm-generic/runtime-const.h
+++ b/include/asm-generic/runtime-const.h
@@ -10,6 +10,7 @@
*/
#define runtime_const_ptr(sym) (sym)
#define runtime_const_shift_right_32(val, sym) ((u32)(val)>>(sym))
+#define runtime_const_mask_32(val, sym) ((u32)(val)&(sym))
#define runtime_const_init(type,sym) do { } while (0)
#endif
--
2.34.1
^ permalink raw reply related
* Re: [PATCH rc v6 3/7] iommu/arm-smmu-v3: Do not enable EVTQ/PRIQ interrupts in kdump kernel
From: Pranjal Shrivastava @ 2026-06-30 4:58 UTC (permalink / raw)
To: Nicolin Chen
Cc: will, robin.murphy, jgg, joro, kees, baolu.lu, kevin.tian,
miko.lenczewski, smostafa, linux-arm-kernel, iommu, linux-kernel,
stable, jamien
In-Reply-To: <akNCuEfZ30Gf21iQ@nvidia.com>
On Mon, Jun 29, 2026 at 09:14:48PM -0700, Nicolin Chen wrote:
> On Mon, Jun 29, 2026 at 08:48:11AM +0000, Pranjal Shrivastava wrote:
> > On Wed, May 20, 2026 at 10:03:20AM -0700, Nicolin Chen wrote:
> > > @@ -5020,19 +5029,30 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
> > > /*
> > > * Cavium ThunderX2 implementation doesn't support unique irq
> > > * lines. Use a single irq line for all the SMMUv3 interrupts.
> > > + *
> > > + * In kdump, EVTQ/PRIQ are disabled, so no threaded handling.
> > > */
> > > - ret = devm_request_threaded_irq(smmu->dev, irq,
> > > - arm_smmu_combined_irq_handler,
> > > - arm_smmu_combined_irq_thread,
> > > - IRQF_ONESHOT,
> > > - "arm-smmu-v3-combined-irq", smmu);
> > > + if (is_kdump_kernel())
> > > + ret = devm_request_irq(smmu->dev, irq,
> > > + arm_smmu_combined_irq_handler, 0,
> > > + "arm-smmu-v3-combined-irq",
> > > + smmu);
> >
> > This `if` isn't needed, we can continue using devm_request_threaded_irq,
> > if you look at the doc for devm_request_threaded_irq [1] it says:
> [...]
> > So, we can pass handler() here while leaving the thread_fn == NULL:
> >
> > ret = devm_request_threaded_irq(smmu->dev, irq,
> > arm_smmu_combined_irq_handler,
> > is_kdump_kernel() ? NULL : arm_smmu_combined_irq_thread,
> > IRQF_ONESHOT,
> > "arm-smmu-v3-combined-irq", smmu);
>
> Are you sure?
>
> __setup_irq():
> 1497- /*
> 1498: * IRQF_ONESHOT means the interrupt source in the IRQ chip will be
> 1499- * masked until the threaded handled is done. If there is no thread
> 1500: * handler then it makes no sense to have IRQF_ONESHOT.
> 1501- */
> 1502: WARN_ON_ONCE(new->flags & IRQF_ONESHOT && !new->thread_fn);
I meant without IRQF_ONESHOT:
is_kdump_kernel() ? 0 : IRQF_ONESHOT, note that devm_request_irq is just:
static inline int __must_check
devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
{
return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags | IRQF_COND_ONESHOT,
devname, dev_id);
}
Not a strong opinion though, just suggesting a way to remove the if.
>
> > Additionally, the arm_smmu_combined_irq_handler() returns
> > IRQ_WAKE_THREAD unconditionally, which causes us to hit the warn_on[3] in
> > __handle_irq_event_percpu.
>
> arm_smmu_combined_irq_handler() does not return IRQ_WAKE_THREAD
> unconditionally.
>
> This is the first part of PATCH-3 in v6:
Ahh I missed that, somehow.
Thanks,
Praan
^ permalink raw reply
* [PATCH v5 8/8] futex: Use runtime constants for __futex_hash() hot path
From: K Prateek Nayak @ 2026-06-30 4:55 UTC (permalink / raw)
To: Arnd Bergmann, Thomas Gleixner, Ingo Molnar, Peter Zijlstra,
Sebastian Andrzej Siewior, Borislav Petkov, Dave Hansen, x86,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou, Heiko Carstens, Vasily Gorbik, Alexander Gordeev
Cc: Darren Hart, Davidlohr Bueso, André Almeida, linux-arch,
linux-kernel, Samuel Holland, Charlie Jenkins, K Prateek Nayak,
linux-arm-kernel, linux-riscv, linux-s390, H. Peter Anvin,
Thomas Huth, Sean Christopherson, Jisheng Zhang, Alexandre Ghiti,
Christian Borntraeger, Sven Schnelle
In-Reply-To: <20260630045531.3939-1-kprateek.nayak@amd.com>
From: Peter Zijlstra <peterz@infradead.org>
Runtime constify the read-only after init data __futex_shift(shift_32),
__futex_mask(mask_32), and __futex_queues(ptr) used in __futex_hash()
hot path to avoid referencing global variable.
This also allows __futex_queues to be allocated dynamically to
"nr_node_ids" slots instead of reserving config dependent MAX_NUMNODES
(1 << CONFIG_NODES_SHIFT) worth of slots upfront.
Runtime constants are initialized before their first access and
runtime_const_init() provides necessary barrier to ensure subsequent
accesses are not reordered against their initialization.
No functional changes intended.
[ prateek: Dynamically allocate __futex_queues, mark the global data
__ro_after_init since they are constified after futex_init(). ]
Link: https://patch.msgid.link/20260227161841.GH606826@noisy.programming.kicks-ass.net
Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> # MAX_NUMNODES bloat
Not-yet-signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
---
changelog v4..v5:
o Rebased on latest tip:master.
---
include/asm-generic/vmlinux.lds.h | 5 +++-
kernel/futex/core.c | 42 +++++++++++++++++--------------
2 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 5659f4b5a1252..53207901d4c15 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -970,7 +970,10 @@
RUNTIME_CONST(ptr, __dentry_cache) \
RUNTIME_CONST(ptr, __names_cache) \
RUNTIME_CONST(ptr, __filp_cache) \
- RUNTIME_CONST(ptr, __bfilp_cache)
+ RUNTIME_CONST(ptr, __bfilp_cache) \
+ RUNTIME_CONST(shift, __futex_shift) \
+ RUNTIME_CONST(mask, __futex_mask) \
+ RUNTIME_CONST(ptr, __futex_queues)
/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */
#define KUNIT_TABLE() \
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 179b26e9c9341..b2a63ceb6ce98 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -48,23 +48,19 @@
#include <vdso/futex.h>
+#include <asm/runtime-const.h>
+
#include "futex.h"
#include "../locking/rtmutex_common.h"
-/*
- * The base of the bucket array and its size are always used together
- * (after initialization only in futex_hash()), so ensure that they
- * reside in the same cacheline.
- */
-static struct {
- unsigned long hashmask;
- unsigned int hashshift;
- struct futex_hash_bucket *queues[MAX_NUMNODES];
-} __futex_data __read_mostly __aligned(2*sizeof(long));
+static u32 __futex_mask __ro_after_init;
+static u32 __futex_shift __ro_after_init;
+static struct futex_hash_bucket **__futex_queues __ro_after_init;
-#define futex_hashmask (__futex_data.hashmask)
-#define futex_hashshift (__futex_data.hashshift)
-#define futex_queues (__futex_data.queues)
+static __always_inline struct futex_hash_bucket **futex_queues(void)
+{
+ return runtime_const_ptr(__futex_queues);
+}
struct futex_private_hash {
int state;
@@ -395,13 +391,13 @@ __futex_hash(union futex_key *key, struct futex_private_hash *fph, struct futex_
* NOTE: this isn't perfectly uniform, but it is fast and
* handles sparse node masks.
*/
- node = (hash >> futex_hashshift) % nr_node_ids;
+ node = runtime_const_shift_right_32(hash, __futex_shift) % nr_node_ids;
if (!node_possible(node)) {
node = find_next_bit_wrap(node_possible_map.bits, nr_node_ids, node);
}
}
- return &futex_queues[node][hash & futex_hashmask];
+ return &futex_queues()[node][runtime_const_mask_32(hash, __futex_mask)];
}
/**
@@ -1922,7 +1918,7 @@ int futex_hash_allocate_default(void)
* 16 <= threads * 4 <= global hash size
*/
buckets = roundup_pow_of_two(4 * threads);
- buckets = clamp(buckets, 16, futex_hashmask + 1);
+ buckets = clamp(buckets, 16, __futex_mask + 1);
if (current_buckets >= buckets)
return 0;
@@ -2020,10 +2016,19 @@ static int __init futex_init(void)
hashsize = max(4, hashsize);
hashsize = roundup_pow_of_two(hashsize);
#endif
- futex_hashshift = ilog2(hashsize);
+ __futex_mask = hashsize - 1;
+ __futex_shift = ilog2(hashsize);
size = sizeof(struct futex_hash_bucket) * hashsize;
order = get_order(size);
+ __futex_queues = kcalloc(nr_node_ids, sizeof(*__futex_queues), GFP_KERNEL);
+
+ runtime_const_init(shift, __futex_shift);
+ runtime_const_init(mask, __futex_mask);
+ runtime_const_init(ptr, __futex_queues);
+
+ BUG_ON(!futex_queues());
+
for_each_node(n) {
struct futex_hash_bucket *table;
@@ -2037,10 +2042,9 @@ static int __init futex_init(void)
for (i = 0; i < hashsize; i++)
futex_hash_bucket_init(&table[i]);
- futex_queues[n] = table;
+ futex_queues()[n] = table;
}
- futex_hashmask = hashsize - 1;
pr_info("futex hash table entries: %lu (%lu bytes on %d NUMA nodes, total %lu KiB, %s).\n",
hashsize, size, num_possible_nodes(), size * num_possible_nodes() / 1024,
order > MAX_PAGE_ORDER ? "vmalloc" : "linear");
--
2.34.1
^ permalink raw reply related
* Re: [PATCH rc v6 3/7] iommu/arm-smmu-v3: Do not enable EVTQ/PRIQ interrupts in kdump kernel
From: Pranjal Shrivastava @ 2026-06-30 5:00 UTC (permalink / raw)
To: Nicolin Chen
Cc: will, robin.murphy, jgg, joro, kees, baolu.lu, kevin.tian,
miko.lenczewski, smostafa, linux-arm-kernel, iommu, linux-kernel,
stable, jamien
In-Reply-To: <akNM5peYovV3GdV4@google.com>
On Tue, Jun 30, 2026 at 04:58:14AM +0000, Pranjal Shrivastava wrote:
> On Mon, Jun 29, 2026 at 09:14:48PM -0700, Nicolin Chen wrote:
> > On Mon, Jun 29, 2026 at 08:48:11AM +0000, Pranjal Shrivastava wrote:
> > > On Wed, May 20, 2026 at 10:03:20AM -0700, Nicolin Chen wrote:
> > > > @@ -5020,19 +5029,30 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
> > > > /*
> > > > * Cavium ThunderX2 implementation doesn't support unique irq
> > > > * lines. Use a single irq line for all the SMMUv3 interrupts.
> > > > + *
> > > > + * In kdump, EVTQ/PRIQ are disabled, so no threaded handling.
> > > > */
> > > > - ret = devm_request_threaded_irq(smmu->dev, irq,
> > > > - arm_smmu_combined_irq_handler,
> > > > - arm_smmu_combined_irq_thread,
> > > > - IRQF_ONESHOT,
> > > > - "arm-smmu-v3-combined-irq", smmu);
> > > > + if (is_kdump_kernel())
> > > > + ret = devm_request_irq(smmu->dev, irq,
> > > > + arm_smmu_combined_irq_handler, 0,
> > > > + "arm-smmu-v3-combined-irq",
> > > > + smmu);
> > >
> >
> > Are you sure?
> >
> > __setup_irq():
> > 1497- /*
> > 1498: * IRQF_ONESHOT means the interrupt source in the IRQ chip will be
> > 1499- * masked until the threaded handled is done. If there is no thread
> > 1500: * handler then it makes no sense to have IRQF_ONESHOT.
> > 1501- */
> > 1502: WARN_ON_ONCE(new->flags & IRQF_ONESHOT && !new->thread_fn);
>
> I meant without IRQF_ONESHOT:
>
> is_kdump_kernel() ? 0 : IRQF_ONESHOT, note that devm_request_irq is just:
>
> static inline int __must_check
> devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
> unsigned long irqflags, const char *devname, void *dev_id)
> {
> return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags | IRQF_COND_ONESHOT,
> devname, dev_id);
> }
>
> Not a strong opinion though, just suggesting a way to remove the if.
>
I though I had given an R-b earlier, but I didn't.
With that nit:
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Thanks,
Praan
^ permalink raw reply
* Re: [PATCH rc v6 4/7] iommu/arm-smmu-v3: Skip EVTQ/PRIQ setup in kdump kernel
From: Pranjal Shrivastava @ 2026-06-30 5:01 UTC (permalink / raw)
To: Nicolin Chen
Cc: will, robin.murphy, jgg, joro, kees, baolu.lu, kevin.tian,
miko.lenczewski, smostafa, linux-arm-kernel, iommu, linux-kernel,
stable, jamien
In-Reply-To: <akNDZM7n/EpBmajY@nvidia.com>
On Mon, Jun 29, 2026 at 09:17:40PM -0700, Nicolin Chen wrote:
> On Mon, Jun 29, 2026 at 03:15:21PM +0000, Pranjal Shrivastava wrote:
> > On Wed, May 20, 2026 at 10:03:21AM -0700, Nicolin Chen wrote:
> > > + if (!is_kdump_kernel()) {
> > > + writeq_relaxed(smmu->evtq.q.q_base,
> > > + smmu->base + ARM_SMMU_EVTQ_BASE);
> > > + writel_relaxed(smmu->evtq.q.llq.prod,
> > > + smmu->page1 + ARM_SMMU_EVTQ_PROD);
> > > + writel_relaxed(smmu->evtq.q.llq.cons,
> > > + smmu->page1 + ARM_SMMU_EVTQ_CONS);
> > > +
> > > + enables |= CR0_EVTQEN;
> > > + ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
> > > + ARM_SMMU_CR0ACK);
> >
> > Nit:
> > I believe only the write_reg_sync(CR0) should be under this if condition
> > do we see any weird behavior if we perform the reg writes in
> > kdump_kernel?
>
> Since CR0_EVTQEN isn't set, the other three writes are dead code.
>
> So, I skipped them.
Ack,
Praan
^ permalink raw reply
* RE: [5/7] soc: aspeed: Add eSPI flash channel support
From: YH Chung @ 2026-06-30 5:02 UTC (permalink / raw)
To: Markus Elfring, linux-aspeed@lists.ozlabs.org,
openbmc@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, Andrew Jeffery, Conor Dooley,
Joel Stanley, Krzysztof Kozlowski, Philipp Zabel, Rob Herring,
Ryan Chen
Cc: LKML, Maciej Lawniczak
In-Reply-To: <1df6b921-368e-461a-af01-d453a3898cf7@web.de>
Hi Markus,
> >>> +++ b/drivers/soc/aspeed/espi/aspeed-espi.c
> >> …
> >>> +static void aspeed_espi_flash_rx_work(struct work_struct *work) {
> …
> > Thanks for the suggestion. I agree that guard(mutex) is helpful when a
> > locked section has multiple exit paths. Since this worker currently
> > has a single simple path, I would prefer to keep the explicit
> > mutex_lock()/mutex_unlock() pair for readability. I can switch to
> > guard(mutex) if you think it would be better in this case.
> I hope that development interests can increase more also for the application of
> scope-based resource management.
>
Thanks for the clarification. I will switch this worker to use guard(mutex)
so that the code follows the scope-based resource management style.
Best regards,
Yun Hsuan
^ permalink raw reply
* Re: [PATCH rc v6 3/7] iommu/arm-smmu-v3: Do not enable EVTQ/PRIQ interrupts in kdump kernel
From: Nicolin Chen @ 2026-06-30 5:36 UTC (permalink / raw)
To: Pranjal Shrivastava
Cc: will, robin.murphy, jgg, joro, kees, baolu.lu, kevin.tian,
miko.lenczewski, smostafa, linux-arm-kernel, iommu, linux-kernel,
stable, jamien
In-Reply-To: <akNM5peYovV3GdV4@google.com>
On Tue, Jun 30, 2026 at 04:58:14AM +0000, Pranjal Shrivastava wrote:
> is_kdump_kernel() ? 0 : IRQF_ONESHOT, note that devm_request_irq is just:
>
> static inline int __must_check
> devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
> unsigned long irqflags, const char *devname, void *dev_id)
> {
> return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags | IRQF_COND_ONESHOT,
> devname, dev_id);
> }
>
> Not a strong opinion though, just suggesting a way to remove the if.
I've thought about that but kept the if-else on purpose:
- Using two ternaries doesn't seem a common practice to me.
- request_threaded_irq doesn't read as clean as request_irq
for GERROR to use -- one could wonder why "threaded".
Thanks
Nicolin
^ permalink raw reply
* [PATCH V4 0/7] PCI: imx6: Integrate pwrctrl API and update device trees
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
From: Sherry Sun <sherry.sun@nxp.com>
This series integrates the PCI pwrctrl framework into the pci-imx6
driver and updates i.MX EVK board device trees to support it.
Patches 2-8 update device trees for i.MX EVK boards which maintained
by NXP to move power supply properties from the PCIe controller node
to the Root Port child node, which is required for pwrctrl framework.
Affected boards:
- i.MX6Q/DL SABRESD
- i.MX6SX SDB
- i.MX8MM EVK
- i.MX8MP EVK
- i.MX8MQ EVK
- i.MX8DXL/QM/QXP EVK
- i.MX95 15x15/19x19 EVK
The driver maintains legacy regulator handling for device trees that
haven't been updated yet. Both old and new device tree structures are
supported.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
Changes in V4:
1. Fix the CHECK_DTBS warnings.
2. Drop pci-imx6 pwrctrl support patch as it got applied.
Changes in V3:
1. Rebased on top of latest 7.1.0-rc4
Changes in V2:
1. After commit 2d8c5098b847 ("PCI/pwrctrl: Do not power off on pwrctrl
device removal"), the pwrctrl drivers no longer power off devices
during removal. Update pci-imx6 driver's shutdown callback in patch#1
to explicitly call pci_pwrctrl_power_off_devices() before
pci_pwrctrl_destroy_devices() to ensure devices are properly powered
off.
---
Sherry Sun (7):
arm: dts: imx6qdl-sabresd: Move power supply property to Root Port
node
arm: dts: imx6sx-sdb: Move power supply property to Root Port node
arm64: dts: imx8mm-evk: Move power supply property to Root Port node
arm64: dts: imx8mp-evk: Move power supply properties to Root Port node
arm64: dts: imx8mq-evk: Move power supply properties to Root Port node
arm64: dts: imx8dxl/qm/qxp: Move power supply properties to Root Port
node
arm64: dts: imx95: Move power supply properties to Root Port node
arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi | 2 +-
arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi | 2 +-
arch/arm64/boot/dts/freescale/imx8dxl-evk.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi | 2 +-
arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx8qm-mek.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts | 8 ++++----
10 files changed, 19 insertions(+), 19 deletions(-)
base-commit: 7de6ae9e12207ec146f2f3f1e58d1a99317e88bc
--
2.50.1
^ permalink raw reply
* [PATCH V4 1/7] arm: dts: imx6qdl-sabresd: Move power supply property to Root Port node
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Sherry Sun <sherry.sun@nxp.com>
Move the power supply property from the PCIe controller node to the Root
Port child node to support the new PCI pwrctrl framework.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi
index fe9046c03ddd..c52b8897f999 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-sabresd.dtsi
@@ -756,12 +756,12 @@ &pcie {
pinctrl-0 = <&pinctrl_pcie>;
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&gpio7 12 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_pcie>;
status = "okay";
};
&pcie_port0 {
reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcie>;
};
&pwm1 {
--
2.50.1
^ permalink raw reply related
* [PATCH V4 2/7] arm: dts: imx6sx-sdb: Move power supply property to Root Port node
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Sherry Sun <sherry.sun@nxp.com>
Move the power supply property from the PCIe controller node to the Root
Port child node to support the new PCI pwrctrl framework.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
index 338de4d144b2..41a69fe83be8 100644
--- a/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
+++ b/arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi
@@ -284,12 +284,12 @@ &pcie {
pinctrl-0 = <&pinctrl_pcie>;
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&gpio2 0 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_pcie_gpio>;
status = "okay";
};
&pcie_port0 {
reset-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcie_gpio>;
};
&lcdif1 {
--
2.50.1
^ permalink raw reply related
* [PATCH V4 3/7] arm64: dts: imx8mm-evk: Move power supply property to Root Port node
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Sherry Sun <sherry.sun@nxp.com>
Move the power supply property from the PCIe controller node to the Root
Port child node to support the new PCI pwrctrl framework.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
index e03aba825c18..3205798614a3 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
@@ -542,7 +542,6 @@ &pcie0 {
assigned-clock-rates = <10000000>, <250000000>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
<&clk IMX8MM_SYS_PLL2_250M>;
- vpcie-supply = <®_pcie0>;
supports-clkreq;
status = "okay";
};
@@ -562,6 +561,7 @@ &pcie0_ep {
&pcie0_port0 {
reset-gpios = <&gpio4 21 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcie0>;
};
&sai2 {
--
2.50.1
^ permalink raw reply related
* [PATCH V4 4/7] arm64: dts: imx8mp-evk: Move power supply properties to Root Port node
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Sherry Sun <sherry.sun@nxp.com>
Move the power supply properties from the PCIe controller node to the
Root Port child node to support the new PCI pwrctrl framework.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm64/boot/dts/freescale/imx8mp-evk.dts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index a7f3acdc36d1..0c6829966f6a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -772,8 +772,6 @@ &pcie0 {
pinctrl-0 = <&pinctrl_pcie0>;
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&gpio2 7 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_pcie0>;
- vpcie3v3aux-supply = <®_pcie0>;
supports-clkreq;
status = "disabled";
};
@@ -786,6 +784,8 @@ &pcie0_ep {
&pcie0_port0 {
reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcie0>;
+ vpcie3v3aux-supply = <®_pcie0>;
};
&pwm1 {
--
2.50.1
^ permalink raw reply related
* [PATCH V4 5/7] arm64: dts: imx8mq-evk: Move power supply properties to Root Port node
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Sherry Sun <sherry.sun@nxp.com>
Move the power supply properties from the PCIe controller node to the
Root Port child node to support the new PCI pwrctrl framework.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
index b9b03416aa39..383a0976d457 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -403,8 +403,6 @@ &pcie1 {
<&pcie0_refclk>,
<&clk IMX8MQ_CLK_PCIE2_PHY>,
<&clk IMX8MQ_CLK_PCIE2_AUX>;
- vpcie-supply = <®_pcie1>;
- vpcie3v3aux-supply = <®_pcie1>;
vph-supply = <&vgen5_reg>;
supports-clkreq;
status = "okay";
@@ -422,6 +420,8 @@ &pcie1_ep {
&pcie1_port0 {
reset-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcie1>;
+ vpcie3v3aux-supply = <®_pcie1>;
};
&pgc_gpu {
--
2.50.1
^ permalink raw reply related
* [PATCH V4 6/7] arm64: dts: imx8dxl/qm/qxp: Move power supply properties to Root Port node
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Sherry Sun <sherry.sun@nxp.com>
Move the power supply properties from the PCIe controller nodes to the
Root Port child nodes to support the new PCI pwrctrl framework.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm64/boot/dts/freescale/imx8dxl-evk.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx8qm-mek.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
index 78e8d41e6791..59d9fe687aaf 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
@@ -677,8 +677,6 @@ &pcie0 {
pinctrl-names = "default";
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&lsio_gpio4 0 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_pcieb>;
- vpcie3v3aux-supply = <®_pcieb>;
status = "okay";
};
@@ -692,6 +690,8 @@ &pcie0_ep {
&pcieb_port0 {
reset-gpios = <&lsio_gpio4 0 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcieb>;
+ vpcie3v3aux-supply = <®_pcieb>;
};
&sai0 {
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
index f706c86137c0..d23313bd547c 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qm-mek.dts
@@ -812,14 +812,14 @@ &pciea {
pinctrl-names = "default";
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&lsio_gpio4 29 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_pciea>;
- vpcie3v3aux-supply = <®_pciea>;
supports-clkreq;
status = "okay";
};
&pciea_port0 {
reset-gpios = <&lsio_gpio4 29 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pciea>;
+ vpcie3v3aux-supply = <®_pciea>;
};
&pcieb {
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
index 2af32eca612a..5ec4082bd43e 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
@@ -732,8 +732,6 @@ &pcie0 {
pinctrl-names = "default";
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpios = <&lsio_gpio4 0 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_pcieb>;
- vpcie3v3aux-supply = <®_pcieb>;
supports-clkreq;
status = "okay";
};
@@ -748,6 +746,8 @@ &pcie0_ep {
&pcieb_port0 {
reset-gpios = <&lsio_gpio4 0 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcieb>;
+ vpcie3v3aux-supply = <®_pcieb>;
};
&scu_key {
--
2.50.1
^ permalink raw reply related
* [PATCH V4 7/7] arm64: dts: imx95: Move power supply properties to Root Port node
From: Sherry Sun (OSS) @ 2026-06-30 6:07 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach
Cc: imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel,
sherry.sun
In-Reply-To: <20260630060710.3294811-1-sherry.sun@oss.nxp.com>
From: Sherry Sun <sherry.sun@nxp.com>
Move the power supply properties from the PCIe controller nodes to the
Root Port child nodes to support the new PCI pwrctrl framework.
Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
---
arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts | 4 ++--
arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts b/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts
index 7d820a0f80b2..6aedcbbe915a 100644
--- a/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts
@@ -555,8 +555,6 @@ &pcie0 {
pinctrl-names = "default";
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&gpio5 13 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_m2_pwr>;
- vpcie3v3aux-supply = <®_m2_pwr>;
supports-clkreq;
status = "disabled";
};
@@ -570,6 +568,8 @@ &pcie0_ep {
&pcie0_port0 {
reset-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_m2_pwr>;
+ vpcie3v3aux-supply = <®_m2_pwr>;
};
&sai1 {
diff --git a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
index 2e463bc7c601..340ab0253ec2 100644
--- a/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts
@@ -542,8 +542,6 @@ &pcie0 {
pinctrl-names = "default";
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&i2c7_pcal6524 5 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_pcie0>;
- vpcie3v3aux-supply = <®_pcie0>;
supports-clkreq;
status = "okay";
};
@@ -557,6 +555,8 @@ &pcie0_ep {
&pcie0_port0 {
reset-gpios = <&i2c7_pcal6524 5 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_pcie0>;
+ vpcie3v3aux-supply = <®_pcie0>;
};
&pcie1 {
@@ -564,8 +564,6 @@ &pcie1 {
pinctrl-names = "default";
/* This property is deprecated, use reset-gpios from the Root Port node. */
reset-gpio = <&i2c7_pcal6524 16 GPIO_ACTIVE_LOW>;
- vpcie-supply = <®_slot_pwr>;
- vpcie3v3aux-supply = <®_slot_pwr>;
status = "okay";
};
@@ -578,6 +576,8 @@ &pcie1_ep {
&pcie1_port0 {
reset-gpios = <&i2c7_pcal6524 16 GPIO_ACTIVE_LOW>;
+ vpcie3v3-supply = <®_slot_pwr>;
+ vpcie3v3aux-supply = <®_slot_pwr>;
};
&sai1 {
--
2.50.1
^ permalink raw reply related
* Re: [PATCH 3/4] dt-bindings: ipmi: Add optional LPC properties to ASPEED BT devices
From: Krzysztof Kozlowski @ 2026-06-30 6:11 UTC (permalink / raw)
To: yc_hsieh, Corey Minyard, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Joel Stanley, Andrew Jeffery
Cc: openipmi-developer, linux-kernel, devicetree, linux-arm-kernel,
linux-aspeed
In-Reply-To: <20260629-aspeed-bt-bmc-multichannel-v1-3-fc23ee337f7a@aspeedtech.com>
On 29/06/2026 08:49, Yu-Che Hsieh via B4 Relay wrote:
> From: Yu-Che Hsieh <yc_hsieh@aspeedtech.com>
>
> Allocating IO and IRQ resources to LPC devices is in-theory an operation
>
> for the host, however ASPEED systems describe these resources through
>
> BMC-internal configuration, as already supported by the ASPEED KCS BMC
What
is
with
this
line breaks?
>
> binding.
>
> Add aspeed,lpc-io-reg and aspeed,lpc-interrupts to the ASPEED BT BMC
>
> binding so firmware can describe the host LPC IO address and SerIRQ
>
> configuration using the same properties as KCS devices.
>
> Signed-off-by: Yu-Che Hsieh <yc_hsieh@aspeedtech.com>
> ---
> .../bindings/ipmi/aspeed,ast2400-ibt-bmc.yaml | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.yaml b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.yaml
> index c4f7cdbbe16b..1803c6bbae93 100644
> --- a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.yaml
> +++ b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-ibt-bmc.yaml
> @@ -25,6 +25,24 @@ properties:
> interrupts:
> maxItems: 1
>
> + aspeed,lpc-io-reg:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + maxItems: 1
> + description: |
> + The host CPU LPC IO address for the BT device.
No, you do not get second reg property.
> +
> + aspeed,lpc-interrupts:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + minItems: 2
> + maxItems: 2
> + description: |
> + A 2-cell property expressing the LPC SerIRQ number and the interrupt
> + level/sense encoding (specified in the standard fashion).
> +
> + Note that the generated interrupt is issued from the BMC to the host, and
> + thus the target interrupt controller is not captured by the BMC's
> + devicetree.
No, you do not get second interrupts property.
>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/4] dt-bindings: phy: nuvoton,ma35d1-usb2-phy: extend for dual-port OTG support
From: Krzysztof Kozlowski @ 2026-06-30 6:16 UTC (permalink / raw)
To: Joey Lu
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Arnd Bergmann, Catalin Marinas, Jacky Huang,
Shan-Chun Hung, Hui-Ping Chen, Joey Lu, linux-phy, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <24de6a00-ba4e-455b-baa7-479d1cc2edf3@gmail.com>
On 29/06/2026 12:40, Joey Lu wrote:
>
> On 6/25/2026 3:58 PM, Krzysztof Kozlowski wrote:
>> On Thu, Jun 25, 2026 at 10:39:56AM +0800, Joey Lu wrote:
>>> properties:
>>> compatible:
>>> enum:
>>> - nuvoton,ma35d1-usb2-phy
>>>
>>> + reg:
>>> + maxItems: 1
>>> +
>>> "#phy-cells":
>>> - const: 0
>>> + const: 1
>>> + description:
>>> + The single cell selects the PHY port. 0 selects the OTG port (USB0,
>>> + shared with DWC2 gadget controller) and 1 selects the host-only port
>>> + (USB1).
>>>
>>> - clocks:
>>> - maxItems: 1
>> This is odd, considering that parent does not have clocks. So explain me
>> this:
>> 1. USB PHY needed clocks.
>> 2. You extend USB PHY to cover second part.
>> 3. That extension for second part means that clocks are not needed.
>> Really, how? How is it possible in hardware?
> The hardware has two independent clock domains:
>
> - The PHY analog block takes the 24 MHz HXT as its reference, wired
> directly to the PHY's internal PLL, which derives the required
> operating
> frequencies internally. This reference path is entirely outside the SoC
> software clock tree; no software-gatable clock gate needs to be enabled
> for the PHY to power up and lock its PLL. The only software control the
> PHY driver exercises is toggling each PHY's Power-On Reset (POR) bit,
> which resides in the SYS register block. The driver accesses this via
> the parent regmap
>
> - `HUSBH0_GATE` / `HUSBH1_GATE` / `USBD_GATE` are AHB/APB bus interface
> clocks for the host and gadget (EHCI, OHCI, DWC2). They gate
> the register-access path between the CPU and each controller, not
> the PHY
> analog circuitry itself.
>
> The original single-port driver enabled `HUSBH0_GATE` as if it belonged
> to the
> PHY, but that gate is actually owned by EHCI0/OHCI0 and is already
> managed by
> those controller drivers through their own `clocks` DTS bindings. The PHY
> driver was redundantly enabling the same gate.
>
> When extending the driver to cover PHY1, the same pattern held: EHCI1/OHCI1
> manage `HUSBH1_GATE` themselves. There is no clock that belongs
> exclusively to
> the PHY, so `clocks` will be dropped from the PHY binding entirely.
What driver has to do with it?
You did not answer the question. How adding missing OTG to existing
device causes that hardware to lose a clock? How is it possible?
>>> + nuvoton,rcalcode:
>>> + $ref: /schemas/types.yaml#/definitions/uint32-array
>>> + minItems: 1
>>> + maxItems: 2
>> You should require two values. I understand that any PHY is optional,
>> thus you skip the entry, so how would you provide value for PHY1 only?
> `nuvoton,rcalcode` will be changed to require exactly two values
> (`minItems: 2, maxItems: 2`), one for PHY0 and one for PHY1 respectively.
> The property will remain optional overall; when absent, each port
> retains its
> power-on default value loaded at hardware initialisation. When present, both
> entries must be supplied.
So are you going to implement it or not?
>>> + items:
>>> + minimum: 0
>>> + maximum: 15
>>> + description:
>>> + Resistor calibration trim codes for PHY0 and PHY1 respectively.
>>> + Each 4-bit value is written to the RCALCODE field in USBPMISCR and
>>> + adjusts the PHY's internal termination resistance. Both entries are
>>> + optional; when absent the hardware reset default is used.
>>>
>>> - nuvoton,sys:
>>> - $ref: /schemas/types.yaml#/definitions/phandle
>>> + nuvoton,oc-active-high:
>>> + type: boolean
>>> description:
>>> - phandle to syscon for checking the PHY clock status.
>>> + When present, the over-current detect input from the VBUS power switch
>>> + is treated as active-high. The default (property absent) is active-low.
>>> + This setting is shared by both USB host ports.
>>>
>>> required:
>>> - compatible
>>> + - reg
>> That's ABI break which was not explained in the commit msg - neither
>> specifying impact nor actually providing reasons why you break ABI.
>>
>> And honestly, you have no resources here except the address, so now it
>> is clear that this should be folded into parent. See DTS101 talk slides.
> The commit message will be updated to explicitly acknowledge the ABI break:
> existing DTS files that contain a standalone `usb-phy` node without a `reg`
> property will fail dt-schema validation after this change. The impact is
> limited to the MA35D1 SoC; no upstream DTS for this SoC existed before this
> patch series, so no in-tree board files are broken. The break is intentional
But all of out of tree users are broken.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH rc v7 2/7] iommu/arm-smmu-v3: Implement is_attach_deferred() for kdump
From: Nicolin Chen @ 2026-06-30 6:15 UTC (permalink / raw)
To: will, robin.murphy, jgg
Cc: joro, praan, kees, baolu.lu, kevin.tian, miko.lenczewski,
smostafa, linux-arm-kernel, iommu, linux-kernel, stable, jamien
In-Reply-To: <cover.1782799827.git.nicolinc@nvidia.com>
Though the kdump kernel adopts the crashed kernel's stream table, the iommu
core will still try to attach each probed device to a default domain, which
overwrites the adopted STE and breaks in-flight DMA from that device.
Implement an is_attach_deferred() callback to prevent this. For each device
that has STE.V=1 and STE.Cfg!=Abort in the adopted table, defer the default
domain attachment, until the device driver explicitly requests it.
Fixes: b63b3439b856 ("iommu/arm-smmu-v3: Abort all transactions if SMMU is enabled in kdump kernel")
Cc: stable@vger.kernel.org # v6.12+
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 +++++++++++++++++++++
1 file changed, 24 insertions(+)
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 af97a22c11696..b4702945b7324 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4198,6 +4198,29 @@ static int arm_smmu_master_prepare_ats(struct arm_smmu_master *master)
return arm_smmu_alloc_cd_tables(master);
}
+static bool arm_smmu_is_attach_deferred(struct device *dev)
+{
+ struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+ struct arm_smmu_device *smmu = master->smmu;
+ int i;
+
+ if (!(smmu->options & ARM_SMMU_OPT_KDUMP_ADOPT))
+ return false;
+
+ for (i = 0; i < master->num_streams; i++) {
+ struct arm_smmu_ste *ste =
+ arm_smmu_get_step_for_sid(smmu, master->streams[i].id);
+ u64 ent0 = le64_to_cpu(ste->data[0]);
+
+ /* Defer only when there might be in-flight DMAs */
+ if ((ent0 & STRTAB_STE_0_V) &&
+ FIELD_GET(STRTAB_STE_0_CFG, ent0) != STRTAB_STE_0_CFG_ABORT)
+ return true;
+ }
+
+ return false;
+}
+
static struct iommu_device *arm_smmu_probe_device(struct device *dev)
{
int ret;
@@ -4361,6 +4384,7 @@ static const struct iommu_ops arm_smmu_ops = {
.hw_info = arm_smmu_hw_info,
.domain_alloc_sva = arm_smmu_sva_domain_alloc,
.domain_alloc_paging_flags = arm_smmu_domain_alloc_paging_flags,
+ .is_attach_deferred = arm_smmu_is_attach_deferred,
.probe_device = arm_smmu_probe_device,
.release_device = arm_smmu_release_device,
.device_group = arm_smmu_device_group,
--
2.43.0
^ permalink raw reply related
* [PATCH rc v7 0/7] iommu/arm-smmu-v3: Fix device crash on kdump kernel
From: Nicolin Chen @ 2026-06-30 6:15 UTC (permalink / raw)
To: will, robin.murphy, jgg
Cc: joro, praan, kees, baolu.lu, kevin.tian, miko.lenczewski,
smostafa, linux-arm-kernel, iommu, linux-kernel, stable, jamien
When transitioning to a kdump kernel, the primary kernel might have crashed
while endpoint devices were actively bus-mastering DMA. Currently, the SMMU
driver aggressively resets the hardware during probe by clearing CR0_SMMUEN
and setting the Global Bypass Attribute (GBPA) to ABORT.
In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal
PCIe AER or SErrors that may panic the kdump kernel
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass
the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMA, the kdump kernel must leave SMMUEN=1 intact
and avoid modifying STRTAB_BASE. This allows HW to continue translating in-
flight DMA using the crashed kernel's page tables until the endpoint device
drivers probe and quiesce their respective hardware.
However, the ARM SMMUv3 architecture specification states that updating the
SMMU_STRTAB_BASE register while SMMUEN == 1 is UNPREDICTABLE or ignored.
This leaves a kdump kernel no choice but to adopt the stream table from the
crashed kernel.
In this series:
- Introduce an ARM_SMMU_OPT_KDUMP_ADOPT
- Skip SMMUEN and STRTAB_BASE resets in arm_smmu_device_reset()
- Skip EVENTQ/PRIQ setup including interrupts and their handlers
- Memremap the crashed kernel's stream tables into the kdump kernel [*]
- Defer any default domain attachment to retain STEs until device drivers
explicitly request it.
[*] For verification reasons, this series only fixes coherent SMMUs.
For non-ARM_SMMU_OPT_KDUMP_ADOPT cases, keep a status quo since the commit
3f54c447df34f ("iommu/arm-smmu-v3: Don't disable SMMU in kdump kernel"):
full reset followed by driver-initiated reattach, potentially rejecting any
in-flight DMA.
Note that the series requires Jason's work that was merged in v6.12: commit
85196f54743d ("iommu/arm-smmu-v3: Reorganize struct arm_smmu_strtab_cfg").
I have a backported version that is verified with a v6.8 kernel. I can send
if we see a strong need after this version is accepted.
This is on Github:
https://github.com/nicolinc/iommufd/commits/smmuv3_kdump-v7
Changelog
v7
* Rebase v7.2-rc1
* Add Reviewed-by from Pranjal
* Reword the linear stream table adoption comment
* Use dev_dbg for the stream table adoption message
* Document why the lazy L2 adoption uses devm_memremap()
* Drop redundant FEAT_COHERENCY checks in the adopt functions
* Use feature bit instead of STRTAB_BASE_CFG in adopt cleanup
* Skip CR0_ATSCHK update in adopt mode to retain the crashed policy
* Restore FEAT_2_LVL_STRTAB if the cleanup action fails to register
v6
https://lore.kernel.org/all/cover.1779265413.git.nicolinc@nvidia.com/
* Rebase v7.1-rc3
* Add Reviewed-by from Jason
* Replace dma_addr_t with phys_addr_t
* Drop arm_smmu_kdump_phys_is_corrupted()
* Skip threaded IRQ handlers for EVTQ and PRIQ
* Bypass arm_smmu_rmr_install_bypass_ste() in kdump case
* Drop devm_ for adopt-time allocations; set up cleanup function via
devm_add_action_or_reset()
v5
https://lore.kernel.org/all/cover.1778416609.git.nicolinc@nvidia.com/
* Add Reviewed-by from Kevin
* Drop READ_ONCE on lazy-attach L1 read
* Split "Skip EVTQ/PRIQ setup" into two patches
* Tighten kdump probe comment and dev_warn message
* Use MEM + BUSY in arm_smmu_kdump_phys_is_corrupted
v4
https://lore.kernel.org/all/cover.1777446969.git.nicolinc@nvidia.com/
* Rebase v7.1-rc1
* s/arm_smmu_adopt/arm_smmu_kdump_adopt
* Revert alloc/memremap/fmt on fallback
* Reorder patches to avoid bisect regression
* Use IRQ_NONE for spurious evtq/priq entries
* Cap linear log2size by kdump's allocation bound
* Defer clearing FEAT_2_LVL_STRTAB on linear adopt
* Add arm_smmu_kdump_phys_is_corrupted() validation
* Defer l2 stream table memremap till master inserts
* Re-validate L1 desc on master insert with READ_ONCE
v3
https://lore.kernel.org/all/cover.1777150307.git.nicolinc@nvidia.com/
* s/OPT_KDUMP/OPT_KDUMP_ADOPT
* Do not adopt if GERROR_SFM_ERR
* Retain CR0_ATSCHK beside CR0_SMMUEN
* Clear latched GERROR bits (e.g. CMDQ_ERR)
* Assert ARM_SMMU_FEAT_COHERENCY in adopt functions
* Add STE.Cfg check in arm_smmu_is_attach_deferred()
* Fix validations on return codes from devm_memremap()
* Sanitize crashed kernel register values in adopt functions
* Drop unnecessary l2ptrs guard in arm_smmu_is_attach_deferred()
* Don't enable PRIQ/EVTQ irqs and guard the irq functions for combined
irq cases
v2
https://lore.kernel.org/all/cover.1776286352.git.nicolinc@nvidia.com/
* Add warning in non-coherent SMMU cases
* Keep eventq/priq disabled vs. enabling-and-disabling-later
* Check KDUMP option in the beginning of arm_smmu_device_reset()
* Validate STRTAB format matches HW capability instead of forcing flags
v1:
https://lore.kernel.org/all/cover.1775763475.git.nicolinc@nvidia.com/
Nicolin Chen (7):
iommu/arm-smmu-v3: Add arm_smmu_kdump_adopt_strtab() for kdump
iommu/arm-smmu-v3: Implement is_attach_deferred() for kdump
iommu/arm-smmu-v3: Do not enable EVTQ/PRIQ interrupts in kdump kernel
iommu/arm-smmu-v3: Skip EVTQ/PRIQ setup in kdump kernel
iommu/arm-smmu-v3: Retain CR0_SMMUEN during kdump device reset
iommu/arm-smmu-v3: Skip RMR bypass for kdump adoption
iommu/arm-smmu-v3: Detect ARM_SMMU_OPT_KDUMP_ADOPT in probe()
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 +
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 467 ++++++++++++++++++--
2 files changed, 422 insertions(+), 46 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH rc v7 4/7] iommu/arm-smmu-v3: Skip EVTQ/PRIQ setup in kdump kernel
From: Nicolin Chen @ 2026-06-30 6:15 UTC (permalink / raw)
To: will, robin.murphy, jgg
Cc: joro, praan, kees, baolu.lu, kevin.tian, miko.lenczewski,
smostafa, linux-arm-kernel, iommu, linux-kernel, stable, jamien
In-Reply-To: <cover.1782799827.git.nicolinc@nvidia.com>
In kdump cases, the crashed kernel's CDs and page tables can be corrupted,
which could trigger event spamming. Also, we cannot serve page requests.
Skip the EVTQ/PRIQ setup entirely rather than enabling then disabling them.
Also add some inline comments explaining that.
Fixes: b63b3439b856 ("iommu/arm-smmu-v3: Abort all transactions if SMMU is enabled in kdump kernel")
Cc: stable@vger.kernel.org # v6.12+
Suggested-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 43 +++++++++++++--------
1 file changed, 27 insertions(+), 16 deletions(-)
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 2c33de5128a09..abcbc9874f252 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -5083,21 +5083,35 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
arm_smmu_cmdq_issue_cmd_with_sync(
smmu, arm_smmu_make_cmd_op(CMDQ_OP_TLBI_NSNH_ALL));
- /* Event queue */
- writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
- writel_relaxed(smmu->evtq.q.llq.prod, smmu->page1 + ARM_SMMU_EVTQ_PROD);
- writel_relaxed(smmu->evtq.q.llq.cons, smmu->page1 + ARM_SMMU_EVTQ_CONS);
-
- enables |= CR0_EVTQEN;
- ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
- ARM_SMMU_CR0ACK);
- if (ret) {
- dev_err(smmu->dev, "failed to enable event queue\n");
- return ret;
+ /*
+ * Event queue
+ *
+ * Do not enable in a kdump case, as the crashed kernel's CDs and page
+ * tables might be corrupted, triggering event spamming.
+ */
+ if (!is_kdump_kernel()) {
+ writeq_relaxed(smmu->evtq.q.q_base,
+ smmu->base + ARM_SMMU_EVTQ_BASE);
+ writel_relaxed(smmu->evtq.q.llq.prod,
+ smmu->page1 + ARM_SMMU_EVTQ_PROD);
+ writel_relaxed(smmu->evtq.q.llq.cons,
+ smmu->page1 + ARM_SMMU_EVTQ_CONS);
+
+ enables |= CR0_EVTQEN;
+ ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
+ ARM_SMMU_CR0ACK);
+ if (ret) {
+ dev_err(smmu->dev, "failed to enable event queue\n");
+ return ret;
+ }
}
- /* PRI queue */
- if (smmu->features & ARM_SMMU_FEAT_PRI) {
+ /*
+ * PRI queue
+ *
+ * Do not enable in a kdump case, as we cannot serve page requests.
+ */
+ if (!is_kdump_kernel() && (smmu->features & ARM_SMMU_FEAT_PRI)) {
writeq_relaxed(smmu->priq.q.q_base,
smmu->base + ARM_SMMU_PRIQ_BASE);
writel_relaxed(smmu->priq.q.llq.prod,
@@ -5130,9 +5144,6 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
return ret;
}
- if (is_kdump_kernel())
- enables &= ~(CR0_EVTQEN | CR0_PRIQEN);
-
/* Enable the SMMU interface */
enables |= CR0_SMMUEN;
ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
--
2.43.0
^ permalink raw reply related
* [PATCH rc v7 1/7] iommu/arm-smmu-v3: Add arm_smmu_kdump_adopt_strtab() for kdump
From: Nicolin Chen @ 2026-06-30 6:15 UTC (permalink / raw)
To: will, robin.murphy, jgg
Cc: joro, praan, kees, baolu.lu, kevin.tian, miko.lenczewski,
smostafa, linux-arm-kernel, iommu, linux-kernel, stable, jamien
In-Reply-To: <cover.1782799827.git.nicolinc@nvidia.com>
When transitioning to a kdump kernel, the primary kernel might have crashed
while endpoint devices were actively bus-mastering DMA. Currently, the SMMU
driver aggressively resets the hardware during probe by clearing CR0_SMMUEN
and setting the Global Bypass Attribute (GBPA) to ABORT.
In a kdump scenario, this aggressive reset is highly destructive:
a) If GBPA is set to ABORT, in-flight DMA will be aborted, generating fatal
PCIe AER or SErrors that may panic the kdump kernel
b) If GBPA is set to BYPASS, in-flight DMA targeting some IOVAs will bypass
the SMMU and corrupt the physical memory at those 1:1 mapped IOVAs.
To safely absorb in-flight DMAs, a kdump kernel will have to leave SMMUEN=1
intact and avoid modifying STRTAB_BASE, allowing HW to continue translating
in-flight DMAs reusing the crashed kernel's page tables until the endpoint
device drivers probe and quiesce their respective hardware.
However, the ARM SMMUv3 architecture specification states that updating the
SMMU_STRTAB_BASE register while SMMUEN == 1 is UNPREDICTABLE or ignored.
This leaves a kdump kernel no choice but to adopt the stream table from the
crashed kernel.
Introduce ARM_SMMU_OPT_KDUMP_ADOPT and adopt functions memremapping all the
stream tables extracted from STRTAB_BASE and STRTAB_BASE_CFG.
Note that the adoption of the crashed kernel's stream table follows certain
strict rules, since the old stream table might be compromised. Thus, apply
some basic validations against the values read from the registers. If tests
fail, it means the stream table cannot be trusted, so toss it entirely. To
avoid OOM due to a potentially corrupted stream table, the memremap for l2
tables is done on the kdump kernel's demand.
The new option will be set in a following change.
Fixes: b63b3439b856 ("iommu/arm-smmu-v3: Abort all transactions if SMMU is enabled in kdump kernel")
Cc: stable@vger.kernel.org # v6.12+
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 +
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 244 +++++++++++++++++++-
2 files changed, 242 insertions(+), 3 deletions(-)
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 c909c9a88538b..9d86dc89d8e2e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -928,6 +928,7 @@ struct arm_smmu_device {
#define ARM_SMMU_OPT_MSIPOLL (1 << 2)
#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3)
#define ARM_SMMU_OPT_TEGRA241_CMDQV (1 << 4)
+#define ARM_SMMU_OPT_KDUMP_ADOPT (1 << 5)
u32 options;
struct arm_smmu_cmdq cmdq;
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 a10affb483a4f..af97a22c11696 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1933,16 +1933,67 @@ static void arm_smmu_init_initial_stes(struct arm_smmu_ste *strtab,
}
}
+static int arm_smmu_kdump_adopt_l2_strtab(struct arm_smmu_device *smmu, u32 sid,
+ phys_addr_t base, u32 span,
+ struct arm_smmu_strtab_l2 **l2table)
+{
+ struct arm_smmu_strtab_l2 *table;
+ size_t size;
+
+ /*
+ * Retest the span in case the L1 descriptor has been overwritten since
+ * the adopt. Reject this master's insert; panic or SMMU-disable would
+ * either lose the vmcore or cascade aborts. Do not try to fix it, as it
+ * would break all other SIDs in the same bus (PCI case). The corruption
+ * blast radius is already bounded to that bus range.
+ */
+ if (span != STRTAB_SPLIT + 1) {
+ dev_err(smmu->dev,
+ "kdump: L1[%u] span %u changed since adopt (was %u)\n",
+ arm_smmu_strtab_l1_idx(sid), span, STRTAB_SPLIT + 1);
+ return -EINVAL;
+ }
+
+ size = (1UL << (span - 1)) * sizeof(struct arm_smmu_ste);
+
+ /*
+ * This L2 table is mapped lazily per master; devres frees it at unbind,
+ * as with the dmam_alloc_coherent() used for a fresh L2.
+ */
+ table = devm_memremap(smmu->dev, base, size, MEMREMAP_WB);
+ if (IS_ERR(table)) {
+ dev_err(smmu->dev,
+ "kdump: failed to adopt l2 stream table for SID %u\n",
+ sid);
+ return PTR_ERR(table);
+ }
+
+ *l2table = table;
+ return 0;
+}
+
static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
{
dma_addr_t l2ptr_dma;
struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
struct arm_smmu_strtab_l2 **l2table;
+ u32 l1_idx = arm_smmu_strtab_l1_idx(sid);
- l2table = &cfg->l2.l2ptrs[arm_smmu_strtab_l1_idx(sid)];
+ l2table = &cfg->l2.l2ptrs[l1_idx];
if (*l2table)
return 0;
+ /* Deferred adoption of the crashed kernel's L2 table */
+ if (smmu->options & ARM_SMMU_OPT_KDUMP_ADOPT) {
+ u64 l2ptr = le64_to_cpu(cfg->l2.l1tab[l1_idx].l2ptr);
+ phys_addr_t base = l2ptr & STRTAB_L1_DESC_L2PTR_MASK;
+ u32 span = FIELD_GET(STRTAB_L1_DESC_SPAN, l2ptr);
+
+ if (span && base)
+ return arm_smmu_kdump_adopt_l2_strtab(smmu, sid, base,
+ span, l2table);
+ }
+
*l2table = dmam_alloc_coherent(smmu->dev, sizeof(**l2table),
&l2ptr_dma, GFP_KERNEL);
if (!*l2table) {
@@ -1954,8 +2005,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
arm_smmu_init_initial_stes((*l2table)->stes,
ARRAY_SIZE((*l2table)->stes));
- arm_smmu_write_strtab_l1_desc(&cfg->l2.l1tab[arm_smmu_strtab_l1_idx(sid)],
- l2ptr_dma);
+ arm_smmu_write_strtab_l1_desc(&cfg->l2.l1tab[l1_idx], l2ptr_dma);
return 0;
}
@@ -4490,10 +4540,197 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
return 0;
}
+static int arm_smmu_kdump_adopt_strtab_2lvl(struct arm_smmu_device *smmu,
+ u32 cfg_reg, phys_addr_t base)
+{
+ u32 log2size = FIELD_GET(STRTAB_BASE_CFG_LOG2SIZE, cfg_reg);
+ u32 split = FIELD_GET(STRTAB_BASE_CFG_SPLIT, cfg_reg);
+ struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
+ u32 num_l1_ents;
+ size_t size;
+ int i;
+
+ if (log2size < split || log2size > smmu->sid_bits) {
+ dev_err(smmu->dev, "kdump: log2size %u out of range [%u, %u]\n",
+ log2size, split, smmu->sid_bits);
+ return -EINVAL;
+ }
+ if (split != STRTAB_SPLIT) {
+ dev_err(smmu->dev,
+ "kdump: unsupported STRTAB_SPLIT %u (expected %u)\n",
+ split, STRTAB_SPLIT);
+ return -EINVAL;
+ }
+
+ num_l1_ents = 1U << (log2size - split);
+ if (num_l1_ents > STRTAB_MAX_L1_ENTRIES) {
+ dev_err(smmu->dev, "kdump: l1 entries %u exceeds max %u\n",
+ num_l1_ents, STRTAB_MAX_L1_ENTRIES);
+ return -EINVAL;
+ }
+
+ cfg->l2.num_l1_ents = num_l1_ents;
+
+ size = num_l1_ents * sizeof(struct arm_smmu_strtab_l1);
+ cfg->l2.l1tab = memremap(base, size, MEMREMAP_WB);
+ if (!cfg->l2.l1tab)
+ return -ENOMEM;
+
+ cfg->l2.l2ptrs =
+ kcalloc(num_l1_ents, sizeof(*cfg->l2.l2ptrs), GFP_KERNEL);
+ if (!cfg->l2.l2ptrs)
+ return -ENOMEM;
+
+ for (i = 0; i < num_l1_ents; i++) {
+ u64 l2ptr = le64_to_cpu(cfg->l2.l1tab[i].l2ptr);
+ phys_addr_t l2_base = l2ptr & STRTAB_L1_DESC_L2PTR_MASK;
+ u32 span = FIELD_GET(STRTAB_L1_DESC_SPAN, l2ptr);
+
+ if (!span || !l2_base)
+ continue;
+
+ if (span != STRTAB_SPLIT + 1) {
+ dev_err(smmu->dev,
+ "kdump: L1[%u] unsupported span %u (vs %u)\n",
+ i, span, STRTAB_SPLIT + 1);
+ return -EINVAL;
+ }
+
+ /*
+ * If the crashed kernel's l1 descriptors are deeply corrupted,
+ * blindly memremapping every l2 table here could lead to OOM.
+ *
+ * Defer the l2 memremap to arm_smmu_init_l2_strtab(), so peak
+ * memory is bounded by the kdump kernel's actual demand.
+ */
+ }
+
+ return 0;
+}
+
+static int arm_smmu_kdump_adopt_strtab_linear(struct arm_smmu_device *smmu,
+ u32 cfg_reg, phys_addr_t base)
+{
+ u32 log2size = FIELD_GET(STRTAB_BASE_CFG_LOG2SIZE, cfg_reg);
+ struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
+ unsigned int max_log2size;
+ size_t size;
+
+ /* Cap the size at what the kdump kernel itself would have allocated */
+ if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
+ max_log2size =
+ ilog2(STRTAB_MAX_L1_ENTRIES * STRTAB_NUM_L2_STES);
+ else
+ max_log2size = smmu->sid_bits;
+
+ /* cfg->linear.num_ents is unsigned int, so cap log2size at 31 */
+ max_log2size = min(max_log2size, 31U);
+ if (log2size > max_log2size) {
+ dev_err(smmu->dev, "kdump: unsupported log2size %u (> %u)\n",
+ log2size, max_log2size);
+ return -EINVAL;
+ }
+
+ /*
+ * We might end up with a num_ents != sid_bits, which is fine. In the
+ * ARM_SMMU_OPT_KDUMP_ADOPT case, arm_smmu_write_strtab() is bypassed.
+ */
+ cfg->linear.num_ents = 1U << log2size;
+
+ size = cfg->linear.num_ents * sizeof(struct arm_smmu_ste);
+ cfg->linear.table = memremap(base, size, MEMREMAP_WB);
+ if (!cfg->linear.table)
+ return -ENOMEM;
+ return 0;
+}
+
+static void arm_smmu_kdump_adopt_cleanup(void *data)
+{
+ struct arm_smmu_device *smmu = data;
+ struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
+
+ if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
+ kfree(cfg->l2.l2ptrs);
+ if (cfg->l2.l1tab)
+ memunmap(cfg->l2.l1tab);
+ } else {
+ if (cfg->linear.table)
+ memunmap(cfg->linear.table);
+ }
+}
+
+static int arm_smmu_kdump_adopt_strtab(struct arm_smmu_device *smmu)
+{
+ u32 cfg_reg = readl_relaxed(smmu->base + ARM_SMMU_STRTAB_BASE_CFG);
+ u64 base_reg = readq_relaxed(smmu->base + ARM_SMMU_STRTAB_BASE);
+ bool was_2lvl = smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB;
+ phys_addr_t base = base_reg & STRTAB_BASE_ADDR_MASK;
+ u32 fmt = FIELD_GET(STRTAB_BASE_CFG_FMT, cfg_reg);
+ int ret;
+
+ dev_dbg(smmu->dev, "kdump: adopting crashed kernel's stream table\n");
+
+ if (fmt == STRTAB_BASE_CFG_FMT_2LVL) {
+ /*
+ * Both kernels run on the same hardware, so it's impossible for
+ * kdump kernel to see the support for linear stream table only.
+ */
+ if (WARN_ON(!(smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)))
+ ret = -EINVAL;
+ else
+ ret = arm_smmu_kdump_adopt_strtab_2lvl(smmu, cfg_reg,
+ base);
+ } else if (fmt == STRTAB_BASE_CFG_FMT_LINEAR) {
+ /*
+ * The kdump kernel need not match the crashed kernel. An older
+ * crashed kernel that predates two-level stream table support
+ * may have used a linear table on 2-level-capable hardware, so
+ * enforce the same format here to match the adopted table.
+ */
+ ret = arm_smmu_kdump_adopt_strtab_linear(smmu, cfg_reg, base);
+ if (!ret)
+ smmu->features &= ~ARM_SMMU_FEAT_2_LVL_STRTAB;
+ } else {
+ dev_err(smmu->dev, "kdump: invalid STRTAB format %u\n", fmt);
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ arm_smmu_kdump_adopt_cleanup(smmu);
+ goto err;
+ }
+
+ ret = devm_add_action_or_reset(smmu->dev, arm_smmu_kdump_adopt_cleanup,
+ smmu);
+ /* devm_add_action_or_reset ran the cleanup upon failure */
+ if (ret) {
+ dev_warn(smmu->dev, "kdump: failed to set up cleanup action\n");
+ /*
+ * Undo the linear adoption's clearing of FEAT_2_LVL_STRTAB so
+ * the full-reset fallback uses the hardware-supported format.
+ */
+ if (was_2lvl)
+ smmu->features |= ARM_SMMU_FEAT_2_LVL_STRTAB;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ dev_warn(smmu->dev, "kdump: falling back to full reset\n");
+ memset(&smmu->strtab_cfg, 0, sizeof(smmu->strtab_cfg));
+ smmu->options &= ~ARM_SMMU_OPT_KDUMP_ADOPT;
+ return ret;
+}
+
static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
{
int ret;
+ if ((smmu->options & ARM_SMMU_OPT_KDUMP_ADOPT) &&
+ !arm_smmu_kdump_adopt_strtab(smmu))
+ goto out;
+
if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
ret = arm_smmu_init_strtab_2lvl(smmu);
else
@@ -4501,6 +4738,7 @@ static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
if (ret)
return ret;
+out:
ida_init(&smmu->vmid_map);
return 0;
--
2.43.0
^ 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