* [patch 26/38] loongarch: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:20 UTC (permalink / raw)
To: LKML
Cc: Huacai Chen, loongarch, Arnd Bergmann, x86, Lu Baolu, iommu,
Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining non-architecture usage of get_cycles() is to provide
random_get_entropy().
Switch loongarch over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
Add 'asm/timex.h' includes to the relevant files, so the global include can
be removed once all architectures are converted over.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: loongarch@lists.linux.dev
---
arch/loongarch/Kconfig | 1 +
arch/loongarch/include/asm/random.h | 15 +++++++++++++++
arch/loongarch/kernel/syscall.c | 1 +
arch/loongarch/lib/delay.c | 2 +-
4 files changed, 18 insertions(+), 1 deletion(-)
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -26,6 +26,7 @@ config LOONGARCH
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_SET_DIRECT_MAP
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
--- /dev/null
+++ b/arch/loongarch/include/asm/random.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
+ */
+#ifndef _ASM_RANDOM_H
+#define _ASM_RANDOM_H
+
+#include <asm/timex.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ return get_cycles();
+}
+
+#endif /* _ASM_RANDOM_H */
--- a/arch/loongarch/kernel/syscall.c
+++ b/arch/loongarch/kernel/syscall.c
@@ -19,6 +19,7 @@
#include <asm/loongarch.h>
#include <asm/signal.h>
#include <asm/switch_to.h>
+#include <asm/timex.h>
#include <asm-generic/syscalls.h>
#undef __SYSCALL
--- a/arch/loongarch/lib/delay.c
+++ b/arch/loongarch/lib/delay.c
@@ -5,9 +5,9 @@
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/smp.h>
-#include <linux/timex.h>
#include <asm/processor.h>
+#include <asm/timex.h>
void __delay(unsigned long cycles)
{
^ permalink raw reply
* [patch 27/38] m68k: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:20 UTC (permalink / raw)
To: LKML
Cc: Geert Uytterhoeven, linux-m68k, Arnd Bergmann, x86, Lu Baolu,
iommu, Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining usage of get_cycles() is to provide
random_get_entropy().
Switch m68k over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY and
providing random_get_entropy() in asm/random.h.
Remove asm/timex.h as it has no functionality anymore.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: linux-m68k@lists.linux-m68k.org
---
arch/m68k/Kconfig | 1 +
arch/m68k/amiga/config.c | 1 +
arch/m68k/include/asm/random.h | 14 ++++++++++++++
arch/m68k/include/asm/timex.h | 25 -------------------------
arch/m68k/kernel/time.c | 2 +-
5 files changed, 17 insertions(+), 26 deletions(-)
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -8,6 +8,7 @@ config M68K
select ARCH_HAS_CPU_FINALIZE_INIT if MMU
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DMA_PREP_COHERENT if M68K_NONCOHERENT_DMA && !COLDFIRE
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_HAS_SYNC_DMA_FOR_DEVICE if M68K_NONCOHERENT_DMA
select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -36,6 +36,7 @@
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/config.h>
+#include <asm/random.h>
#include "amiga.h"
--- /dev/null
+++ b/arch/m68k/include/asm/random.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASMm68K_RANDOM_H
+#define _ASMm68K_RANDOM_H
+
+extern unsigned long (*mach_random_get_entropy)(void);
+
+static inline unsigned long random_get_entropy(void)
+{
+ if (mach_random_get_entropy)
+ return mach_random_get_entropy();
+ return random_get_entropy_fallback();
+}
+
+#endif
--- a/arch/m68k/include/asm/timex.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * linux/include/asm-m68k/timex.h
- *
- * m68k architecture timex specifications
- */
-#ifndef _ASMm68K_TIMEX_H
-#define _ASMm68K_TIMEX_H
-
-static inline cycles_t get_cycles(void)
-{
- return 0;
-}
-
-extern unsigned long (*mach_random_get_entropy)(void);
-
-static inline unsigned long random_get_entropy(void)
-{
- if (mach_random_get_entropy)
- return mach_random_get_entropy();
- return random_get_entropy_fallback();
-}
-#define random_get_entropy random_get_entropy
-
-#endif
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -26,12 +26,12 @@
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/irq_regs.h>
+#include <asm/random.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/profile.h>
-
unsigned long (*mach_random_get_entropy)(void);
EXPORT_SYMBOL_GPL(mach_random_get_entropy);
^ permalink raw reply
* [patch 28/38] mips: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:20 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining usage of get_cycles() is to provide random_get_entropy().
Switch mips over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
As a consequence this unearthed a nasty include dependency hell because
arbitrary code relies on a magic include of asm/timex.h. Including the
headers in asm/random.h turned out to be impossible as well.
The only solution for now is to uninline random_get_entropy(). Fix up all
other dependencies on the content of asm/timex.h in those files which
really depend on it.
Remove asm/timex.h as it has no functionality anymore.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
arch/mips/Kconfig | 1
arch/mips/generic/init.c | 1
arch/mips/include/asm/random.h | 7 +++
arch/mips/include/asm/timex.h | 92 -----------------------------------------
arch/mips/kernel/pm-cps.c | 1
arch/mips/kernel/proc.c | 1
arch/mips/kernel/relocate.c | 1
arch/mips/kernel/time.c | 53 +++++++++++++++++++++++
arch/mips/lib/dump_tlb.c | 1
arch/mips/mm/cache.c | 1
10 files changed, 66 insertions(+), 93 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -19,6 +19,7 @@ config MIPS
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN
select ARCH_HAS_GCOV_PROFILE_ALL
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_KEEP_MEMBLOCK
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
--- a/arch/mips/generic/init.c
+++ b/arch/mips/generic/init.c
@@ -12,6 +12,7 @@
#include <linux/of_fdt.h>
#include <asm/bootinfo.h>
+#include <asm/cpu-type.h>
#include <asm/fw/fw.h>
#include <asm/irq_cpu.h>
#include <asm/machine.h>
--- /dev/null
+++ b/arch/mips/include/asm/random.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-v2.0-only */
+#ifndef _ASM_RANDOM_H
+#define _ASM_RANDOM_H
+
+unsigned long random_get_entropy(void);
+
+#endif /* _ASM_RANDOM_H */
--- a/arch/mips/include/asm/timex.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1998, 1999, 2003 by Ralf Baechle
- * Copyright (C) 2014 by Maciej W. Rozycki
- */
-#ifndef _ASM_TIMEX_H
-#define _ASM_TIMEX_H
-
-#ifdef __KERNEL__
-
-#include <linux/compiler.h>
-
-#include <asm/cpu.h>
-#include <asm/cpu-features.h>
-#include <asm/mipsregs.h>
-#include <asm/cpu-type.h>
-
-/*
- * Standard way to access the cycle counter.
- * Currently only used on SMP for scheduling.
- *
- * Only the low 32 bits are available as a continuously counting entity.
- * But this only means we'll force a reschedule every 8 seconds or so,
- * which isn't an evil thing.
- *
- * We know that all SMP capable CPUs have cycle counters.
- */
-
-/*
- * On R4000/R4400 an erratum exists such that if the cycle counter is
- * read in the exact moment that it is matching the compare register,
- * no interrupt will be generated.
- *
- * There is a suggested workaround and also the erratum can't strike if
- * the compare interrupt isn't being used as the clock source device.
- * However for now the implementation of this function doesn't get these
- * fine details right.
- */
-static inline int can_use_mips_counter(unsigned int prid)
-{
- int comp = (prid & PRID_COMP_MASK) != PRID_COMP_LEGACY;
-
- if (__builtin_constant_p(cpu_has_counter) && !cpu_has_counter)
- return 0;
- else if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r)
- return 1;
- else if (likely(!__builtin_constant_p(cpu_has_mips_r) && comp))
- return 1;
- /* Make sure we don't peek at cpu_data[0].options in the fast path! */
- if (!__builtin_constant_p(cpu_has_counter))
- asm volatile("" : "=m" (cpu_data[0].options));
- if (likely(cpu_has_counter &&
- prid > (PRID_IMP_R4000 | PRID_REV_ENCODE_44(15, 15))))
- return 1;
- else
- return 0;
-}
-
-static inline cycles_t get_cycles(void)
-{
- if (can_use_mips_counter(read_c0_prid()))
- return read_c0_count();
- else
- return 0; /* no usable counter */
-}
-#define get_cycles get_cycles
-
-/*
- * Like get_cycles - but where c0_count is not available we desperately
- * use c0_random in an attempt to get at least a little bit of entropy.
- */
-static inline unsigned long random_get_entropy(void)
-{
- unsigned int c0_random;
-
- if (can_use_mips_counter(read_c0_prid()))
- return read_c0_count();
-
- if (cpu_has_3kex)
- c0_random = (read_c0_random() >> 8) & 0x3f;
- else
- c0_random = read_c0_random() & 0x3f;
- return (random_get_entropy_fallback() << 6) | (0x3f - c0_random);
-}
-#define random_get_entropy random_get_entropy
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_TIMEX_H */
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -13,6 +13,7 @@
#include <asm/asm-offsets.h>
#include <asm/cacheflush.h>
#include <asm/cacheops.h>
+#include <asm/cpu-type.h>
#include <asm/idle.h>
#include <asm/mips-cps.h>
#include <asm/mipsmtregs.h>
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -11,6 +11,7 @@
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
#include <asm/idle.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
--- a/arch/mips/kernel/relocate.c
+++ b/arch/mips/kernel/relocate.c
@@ -13,7 +13,6 @@
#include <asm/fw/fw.h>
#include <asm/sections.h>
#include <asm/setup.h>
-#include <asm/timex.h>
#include <linux/elf.h>
#include <linux/kernel.h>
#include <linux/libfdt.h>
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -2,6 +2,7 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 1998, 1999, 2003 by Ralf Baechle
* Copyright (c) 2003, 2004 Maciej W. Rozycki
*
* Common time service routines for MIPS machines.
@@ -21,9 +22,12 @@
#include <linux/cpufreq.h>
#include <linux/delay.h>
+#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/cpu-type.h>
#include <asm/div64.h>
+#include <asm/mipsregs.h>
+#include <asm/random.h>
#include <asm/time.h>
#ifdef CONFIG_CPU_FREQ
@@ -150,6 +154,55 @@ static __init int cpu_has_mfc0_count_bug
return 0;
}
+
+/*
+ * On R4000/R4400 an erratum exists such that if the cycle counter is
+ * read in the exact moment that it is matching the compare register,
+ * no interrupt will be generated.
+ *
+ * There is a suggested workaround and also the erratum can't strike if
+ * the compare interrupt isn't being used as the clock source device.
+ * However for now the implementation of this function doesn't get these
+ * fine details right.
+ */
+static inline int can_use_mips_counter(unsigned int prid)
+{
+ int comp = (prid & PRID_COMP_MASK) != PRID_COMP_LEGACY;
+
+ if (__builtin_constant_p(cpu_has_counter) && !cpu_has_counter)
+ return 0;
+ else if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r)
+ return 1;
+ else if (likely(!__builtin_constant_p(cpu_has_mips_r) && comp))
+ return 1;
+ /* Make sure we don't peek at cpu_data[0].options in the fast path! */
+ if (!__builtin_constant_p(cpu_has_counter))
+ asm volatile("" : "=m" (cpu_data[0].options));
+ if (likely(cpu_has_counter &&
+ prid > (PRID_IMP_R4000 | PRID_REV_ENCODE_44(15, 15))))
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * Like get_cycles - but where c0_count is not available we desperately
+ * use c0_random in an attempt to get at least a little bit of entropy.
+ */
+unsigned long random_get_entropy(void)
+{
+ unsigned int c0_random;
+
+ if (can_use_mips_counter(read_c0_prid()))
+ return read_c0_count();
+
+ if (cpu_has_3kex)
+ c0_random = (read_c0_random() >> 8) & 0x3f;
+ else
+ c0_random = read_c0_random() & 0x3f;
+ return (random_get_entropy_fallback() << 6) | (0x3f - c0_random);
+}
+
void __init time_init(void)
{
plat_time_init();
--- a/arch/mips/lib/dump_tlb.c
+++ b/arch/mips/lib/dump_tlb.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <asm/cpu-type.h>
#include <asm/hazards.h>
#include <asm/mipsregs.h>
#include <asm/mmu_context.h>
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -22,6 +22,7 @@
#include <asm/processor.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
^ permalink raw reply
* [patch 29/38] nios2: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:20 UTC (permalink / raw)
To: LKML
Cc: Dinh Nguyen, Arnd Bergmann, x86, Lu Baolu, iommu,
Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Jonas Bonn, linux-openrisc,
Helge Deller, linux-parisc, Michael Ellerman, linuxppc-dev,
Paul Walmsley, linux-riscv, Heiko Carstens, linux-s390,
David S. Miller, sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining non-architecture usage of get_cycles() is to provide
random_get_entropy().
Switch nios2 over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
Add 'asm/timex.h' includes to the relevant files, so the global include can
be removed once all architectures are converted over.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Dinh Nguyen <dinguyen@kernel.org>
---
arch/nios2/Kconfig | 1 +
arch/nios2/include/asm/random.h | 14 ++++++++++++++
arch/nios2/include/asm/timex.h | 5 +----
arch/nios2/kernel/time.c | 4 ++--
4 files changed, 18 insertions(+), 6 deletions(-)
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -7,6 +7,7 @@ config NIOS2
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_HAS_DMA_SET_UNCACHED
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_NO_SWAP
select COMMON_CLK
select TIMER_OF
--- /dev/null
+++ b/arch/nios2/include/asm/random.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASM_NIOS2_RANDOM_H
+#define _ASM_NIOS2_RANDOM_H
+
+#include <asm/timex.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ unsigned long c = get_cycles();
+
+ return c ? c : random_get_entropy_fallback();
+}
+
+#endif
--- a/arch/nios2/include/asm/timex.h
+++ b/arch/nios2/include/asm/timex.h
@@ -5,9 +5,6 @@
#ifndef _ASM_NIOS2_TIMEX_H
#define _ASM_NIOS2_TIMEX_H
-extern cycles_t get_cycles(void);
-#define get_cycles get_cycles
-
-#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
+cycles_t get_cycles(void);
#endif
--- a/arch/nios2/kernel/time.c
+++ b/arch/nios2/kernel/time.c
@@ -7,7 +7,6 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/clockchips.h>
@@ -19,6 +18,8 @@
#include <linux/io.h>
#include <linux/slab.h>
+#include <asm/timex.h>
+
#define ALTR_TIMER_COMPATIBLE "altr,timer-1.0"
#define ALTERA_TIMER_STATUS_REG 0
@@ -112,7 +113,6 @@ cycles_t get_cycles(void)
return nios2_timer_read(&nios2_cs.cs);
return 0;
}
-EXPORT_SYMBOL(get_cycles);
static void nios2_timer_start(struct nios2_timer *timer)
{
^ permalink raw reply
* [patch 30/38] openrisc: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:20 UTC (permalink / raw)
To: LKML
Cc: Jonas Bonn, linux-openrisc, Arnd Bergmann, x86, Lu Baolu, iommu,
Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Dinh Nguyen, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining non-architecture usage of get_cycles() is to provide
random_get_entropy().
Switch openrisc over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
Add 'asm/timex.h' includes to the relevant files, so the global include can
be removed once all architectures are converted over.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: linux-openrisc@vger.kernel.org
---
arch/openrisc/Kconfig | 1 +
arch/openrisc/include/asm/random.h | 12 ++++++++++++
arch/openrisc/include/asm/timex.h | 5 -----
arch/openrisc/lib/delay.c | 1 +
4 files changed, 14 insertions(+), 5 deletions(-)
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -10,6 +10,7 @@ config OPENRISC
select ARCH_HAS_DELAY_TIMER
select ARCH_HAS_DMA_SET_UNCACHED
select ARCH_HAS_DMA_CLEAR_UNCACHED
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select GENERIC_BUILTIN_DTB
select COMMON_CLK
--- /dev/null
+++ b/arch/openrisc/include/asm/random.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef __ASM_OPENRISC_RANDOM_H
+#define __ASM_OPENRISC_RANDOM_H
+
+#include <asm/timex.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ return get_cycles();
+}
+
+#endif
--- a/arch/openrisc/include/asm/timex.h
+++ b/arch/openrisc/include/asm/timex.h
@@ -9,13 +9,9 @@
* OpenRISC implementation:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*/
-
#ifndef __ASM_OPENRISC_TIMEX_H
#define __ASM_OPENRISC_TIMEX_H
-#define get_cycles get_cycles
-
-#include <asm-generic/timex.h>
#include <asm/spr.h>
#include <asm/spr_defs.h>
@@ -23,6 +19,5 @@ static inline cycles_t get_cycles(void)
{
return mfspr(SPR_TTCR);
}
-#define get_cycles get_cycles
#endif
--- a/arch/openrisc/lib/delay.c
+++ b/arch/openrisc/lib/delay.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <asm/param.h>
+#include <asm/timex.h>
#include <asm/processor.h>
bool delay_read_timer(unsigned long *timer_value)
^ permalink raw reply
* [patch 31/38] parisc: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: Helge Deller, linux-parisc, Arnd Bergmann, x86, Lu Baolu, iommu,
Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Dinh Nguyen, Jonas Bonn,
linux-openrisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining non-architecture usage of get_cycles() is to provide
random_get_entropy().
Switch parisc over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
Add 'asm/timex.h' includes to the relevant files, so the global include can
be removed once all architectures are converted over.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Helge Deller <deller@gmx.de>
Cc: linux-parisc@vger.kernel.org
---
arch/parisc/Kconfig | 1 +
arch/parisc/include/asm/random.h | 12 ++++++++++++
arch/parisc/include/asm/timex.h | 6 ------
arch/parisc/kernel/processor.c | 1 +
arch/parisc/kernel/time.c | 1 +
5 files changed, 15 insertions(+), 6 deletions(-)
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -16,6 +16,7 @@ config PARISC
select ARCH_HAS_STRICT_MODULE_RWX
select ARCH_HAS_UBSAN
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_NO_SG_CHAIN
select ARCH_SPLIT_ARG64 if !64BIT
select ARCH_SUPPORTS_HUGETLBFS if PA20
--- /dev/null
+++ b/arch/parisc/include/asm/random.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASMPARISC_RANDOM_H
+#define _ASMPARISC_RANDOM_H
+
+#include <asm/timex.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ return get_cycles();
+}
+
+#endif
--- a/arch/parisc/include/asm/timex.h
+++ b/arch/parisc/include/asm/timex.h
@@ -1,9 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * linux/include/asm-parisc/timex.h
- *
- * PARISC architecture timex specifications
- */
#ifndef _ASMPARISC_TIMEX_H
#define _ASMPARISC_TIMEX_H
@@ -13,6 +8,5 @@ static inline cycles_t get_cycles(void)
{
return mfctl(16);
}
-#define get_cycles get_cycles
#endif
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -30,6 +30,7 @@
#include <asm/pdcpat.h>
#include <asm/irq.h> /* for struct irq_region */
#include <asm/parisc-device.h>
+#include <asm/timex.h>
struct system_cpuinfo_parisc boot_cpu_data __ro_after_init;
EXPORT_SYMBOL(boot_cpu_data);
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <asm/processor.h>
#include <asm/pdcpat.h>
+#include <asm/timex.h>
static u64 cr16_clock_freq;
static unsigned long clocktick;
^ permalink raw reply
* [patch 32/38] powerpc/spufs: Use mftb() directly
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: Michael Ellerman, linuxppc-dev, Arnd Bergmann, x86, Lu Baolu,
iommu, Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Dinh Nguyen, Jonas Bonn,
linux-openrisc, Helge Deller, linux-parisc, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
There is no reason to indirect via get_cycles(), which is about to be
removed.
Use mftb() directly.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
---
arch/powerpc/platforms/cell/spufs/switch.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -34,6 +34,7 @@
#include <asm/spu_priv1.h>
#include <asm/spu_csa.h>
#include <asm/mmu_context.h>
+#include <asm/time.h>
#include "spufs.h"
@@ -279,7 +280,7 @@ static inline void save_timebase(struct
* Read PPE Timebase High and Timebase low registers
* and save in CSA. TBD.
*/
- csa->suspend_time = get_cycles();
+ csa->suspend_time = mftb();
}
static inline void remove_other_spu_access(struct spu_state *csa,
@@ -1261,7 +1262,7 @@ static inline void setup_decr(struct spu
* in LSCSA.
*/
if (csa->priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING) {
- cycles_t resume_time = get_cycles();
+ cycles_t resume_time = mftb();
cycles_t delta_time = resume_time - csa->suspend_time;
csa->lscsa->decr_status.slot[0] = SPU_DECR_STATUS_RUNNING;
^ permalink raw reply
* [patch 33/38] powerpc: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: Michael Ellerman, linuxppc-dev, Arnd Bergmann, x86, Lu Baolu,
iommu, Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Dinh Nguyen, Jonas Bonn,
linux-openrisc, Helge Deller, linux-parisc, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining usage of get_cycles() is to provide random_get_entropy().
Switch powerpc over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
Remove asm/timex.h as it has no functionality anymore.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/random.h | 13 +++++++++++++
arch/powerpc/include/asm/timex.h | 21 ---------------------
3 files changed, 14 insertions(+), 21 deletions(-)
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -150,6 +150,7 @@ config PPC
select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTDUMP
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx) && !HIBERNATION
--- /dev/null
+++ b/arch/powerpc/include/asm/random.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_RANDOM_H
+#define _ASM_POWERPC_RANDOM_H
+
+#include <asm/cputable.h>
+#include <asm/vdso/timebase.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ return mftb();
+}
+
+#endif /* _ASM_POWERPC_RANDOM_H */
--- a/arch/powerpc/include/asm/timex.h
+++ b/arch/powerpc/include/asm/timex.h
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_POWERPC_TIMEX_H
-#define _ASM_POWERPC_TIMEX_H
-
-#ifdef __KERNEL__
-
-/*
- * PowerPC architecture timex specifications
- */
-
-#include <asm/cputable.h>
-#include <asm/vdso/timebase.h>
-
-ostatic inline cycles_t get_cycles(void)
-{
- return mftb();
-}
-#define get_cycles get_cycles
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_TIMEX_H */
^ permalink raw reply
* [patch 34/38] riscv: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: Paul Walmsley, linux-riscv, Arnd Bergmann, x86, Lu Baolu, iommu,
Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Dinh Nguyen, Jonas Bonn,
linux-openrisc, Helge Deller, linux-parisc, Michael Ellerman,
linuxppc-dev, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining non-architecture usage of get_cycles() is to provide
random_get_entropy().
Switch riscv over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
Add 'asm/timex.h' includes to the relevant files, so the global include can
be removed once all architectures are converted over.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: linux-riscv@lists.infradead.org
---
arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/random.h | 25 +++++++++++++++++++++++++
arch/riscv/include/asm/timex.h | 13 -------------
arch/riscv/kernel/unaligned_access_speed.c | 1 +
arch/riscv/kvm/vcpu_timer.c | 1 +
arch/riscv/lib/delay.c | 1 +
6 files changed, 29 insertions(+), 13 deletions(-)
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -47,6 +47,7 @@ config RISCV
select ARCH_HAS_PREPARE_SYNC_CORE_CMD
select ARCH_HAS_PTDUMP if MMU
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_HAS_SET_DIRECT_MAP if MMU
select ARCH_HAS_SET_MEMORY if MMU
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
--- /dev/null
+++ b/arch/riscv/include/asm/random.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASM_RISCV_RANDOM_H
+#define _ASM_RISCV_RANDOM_H
+
+#include <asm/timex.h>
+
+#ifdef CONFIG_RISCV_M_MODE
+/*
+ * Much like MIPS, we may not have a viable counter to use at an early point
+ * in the boot process. Unfortunately we don't have a fallback, so instead
+ * invoke the fallback function.
+ */
+static inline unsigned long random_get_entropy(void)
+{
+ if (unlikely(clint_time_val == NULL))
+ return random_get_entropy_fallback();
+ return get_cycles();
+}
+#else /* !CONFIG_RISCV_M_MODE */
+static inline unsigned long random_get_entropy(void)
+{
+ return get_cycles();
+}
+#endif /* CONFIG_RISCV_M_MODE */
+#endif /* _ASM_RISCV_RANDOM_H */
--- a/arch/riscv/include/asm/timex.h
+++ b/arch/riscv/include/asm/timex.h
@@ -31,19 +31,6 @@ static inline u32 get_cycles_hi(void)
#define get_cycles_hi get_cycles_hi
#endif /* CONFIG_64BIT */
-/*
- * Much like MIPS, we may not have a viable counter to use at an early point
- * in the boot process. Unfortunately we don't have a fallback, so instead
- * we just return 0.
- */
-static inline unsigned long random_get_entropy(void)
-{
- if (unlikely(clint_time_val == NULL))
- return random_get_entropy_fallback();
- return get_cycles();
-}
-#define random_get_entropy() random_get_entropy()
-
#else /* CONFIG_RISCV_M_MODE */
static inline cycles_t get_cycles(void)
--- a/arch/riscv/kernel/unaligned_access_speed.c
+++ b/arch/riscv/kernel/unaligned_access_speed.c
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <asm/cpufeature.h>
#include <asm/hwprobe.h>
+#include <asm/timex.h>
#include <asm/vector.h>
#include "copy-unaligned.h"
--- a/arch/riscv/kvm/vcpu_timer.c
+++ b/arch/riscv/kvm/vcpu_timer.c
@@ -14,6 +14,7 @@
#include <asm/delay.h>
#include <asm/kvm_nacl.h>
#include <asm/kvm_vcpu_timer.h>
+#include <asm/timex.h>
static u64 kvm_riscv_current_cycles(struct kvm_guest_timer *gt)
{
--- a/arch/riscv/lib/delay.c
+++ b/arch/riscv/lib/delay.c
@@ -10,6 +10,7 @@
#include <linux/export.h>
#include <asm/processor.h>
+#include <asm/timex.h>
/*
* This is copies from arch/arm/include/asm/delay.h
^ permalink raw reply
* [patch 35/38] s390: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: Heiko Carstens, linux-s390, Arnd Bergmann, x86, Lu Baolu, iommu,
Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Dinh Nguyen, Jonas Bonn,
linux-openrisc, Helge Deller, linux-parisc, Michael Ellerman,
linuxppc-dev, Paul Walmsley, linux-riscv, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining non-architecture usage of get_cycles() is to provide
random_get_entropy().
Switch s390 over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY and
providing random_get_entropy() in asm/random.h.
Add 'asm/timex.h' includes to the relevant files, so the global include can
be removed once all architectures are converted over.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: linux-s390@vger.kernel.org
---
arch/s390/Kconfig | 1 +
arch/s390/include/asm/random.h | 12 ++++++++++++
arch/s390/include/asm/timex.h | 6 ------
arch/s390/kernel/time.c | 1 +
arch/s390/kernel/vtime.c | 1 +
5 files changed, 15 insertions(+), 6 deletions(-)
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -108,6 +108,7 @@ config S390
select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTDUMP
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_HAS_SCALED_CPUTIME
select ARCH_HAS_SET_DIRECT_MAP
select ARCH_HAS_SET_MEMORY
--- /dev/null
+++ b/arch/s390/include/asm/random.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_S390_RANDOM_H
+#define _ASM_S390_RANDOM_H
+
+#include <asm/timex.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ return (unsigned long)get_tod_clock_monotonic() >> 2;
+}
+
+#endif
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -219,12 +219,6 @@ static inline unsigned long get_tod_cloc
return tod;
}
-static inline cycles_t get_cycles(void)
-{
- return (cycles_t)get_tod_clock_monotonic() >> 2;
-}
-#define get_cycles get_cycles
-
/**
* tod_to_ns - convert a TOD format value to nanoseconds
* @todval: to be converted TOD format value
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -50,6 +50,7 @@
#include <asm/irq_regs.h>
#include <asm/vtimer.h>
#include <asm/stp.h>
+#include <asm/timex.h>
#include <asm/cio.h>
#include "entry.h"
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -14,6 +14,7 @@
#include <linux/time.h>
#include <asm/alternative.h>
#include <asm/cputime.h>
+#include <asm/timex.h>
#include <asm/vtimer.h>
#include <asm/vtime.h>
#include <asm/cpu_mf.h>
^ permalink raw reply
* [patch 36/38] sparc: Select ARCH_HAS_RANDOM_ENTROPY for SPARC64
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: David S. Miller, sparclinux, Arnd Bergmann, x86, Lu Baolu, iommu,
Michael Grzeschik, netdev, linux-wireless, Herbert Xu,
linux-crypto, Vlastimil Babka, linux-mm, David Woodhouse,
Bernie Thompson, linux-fbdev, Theodore Tso, linux-ext4,
Andrew Morton, Uladzislau Rezki, Marco Elver, Dmitry Vyukov,
kasan-dev, Andrey Ryabinin, Thomas Sailer, linux-hams,
Jason A. Donenfeld, Richard Henderson, linux-alpha, Russell King,
linux-arm-kernel, Catalin Marinas, Huacai Chen, loongarch,
Geert Uytterhoeven, linux-m68k, Dinh Nguyen, Jonas Bonn,
linux-openrisc, Helge Deller, linux-parisc, Michael Ellerman,
linuxppc-dev, Paul Walmsley, linux-riscv, Heiko Carstens,
linux-s390
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining usage of get_cycles() is to provide random_get_entropy().
Switch sparc over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY
and providing random_get_entropy() in asm/random.h.
Remove asm/timex*.h as it has no functionality anymore.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
---
arch/sparc/Kconfig | 1 +
arch/sparc/include/asm/random.h | 15 +++++++++++++++
arch/sparc/include/asm/timex.h | 9 ---------
arch/sparc/include/asm/timex_64.h | 15 ---------------
arch/sparc/kernel/pcic.c | 1 -
arch/sparc/kernel/time_32.c | 1 -
arch/sparc/vdso/vclock_gettime.c | 1 -
7 files changed, 16 insertions(+), 27 deletions(-)
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -71,6 +71,7 @@ config SPARC64
def_bool 64BIT
select ALTERNATE_USER_ADDRESS_SPACE
select ARCH_HAS_DELAY_TIMER
+ select ARCH_HAS_RANDOM_ENTROPY
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_KRETPROBES
--- /dev/null
+++ b/arch/sparc/include/asm/random.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASMsparc_RANDOM_H
+#define _ASMsparc_RANDOM_H
+
+#if defined(__sparc__) && defined(__arch64__)
+
+#include <asm/timer.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ return tick_ops->get_tick();
+}
+
+#endif
+#endif
--- a/arch/sparc/include/asm/timex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ___ASM_SPARC_TIMEX_H
-#define ___ASM_SPARC_TIMEX_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/timex_64.h>
-#else
-#include <asm-generic/timex.h>
-#endif
-#endif
--- a/arch/sparc/include/asm/timex_64.h
+++ b/arch/sparc/include/asm/timex_64.h
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * linux/include/asm/timex.h
- *
- * sparc64 architecture timex specifications
- */
-#ifndef _ASMsparc64_TIMEX_H
-#define _ASMsparc64_TIMEX_H
-
-#include <asm/timer.h>
-
-/* Getting on the cycle counter on sparc64. */
-#define get_cycles() tick_ops->get_tick()
-
-#endif
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -33,7 +33,6 @@
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/pcic.h>
-#include <asm/timex.h>
#include <asm/timer.h>
#include <linux/uaccess.h>
#include <asm/irq_regs.h>
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -37,7 +37,6 @@
#include <asm/mc146818rtc.h>
#include <asm/oplib.h>
-#include <asm/timex.h>
#include <asm/timer.h>
#include <asm/irq.h>
#include <asm/io.h>
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -17,7 +17,6 @@
#include <linux/string.h>
#include <asm/io.h>
#include <asm/unistd.h>
-#include <asm/timex.h>
#include <asm/clocksource.h>
#include <asm/vvar.h>
^ permalink raw reply
* [patch 37/38] x86: Select ARCH_HAS_RANDOM_ENTROPY
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: x86, Arnd Bergmann, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
The only remaining usage of get_cycles() is to provide random_get_entropy().
Switch x86 over to the new scheme of selecting ARCH_HAS_RANDOM_ENTROPY and
providing random_get_entropy() in asm/random.h.
Remove asm/timex.h as it has no functionality anymore.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: x86@kernel.org
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/random.h | 16 ++++++++++++++++
arch/x86/include/asm/timex.h | 17 -----------------
arch/x86/include/asm/tsc.h | 9 ---------
4 files changed, 17 insertions(+), 26 deletions(-)
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -101,6 +101,7 @@ config X86
select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTDUMP
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_RANDOM_ENTROPY
select ARCH_HAS_HW_PTE_YOUNG
select ARCH_HAS_NONLEAF_PMD_YOUNG if PGTABLE_LEVELS > 2
select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64
--- /dev/null
+++ b/arch/x86/include/asm/random.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_RANDOM_H
+#define _ASM_X86_RANDOM_H
+
+#include <asm/processor.h>
+#include <asm/tsc.h>
+
+static inline unsigned long random_get_entropy(void)
+{
+ if (!IS_ENABLED(CONFIG_X86_TSC) &&
+ !cpu_feature_enabled(X86_FEATURE_TSC))
+ return random_get_entropy_fallback();
+ return rdtsc();
+}
+
+#endif /* _ASM_X86_RANDOM_H */
--- a/arch/x86/include/asm/timex.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_X86_TIMEX_H
-#define _ASM_X86_TIMEX_H
-
-#include <asm/processor.h>
-#include <asm/tsc.h>
-
-static inline unsigned long random_get_entropy(void)
-{
- if (!IS_ENABLED(CONFIG_X86_TSC) &&
- !cpu_feature_enabled(X86_FEATURE_TSC))
- return random_get_entropy_fallback();
- return rdtsc();
-}
-#define random_get_entropy random_get_entropy
-
-#endif /* _ASM_X86_TIMEX_H */
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -72,15 +72,6 @@ extern unsigned int tsc_khz;
extern void disable_TSC(void);
-static inline cycles_t get_cycles(void)
-{
- if (!IS_ENABLED(CONFIG_X86_TSC) &&
- !cpu_feature_enabled(X86_FEATURE_TSC))
- return 0;
- return rdtsc();
-}
-#define get_cycles get_cycles
-
extern void tsc_early_init(void);
extern void tsc_init(void);
extern void mark_tsc_unstable(char *reason);
^ permalink raw reply
* [patch 38/38] treewide: Remove asm/timex.h includes from generic code
From: Thomas Gleixner @ 2026-04-10 12:21 UTC (permalink / raw)
To: LKML
Cc: Arnd Bergmann, x86, Lu Baolu, iommu, Michael Grzeschik, netdev,
linux-wireless, Herbert Xu, linux-crypto, Vlastimil Babka,
linux-mm, David Woodhouse, Bernie Thompson, linux-fbdev,
Theodore Tso, linux-ext4, Andrew Morton, Uladzislau Rezki,
Marco Elver, Dmitry Vyukov, kasan-dev, Andrey Ryabinin,
Thomas Sailer, linux-hams, Jason A. Donenfeld, Richard Henderson,
linux-alpha, Russell King, linux-arm-kernel, Catalin Marinas,
Huacai Chen, loongarch, Geert Uytterhoeven, linux-m68k,
Dinh Nguyen, Jonas Bonn, linux-openrisc, Helge Deller,
linux-parisc, Michael Ellerman, linuxppc-dev, Paul Walmsley,
linux-riscv, Heiko Carstens, linux-s390, David S. Miller,
sparclinux
In-Reply-To: <20260410120044.031381086@kernel.org>
asm/timex.h does not provide any functionality for non-architecture code
anymore.
Remove the asm-generic fallback and all references in include and source
files along with the random_get_entropy() #ifdeffery in timex.h.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
---
include/asm-generic/Kbuild | 1 -
include/asm-generic/timex.h | 15 ---------------
include/linux/random.h | 3 +++
include/linux/timex.h | 26 --------------------------
kernel/time/timer.c | 1 -
lib/interval_tree_test.c | 1 -
lib/rbtree_test.c | 1 -
7 files changed, 3 insertions(+), 45 deletions(-)
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -56,7 +56,6 @@ mandatory-y += shmparam.h
mandatory-y += simd.h
mandatory-y += softirq_stack.h
mandatory-y += switch_to.h
-mandatory-y += timex.h
mandatory-y += tlbflush.h
mandatory-y += topology.h
mandatory-y += trace_clock.h
--- a/include/asm-generic/timex.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_GENERIC_TIMEX_H
-#define __ASM_GENERIC_TIMEX_H
-
-/*
- * If you have a cycle counter, return the value here.
- */
-#ifndef get_cycles
-static inline cycles_t get_cycles(void)
-{
- return 0;
-}
-#endif
-
-#endif /* __ASM_GENERIC_TIMEX_H */
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -1,3 +1,4 @@
+
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_RANDOM_H
@@ -152,6 +153,8 @@ unsigned long random_get_entropy_fallbac
*/
#ifdef CONFIG_ARCH_HAS_RANDOM_ENTROPY
#include <asm/random.h>
+#else
+#define random_get_entropy() random_get_entropy_fallback()
#endif
#endif /* _LINUX_RANDOM_H */
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -62,32 +62,6 @@
#include <linux/types.h>
#include <linux/param.h>
-unsigned long random_get_entropy_fallback(void);
-
-#include <asm/timex.h>
-
-#ifndef CONFIG_ARCH_HAS_RANDOM_ENTROPY
-#ifndef random_get_entropy
-/*
- * The random_get_entropy() function is used by the /dev/random driver
- * in order to extract entropy via the relative unpredictability of
- * when an interrupt takes places versus a high speed, fine-grained
- * timing source or cycle counter. Since it will be occurred on every
- * single interrupt, it must have a very low cost/overhead.
- *
- * By default we use get_cycles() for this purpose, but individual
- * architectures may override this in their asm/timex.h header file.
- * If a given arch does not have get_cycles(), then we fallback to
- * using random_get_entropy_fallback().
- */
-#ifdef get_cycles
-#define random_get_entropy() ((unsigned long)get_cycles())
-#else
-#define random_get_entropy() random_get_entropy_fallback()
-#endif
-#endif
-#endif
-
/*
* SHIFT_PLL is used as a dampening factor to define how much we
* adjust the frequency correction for a given offset in PLL mode.
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -48,7 +48,6 @@
#include <linux/uaccess.h>
#include <asm/unistd.h>
#include <asm/div64.h>
-#include <asm/timex.h>
#include <asm/io.h>
#include "tick-internal.h"
--- a/lib/interval_tree_test.c
+++ b/lib/interval_tree_test.c
@@ -4,7 +4,6 @@
#include <linux/interval_tree.h>
#include <linux/prandom.h>
#include <linux/slab.h>
-#include <asm/timex.h>
#include <linux/bitmap.h>
#include <linux/maple_tree.h>
--- a/lib/rbtree_test.c
+++ b/lib/rbtree_test.c
@@ -4,7 +4,6 @@
#include <linux/rbtree_augmented.h>
#include <linux/prandom.h>
#include <linux/slab.h>
-#include <asm/timex.h>
#define __param(type, name, init, msg) \
static type name = init; \
^ permalink raw reply
* Re: [PATCH net v4 0/2] stmmac crash/stall fixes when under memory pressure
From: Russell King (Oracle) @ 2026-04-10 12:23 UTC (permalink / raw)
To: Sam Edwards
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Maxime Coquelin, Alexandre Torgue, Maxime Chevallier,
Ovidiu Panait, Vladimir Oltean, Baruch Siach, Serge Semin,
Giuseppe Cavallaro, netdev, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <CAH5Ym4g3pbU_bWzMwJMdhEFv4K2sp3pty3g04=0=9Z80_LzW1w@mail.gmail.com>
On Thu, Apr 02, 2026 at 10:39:32AM -0700, Sam Edwards wrote:
> On Thu, Apr 2, 2026 at 10:16 AM Russell King (Oracle)
> <linux@armlinux.org.uk> wrote:
> > I've tested this on my Jetson Xavier platform. One of the issues I've
> > had is that running iperf3 results in the receive side stalling because
> > it runs out of descriptors. However, despite the receive ring
> > eventually being re-filled and the hardware appropriately prodded, it
> > steadfastly refuses to restart, despite the descriptors having been
> > updated.
>
> Hi Russell,
>
> Just to make sure I understand correctly: before my patches, you've
> been observing this problem on Xavier for a while (no interrupts, ring
> goes dry); with my patches, the ring is refilled, but the dwmac5
> doesn't resume DMA. (Ah, just saw your follow-up email.)
>
> > Any ideas?
>
> Off the top of my head, my hypothesis is that dwmac5 has an additional
> tripwire when the receive DMA is exhausted, and the
> stmmac_set_rx_tail_ptr()/stmmac_enable_dma_reception() at the end of
> stmmac_rx_refill() aren't sufficient to wake it back up.
>
> I think this is new to dwmac5, because my RK3588 (dwmac4.20 iirc)
> happily resumes after the same condition.
>
> You gave a lot of info; thanks! I'll try to scrape up some
> documentation on dwmac5 to see if there's something more
> stmmac_rx_refill() ought to be doing. I think I have a Xavier NX
> around here somewhere, I'll see if I can repro the problem.
I've added dma_rmb() into dwmac4_wrback_get_tx_status() and
dwmac4_wrback_get_rx_status(), and with that I've had an iperf3
instance finally complete... but only once:
root@tegra-ubuntu:~# iperf3 -c 192.168.248.1 -R
Connecting to host 192.168.248.1, port 5201
Reverse mode, remote host 192.168.248.1 is sending
[ 5] local 192.168.248.174 port 42232 connected to 192.168.248.1 port 5201
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 50.8 MBytes 426 Mbits/sec
[ 5] 1.00-2.00 sec 54.9 MBytes 460 Mbits/sec
[ 5] 2.00-3.00 sec 54.0 MBytes 453 Mbits/sec
[ 5] 3.00-4.00 sec 53.8 MBytes 452 Mbits/sec
[ 5] 4.00-5.00 sec 52.4 MBytes 438 Mbits/sec
[ 5] 5.00-6.00 sec 54.3 MBytes 455 Mbits/sec
[ 5] 6.00-7.00 sec 53.7 MBytes 452 Mbits/sec
[ 5] 7.00-8.00 sec 52.8 MBytes 443 Mbits/sec
[ 5] 8.00-9.00 sec 53.7 MBytes 451 Mbits/sec
[ 5] 9.00-10.00 sec 54.3 MBytes 455 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.01 sec 537 MBytes 450 Mbits/sec 13 sender
[ 5] 0.00-10.00 sec 535 MBytes 448 Mbits/sec receiver
iperf Done.
So, it seems better, but not completely solved.
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
index 2994df41ec2c..119f31c94b61 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
@@ -17,10 +17,12 @@ static int dwmac4_wrback_get_tx_status(struct stmmac_extra_stats *x,
struct dma_desc *p,
void __iomem *ioaddr)
{
- u32 tdes3 = le32_to_cpu(p->des3);
+ u32 tdes3;
int ret = tx_done;
/* Get tx owner first */
+ dma_rmb();
+ tdes3 = le32_to_cpu(p->des3);
if (unlikely(tdes3 & TDES3_OWN))
return tx_dma_own;
@@ -70,12 +72,12 @@ static int dwmac4_wrback_get_tx_status(struct stmmac_extra_stats *x,
static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x,
struct dma_desc *p)
{
- u32 rdes1 = le32_to_cpu(p->des1);
- u32 rdes2 = le32_to_cpu(p->des2);
- u32 rdes3 = le32_to_cpu(p->des3);
+ u32 rdes1, rdes2, rdes3;
int message_type;
int ret = good_frame;
+ dma_rmb();
+ rdes3 = le32_to_cpu(p->des3);
if (unlikely(rdes3 & RDES3_OWN))
return dma_own;
@@ -107,6 +109,7 @@ static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x,
message_type = FIELD_GET(RDES1_PTP_MSG_TYPE_MASK, rdes1);
+ rdes1 = le32_to_cpu(p->des1);
if (rdes1 & RDES1_IP_HDR_ERROR) {
x->ip_hdr_err++;
ret |= csum_none;
@@ -152,6 +155,7 @@ static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x,
if (rdes1 & RDES1_TIMESTAMP_DROPPED)
x->timestamp_dropped++;
+ rdes2 = le32_to_cpu(p->des2);
if (unlikely(rdes2 & RDES2_SA_FILTER_FAIL)) {
x->sa_rx_filter_fail++;
ret = discard_frame;
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply related
* Re: [PATCH net-next v3 0/4] net: move .getsockopt away from __user buffers
From: Breno Leitao @ 2026-04-10 12:29 UTC (permalink / raw)
To: David Laight
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Kuniyuki Iwashima, Willem de Bruijn, metze, axboe,
Stanislav Fomichev, io-uring, bpf, netdev, Linus Torvalds,
linux-kernel, kernel-team
In-Reply-To: <20260408195640.324ee932@pumpkin>
On Wed, Apr 08, 2026 at 07:56:40PM +0100, David Laight wrote:
> On Wed, 8 Apr 2026 06:52:54 -0700
> Breno Leitao <leitao@debian.org> wrote:
>
> > Hello David,
> >
> > On Wed, Apr 08, 2026 at 12:26:53PM +0100, David Laight wrote:
> > > On Wed, 08 Apr 2026 03:30:28 -0700
> > > Breno Leitao <leitao@debian.org> wrote:
> > >
> > > > Currently, the .getsockopt callback requires __user pointers:
> > > >
> > > > int (*getsockopt)(struct socket *sock, int level,
> > > > int optname, char __user *optval, int __user *optlen);
> > > >
> > > > This prevents kernel callers (io_uring, BPF) from using getsockopt on
> > > > levels other than SOL_SOCKET, since they pass kernel pointers.
> > > >
> > > > Following Linus' suggestion [0], this series introduces sockopt_t, a
> > > > type-safe wrapper around iov_iter, and a getsockopt_iter callback that
> > > > works with both user and kernel buffers. AF_PACKET and CAN raw are
> > > > converted as initial users, with selftests covering the trickiest
> > > > conversion patterns.
> > >
> > > What are you doing about the cases where 'optlen' is a complete lie?
> >
> > Is this incorrect optlen originating from userspace, and getting into
> > the .getsockopt callbacks?
>
> Look at tcp_ao_copy_mptks_to_user() in net/ipv4/tcp_ao.c
> This isn't 'old code' it was added in 2023.
>
> Basically what is being transferred is an array and 'optlen' is the
> size of one element.
> The number of elements is in the first one.
Thank you for pointing this out. I now understand the issue you're raising.
The problem is that optlen doesn't represent the full buffer length. Instead:
optlen = per-element struct size (stride)
actual buffer length = optlen * nkeys (where nkeys comes from optval[0])
For handling these cases, I can think of several approaches:
1) Dynamically resize the iter once the actual buffer size is discovered:
int sockopt_set_buflen(sockopt_t *opt, size_t new_len)
{
if (!opt->legacy) /* Following Stefan's suggestion */
return -EINVAL;
/* Re-initialize iter with the actual buffer size.
* For ubuf: same base pointer, updated count.
* For kvec: same iov_base, updated iov_len + re-init.
*/
}
This allows legacy protocols to adjust the iov_iter later, mirroring
current behavior. Note that this doesn't worsen the existing
situation—currently, the current code is like having iov_iter length is
set to INT_MAX, given the callback can read/write to any location based
on that __user pointer.
2) Use a special legacy callback path, as proposed by Stefan.
3) Store base pointers in sockopt_t and defer iter initialization for
legacy callbacks:
static int tcp_ao_copy_mkts_to_user(const struct sock *sk,
struct tcp_ao_info *ao_info,
sockopt_t *opt)
{
struct tcp_ao_getsockopt opt_in;
int user_len = opt->optlen;
struct kvec kvec;
/* First, initialize a small iter to read the first element */
sockopt_init_iter(opt, user_len, &kvec);
if (copy_from_iter(&opt_in, user_len, &opt->iter_in) != user_len)
return -EFAULT;
/* Now we know the actual buffer size */
sockopt_init_iter(opt, user_len * opt_in.nkeys, &kvec);
/* ... write the full array via copy_to_iter() ... */
}
4) Maintain two separate callbacks: ->getsockopt_iter (to be renamed to ->getsockopt
after the transition) and ->getsockopt_unsafe for legacy cases.
Regardless of which approach we take for these legacy implementations, I don't
believe any of them invalidate the current patchset from a design standpoint.
Since these legacy protocols represent less than 1% of the cases, I'd prefer to
optimize for the common path and handle the exceptional cases as exceptions.
^ permalink raw reply
* [PATCH net-next v4 0/2] net: pse-pd: add poll path and LED trigger support
From: Carlo Szelinsky @ 2026-04-10 12:44 UTC (permalink / raw)
To: Oleksij Rempel, Kory Maincent
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Krzysztof Kozlowski, Krzysztof Kozlowski,
Conor Dooley, Rob Herring, netdev, linux-kernel, linux-leds,
Carlo Szelinsky
Thanks to Kory, Oleksij, Krzysztof and Andrew for all the helpful
feedback on earlier versions - really appreciate the time you put
into reviewing this.
This series adds poll-based event detection and LED trigger support
to the PSE core subsystem.
Patch 1 introduces the poll path independently of LED support,
so it can be tested in isolation on boards with and without IRQ
configured.
Patch 2 adds LED triggers that hook into the shared event handling
path introduced by patch 1.
Note: pse_handle_events() and the existing pse_isr() pass notifs_mask
as a single unsigned long, which limits the bitmask to BITS_PER_LONG
PI lines. This is a pre-existing constraint in the IRQ path and is
sufficient for all current PSE controllers (max 48 ports vs 64-bit
unsigned long), but may need to be converted to DECLARE_BITMAP() if
future hardware exceeds this limit.
Changes since v3:
- Dropped the dt-bindings poll-interval-ms patch: the poll interval
is a driver decision, not a hardware property (Krzysztof)
- Removed of_property_read_u32() for poll-interval-ms from
devm_pse_poll_helper(); the 500ms default is now hardcoded but
drivers can override pcdev->poll_interval_ms before calling the
helper
- Rebased on net-next/main
Changes since v2:
- Based on net-next/main, added net-next subject prefix
- Added --base tree information
- Added CC for devicetree list and DT maintainers
- Collected Reviewed-by from Kory Maincent on patch 1/3
- Fixed build error when CONFIG_LEDS_TRIGGERS is disabled:
moved LED registration before list_add(), removing the
pcdev->pi_led_trigs = NULL assignment on conditionally
compiled struct member (reported by kernel test robot)
- Fixed use-after-free on device unbind: poll work is now
cancelled via devm_add_action_or_reset() to ensure correct
devres teardown ordering (poll_work cancelled before
poll_notifs is freed)
- Used system_freezable_wq for poll worker to prevent hardware
access during system suspend
- Added PoDL power status and admin state checks to LED triggers
so they work for both C33 and PoDL controller types
- Used dev_name(dev) for LED trigger names to ensure uniqueness
across multiple PSE controllers (of_node->name can be generic)
- Added initial LED state query at registration so already-active
ports are reflected immediately
- Added pse_led_update() calls in regulator enable/disable paths
so ethtool admin state changes are reflected in LEDs
- Moved LED trigger registration before list_add() to prevent
race where IRQ/poll could invoke pse_led_update() on partially
initialized triggers
Changes since v1:
- Split single patch into 3 separate patches
- Extracted pse_handle_events() and devm_pse_poll_helper() as a
standalone poll path (patches 1-2), testable without LED code
- Added DT binding for poll-interval-ms as a separate patch
- Renamed led-poll-interval-ms to poll-interval-ms for generic use
- Fire LED triggers from the notification path rather than a
separate poll loop
Tested on Realtek RTL9303 with HS104 PoE chip, poll path only
(without IRQ configured). Verified PD connect/disconnect notifications
and LED trigger state changes.
Link: https://lore.kernel.org/all/20260329153124.2823980-1-github@szelinsky.de/
Link: https://lore.kernel.org/all/20260323201225.1836561-1-github@szelinsky.de/
Link: https://lore.kernel.org/all/20260314235916.2391678-1-github@szelinsky.de/
Carlo Szelinsky (2):
net: pse-pd: add devm_pse_poll_helper()
net: pse-pd: add LED trigger support via notification path
drivers/net/pse-pd/pse_core.c | 296 ++++++++++++++++++++++++++++++----
include/linux/pse-pd/pse.h | 34 ++++
2 files changed, 299 insertions(+), 31 deletions(-)
base-commit: b3e69fc3196fc421e26196e7792f17b0463edc6f
--
2.43.0
^ permalink raw reply
* [PATCH net-next v4 1/2] net: pse-pd: add devm_pse_poll_helper()
From: Carlo Szelinsky @ 2026-04-10 12:44 UTC (permalink / raw)
To: Oleksij Rempel, Kory Maincent
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Krzysztof Kozlowski, Krzysztof Kozlowski,
Conor Dooley, Rob Herring, netdev, linux-kernel, linux-leds,
Carlo Szelinsky
In-Reply-To: <20260410124428.809943-1-github@szelinsky.de>
Extract the common event handling loop from pse_isr() into a shared
pse_handle_events() function, and add a generic poll-based alternative
to the IRQ path for PSE controllers that lack interrupt support or
have IRQ lines not wired on the board.
The new devm_pse_poll_helper() function sets up a delayed work that
periodically calls the driver's map_event callback to detect state
changes, feeding events into the existing ntf_fifo / pse_send_ntf_worker
notification pipeline. This reuses the same pse_irq_desc interface as
the IRQ path — the driver provides a map_event callback that populates
per-PI notification arrays.
The poll worker uses system_freezable_wq to avoid running during system
suspend when the underlying hardware (e.g. I2C bus) may be inaccessible.
Work cancellation on teardown is handled via devm_add_action_or_reset()
to ensure the delayed work is cancelled before poll_notifs is freed
by devres, avoiding a use-after-free when devm_pse_poll_helper() is
called after devm_pse_controller_register() (devres LIFO ordering).
The poll interval defaults to 500ms if not set by the driver, balancing
responsiveness against bus load (e.g. I2C).
Signed-off-by: Carlo Szelinsky <github@szelinsky.de>
---
drivers/net/pse-pd/pse_core.c | 164 +++++++++++++++++++++++++++-------
include/linux/pse-pd/pse.h | 12 +++
2 files changed, 146 insertions(+), 30 deletions(-)
diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c
index 3beaaaeec9e1..f641a6fa087f 100644
--- a/drivers/net/pse-pd/pse_core.c
+++ b/drivers/net/pse-pd/pse_core.c
@@ -14,10 +14,18 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/rtnetlink.h>
+#include <linux/workqueue.h>
#include <net/net_trackers.h>
#define PSE_PW_D_LIMIT INT_MAX
+/*
+ * Default poll interval for controllers without IRQ support.
+ * 500ms provides a reasonable trade-off between responsiveness
+ * (event detection, PD detection) and I2C bus utilization.
+ */
+#define PSE_DEFAULT_POLL_INTERVAL_MS 500
+
static DEFINE_MUTEX(pse_list_mutex);
static LIST_HEAD(pse_controller_list);
static DEFINE_XARRAY_ALLOC(pse_pw_d_map);
@@ -1238,66 +1246,103 @@ static int pse_set_config_isr(struct pse_controller_dev *pcdev, int id,
}
/**
- * pse_isr - IRQ handler for PSE
- * @irq: irq number
- * @data: pointer to user interrupt structure
+ * pse_handle_events - Process PSE events for all PIs
+ * @pcdev: a pointer to the PSE controller device
+ * @notifs: per-PI notification array
+ * @notifs_mask: bitmask of PIs with events
*
- * Return: irqreturn_t - status of IRQ
+ * Common event handling shared between IRQ and poll paths.
+ * Caller must hold pcdev->lock.
*/
-static irqreturn_t pse_isr(int irq, void *data)
+static void pse_handle_events(struct pse_controller_dev *pcdev,
+ unsigned long *notifs,
+ unsigned long notifs_mask)
{
- struct pse_controller_dev *pcdev;
- unsigned long notifs_mask = 0;
- struct pse_irq_desc *desc;
- struct pse_irq *h = data;
- int ret, i;
-
- desc = &h->desc;
- pcdev = h->pcdev;
-
- /* Clear notifs mask */
- memset(h->notifs, 0, pcdev->nr_lines * sizeof(*h->notifs));
- mutex_lock(&pcdev->lock);
- ret = desc->map_event(irq, pcdev, h->notifs, ¬ifs_mask);
- if (ret || !notifs_mask) {
- mutex_unlock(&pcdev->lock);
- return IRQ_NONE;
- }
+ int i;
for_each_set_bit(i, ¬ifs_mask, pcdev->nr_lines) {
- unsigned long notifs, rnotifs;
+ unsigned long pi_notifs, rnotifs;
struct pse_ntf ntf = {};
+ int ret;
/* Do nothing PI not described */
if (!pcdev->pi[i].rdev)
continue;
- notifs = h->notifs[i];
+ pi_notifs = notifs[i];
if (pse_pw_d_is_sw_pw_control(pcdev, pcdev->pi[i].pw_d)) {
- ret = pse_set_config_isr(pcdev, i, notifs);
+ ret = pse_set_config_isr(pcdev, i, pi_notifs);
if (ret)
- notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR;
+ pi_notifs |= ETHTOOL_PSE_EVENT_SW_PW_CONTROL_ERROR;
}
- dev_dbg(h->pcdev->dev,
- "Sending PSE notification EVT 0x%lx\n", notifs);
+ dev_dbg(pcdev->dev,
+ "Sending PSE notification EVT 0x%lx\n", pi_notifs);
- ntf.notifs = notifs;
+ ntf.notifs = pi_notifs;
ntf.id = i;
kfifo_in_spinlocked(&pcdev->ntf_fifo, &ntf, 1,
&pcdev->ntf_fifo_lock);
schedule_work(&pcdev->ntf_work);
- rnotifs = pse_to_regulator_notifs(notifs);
+ rnotifs = pse_to_regulator_notifs(pi_notifs);
regulator_notifier_call_chain(pcdev->pi[i].rdev, rnotifs,
NULL);
}
+}
+
+/**
+ * pse_isr - IRQ handler for PSE
+ * @irq: irq number
+ * @data: pointer to user interrupt structure
+ *
+ * Return: irqreturn_t - status of IRQ
+ */
+static irqreturn_t pse_isr(int irq, void *data)
+{
+ struct pse_controller_dev *pcdev;
+ unsigned long notifs_mask = 0;
+ struct pse_irq *h = data;
+ int ret;
+ pcdev = h->pcdev;
+
+ /* Clear notifs mask */
+ memset(h->notifs, 0, pcdev->nr_lines * sizeof(*h->notifs));
+ mutex_lock(&pcdev->lock);
+ ret = h->desc.map_event(irq, pcdev, h->notifs, ¬ifs_mask);
+ if (ret || !notifs_mask) {
+ mutex_unlock(&pcdev->lock);
+ return IRQ_NONE;
+ }
+
+ pse_handle_events(pcdev, h->notifs, notifs_mask);
mutex_unlock(&pcdev->lock);
return IRQ_HANDLED;
}
+static void pse_poll_worker(struct work_struct *work)
+{
+ struct pse_controller_dev *pcdev =
+ container_of(work, struct pse_controller_dev,
+ poll_work.work);
+ unsigned long notifs_mask = 0;
+ int ret;
+
+ memset(pcdev->poll_notifs, 0,
+ pcdev->nr_lines * sizeof(*pcdev->poll_notifs));
+ mutex_lock(&pcdev->lock);
+ ret = pcdev->poll_desc.map_event(0, pcdev, pcdev->poll_notifs,
+ ¬ifs_mask);
+ if (!ret && notifs_mask)
+ pse_handle_events(pcdev, pcdev->poll_notifs, notifs_mask);
+ mutex_unlock(&pcdev->lock);
+
+ queue_delayed_work(system_freezable_wq, &pcdev->poll_work,
+ msecs_to_jiffies(pcdev->poll_interval_ms));
+}
+
/**
* devm_pse_irq_helper - Register IRQ based PSE event notifier
* @pcdev: a pointer to the PSE
@@ -1351,6 +1396,65 @@ int devm_pse_irq_helper(struct pse_controller_dev *pcdev, int irq,
}
EXPORT_SYMBOL_GPL(devm_pse_irq_helper);
+static void pse_poll_cancel(void *data)
+{
+ struct pse_controller_dev *pcdev = data;
+
+ cancel_delayed_work_sync(&pcdev->poll_work);
+}
+
+/**
+ * devm_pse_poll_helper - Register poll-based PSE event notifier
+ * @pcdev: a pointer to the PSE controller device
+ * @d: PSE event description (uses same pse_irq_desc as IRQ path)
+ *
+ * For PSE controllers without IRQ support or with IRQ not wired. Sets
+ * up a delayed work that periodically calls the driver's map_event
+ * callback to detect state changes, feeding events into the standard
+ * notification pipeline.
+ *
+ * The poll worker uses system_freezable_wq to ensure it does not run
+ * during system suspend while the hardware may be inaccessible.
+ *
+ * Return: 0 on success and errno on failure
+ */
+int devm_pse_poll_helper(struct pse_controller_dev *pcdev,
+ const struct pse_irq_desc *d)
+{
+ struct device *dev = pcdev->dev;
+ int ret;
+
+ if (!d || !d->map_event || !d->name)
+ return -EINVAL;
+
+ pcdev->poll_desc = *d;
+ pcdev->poll_notifs = devm_kcalloc(dev, pcdev->nr_lines,
+ sizeof(*pcdev->poll_notifs),
+ GFP_KERNEL);
+ if (!pcdev->poll_notifs)
+ return -ENOMEM;
+
+ if (!pcdev->poll_interval_ms)
+ pcdev->poll_interval_ms = PSE_DEFAULT_POLL_INTERVAL_MS;
+
+ INIT_DELAYED_WORK(&pcdev->poll_work, pse_poll_worker);
+ pcdev->polling = true;
+
+ /* Register devm action to cancel poll work before poll_notifs is
+ * freed by devres. This ensures correct teardown ordering since
+ * devm_pse_poll_helper() is called after devm_pse_controller_register().
+ */
+ ret = devm_add_action_or_reset(dev, pse_poll_cancel, pcdev);
+ if (ret)
+ return ret;
+
+ queue_delayed_work(system_freezable_wq, &pcdev->poll_work,
+ msecs_to_jiffies(pcdev->poll_interval_ms));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_pse_poll_helper);
+
/* PSE control section */
static void __pse_control_release(struct kref *kref)
diff --git a/include/linux/pse-pd/pse.h b/include/linux/pse-pd/pse.h
index 4e5696cfade7..44d5d10e239d 100644
--- a/include/linux/pse-pd/pse.h
+++ b/include/linux/pse-pd/pse.h
@@ -292,6 +292,11 @@ struct pse_ntf {
* @pi: table of PSE PIs described in this controller device
* @no_of_pse_pi: flag set if the pse_pis devicetree node is not used
* @irq: PSE interrupt
+ * @polling: flag indicating poll-based event detection is active
+ * @poll_interval_ms: poll interval in milliseconds
+ * @poll_work: delayed work for poll-based event detection
+ * @poll_desc: copy of the driver's event descriptor for polling
+ * @poll_notifs: per-PI notification scratch space for poll worker
* @pis_prio_max: Maximum value allowed for the PSE PIs priority
* @supp_budget_eval_strategies: budget evaluation strategies supported
* by the PSE
@@ -312,6 +317,11 @@ struct pse_controller_dev {
struct pse_pi *pi;
bool no_of_pse_pi;
int irq;
+ bool polling;
+ unsigned int poll_interval_ms;
+ struct delayed_work poll_work;
+ struct pse_irq_desc poll_desc;
+ unsigned long *poll_notifs;
unsigned int pis_prio_max;
u32 supp_budget_eval_strategies;
struct work_struct ntf_work;
@@ -345,6 +355,8 @@ int devm_pse_controller_register(struct device *dev,
struct pse_controller_dev *pcdev);
int devm_pse_irq_helper(struct pse_controller_dev *pcdev, int irq,
int irq_flags, const struct pse_irq_desc *d);
+int devm_pse_poll_helper(struct pse_controller_dev *pcdev,
+ const struct pse_irq_desc *d);
struct pse_control *of_pse_control_get(struct device_node *node,
struct phy_device *phydev);
--
2.43.0
^ permalink raw reply related
* [PATCH net-next v4 2/2] net: pse-pd: add LED trigger support via notification path
From: Carlo Szelinsky @ 2026-04-10 12:44 UTC (permalink / raw)
To: Oleksij Rempel, Kory Maincent
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Krzysztof Kozlowski, Krzysztof Kozlowski,
Conor Dooley, Rob Herring, netdev, linux-kernel, linux-leds,
Carlo Szelinsky, kernel test robot
In-Reply-To: <20260410124428.809943-1-github@szelinsky.de>
Add per-PI "delivering" and "enabled" LED triggers to the PSE core
subsystem. LED state is updated from the shared pse_handle_events()
function whenever the IRQ or poll path detects a state change, as well
as from the regulator enable/disable paths so that host-initiated
admin state changes via ethtool are immediately reflected.
Both C33 and PoDL power status and admin state are checked so that LED
triggers work for both controller types.
Trigger names use dev_name(dev) (e.g. "pse-1-003c:port0:delivering")
to ensure uniqueness when multiple PSE controllers are present on the
same system.
Initial LED state is queried at registration time so already-active
ports are reflected immediately without waiting for a hardware event.
LED trigger registration is performed before adding the controller to
the global list, avoiding a race where an IRQ or poll event could
invoke pse_led_update() on a partially initialized trigger.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603251254.o5PqMBRU-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202603251250.cuMCk5Yv-lkp@intel.com/
Signed-off-by: Carlo Szelinsky <github@szelinsky.de>
---
drivers/net/pse-pd/pse_core.c | 134 +++++++++++++++++++++++++++++++++-
include/linux/pse-pd/pse.h | 22 ++++++
2 files changed, 154 insertions(+), 2 deletions(-)
diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c
index f641a6fa087f..dfc84340afb9 100644
--- a/drivers/net/pse-pd/pse_core.c
+++ b/drivers/net/pse-pd/pse_core.c
@@ -12,9 +12,10 @@
#include <linux/phy.h>
#include <linux/pse-pd/pse.h>
#include <linux/regulator/driver.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
#include <linux/regulator/machine.h>
#include <linux/rtnetlink.h>
-#include <linux/workqueue.h>
#include <net/net_trackers.h>
#define PSE_PW_D_LIMIT INT_MAX
@@ -670,6 +671,111 @@ static int _pse_pi_delivery_power_sw_pw_ctrl(struct pse_controller_dev *pcdev,
return 0;
}
+#if IS_ENABLED(CONFIG_LEDS_TRIGGERS)
+/**
+ * pse_led_update - Update LED triggers for a PI based on current state
+ * @pcdev: PSE controller device
+ * @id: PI index
+ *
+ * Queries the current power status and admin state of the PI and
+ * fires LED trigger events on state changes. Called from the
+ * notification path and the regulator enable/disable paths.
+ *
+ * Must be called with pcdev->lock held.
+ */
+static void pse_led_update(struct pse_controller_dev *pcdev, int id)
+{
+ struct pse_pi_led_triggers *trigs;
+ struct pse_pw_status pw_status = {};
+ struct pse_admin_state admin_state = {};
+ bool delivering, enabled;
+
+ if (!pcdev->pi_led_trigs)
+ return;
+
+ trigs = &pcdev->pi_led_trigs[id];
+ if (!trigs->delivering.name)
+ return;
+
+ if (pcdev->ops->pi_get_pw_status(pcdev, id, &pw_status))
+ return;
+ if (pcdev->ops->pi_get_admin_state(pcdev, id, &admin_state))
+ return;
+
+ delivering = pw_status.c33_pw_status ==
+ ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING ||
+ pw_status.podl_pw_status ==
+ ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING;
+ enabled = admin_state.c33_admin_state ==
+ ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED ||
+ admin_state.podl_admin_state ==
+ ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED;
+
+ if (trigs->last_delivering != delivering) {
+ trigs->last_delivering = delivering;
+ led_trigger_event(&trigs->delivering,
+ delivering ? LED_FULL : LED_OFF);
+ }
+
+ if (trigs->last_enabled != enabled) {
+ trigs->last_enabled = enabled;
+ led_trigger_event(&trigs->enabled,
+ enabled ? LED_FULL : LED_OFF);
+ }
+}
+
+static int pse_led_triggers_register(struct pse_controller_dev *pcdev)
+{
+ struct device *dev = pcdev->dev;
+ const char *dev_id;
+ int i, ret;
+
+ dev_id = dev_name(dev);
+
+ pcdev->pi_led_trigs = devm_kcalloc(dev, pcdev->nr_lines,
+ sizeof(*pcdev->pi_led_trigs),
+ GFP_KERNEL);
+ if (!pcdev->pi_led_trigs)
+ return -ENOMEM;
+
+ for (i = 0; i < pcdev->nr_lines; i++) {
+ struct pse_pi_led_triggers *trigs = &pcdev->pi_led_trigs[i];
+
+ /* Skip PIs not described in device tree */
+ if (!pcdev->no_of_pse_pi && !pcdev->pi[i].np)
+ continue;
+
+ trigs->delivering.name = devm_kasprintf(dev, GFP_KERNEL,
+ "pse-%s:port%d:delivering",
+ dev_id, i);
+ if (!trigs->delivering.name)
+ return -ENOMEM;
+
+ ret = devm_led_trigger_register(dev, &trigs->delivering);
+ if (ret)
+ return ret;
+
+ trigs->enabled.name = devm_kasprintf(dev, GFP_KERNEL,
+ "pse-%s:port%d:enabled",
+ dev_id, i);
+ if (!trigs->enabled.name)
+ return -ENOMEM;
+
+ ret = devm_led_trigger_register(dev, &trigs->enabled);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#else
+static inline void pse_led_update(struct pse_controller_dev *pcdev, int id) {}
+static int pse_led_triggers_register(struct pse_controller_dev *pcdev)
+{
+ return 0;
+}
+#endif /* CONFIG_LEDS_TRIGGERS */
+
static int pse_pi_enable(struct regulator_dev *rdev)
{
struct pse_controller_dev *pcdev = rdev_get_drvdata(rdev);
@@ -695,6 +801,7 @@ static int pse_pi_enable(struct regulator_dev *rdev)
pcdev->pi[id].admin_state_enabled = 1;
ret = 0;
}
+ pse_led_update(pcdev, id);
mutex_unlock(&pcdev->lock);
return ret;
}
@@ -702,6 +809,7 @@ static int pse_pi_enable(struct regulator_dev *rdev)
ret = ops->pi_enable(pcdev, id);
if (!ret)
pcdev->pi[id].admin_state_enabled = 1;
+ pse_led_update(pcdev, id);
mutex_unlock(&pcdev->lock);
return ret;
@@ -719,6 +827,7 @@ static int pse_pi_disable(struct regulator_dev *rdev)
ret = _pse_pi_disable(pcdev, id);
if (!ret)
pi->admin_state_enabled = 0;
+ pse_led_update(pcdev, id);
mutex_unlock(&pcdev->lock);
return 0;
@@ -1108,6 +1217,20 @@ int pse_controller_register(struct pse_controller_dev *pcdev)
if (ret)
return ret;
+ ret = pse_led_triggers_register(pcdev);
+ if (ret) {
+ dev_warn(pcdev->dev, "Failed to register LED triggers: %d\n",
+ ret);
+ }
+
+ /* Query initial LED state for all PIs so already-active ports
+ * are reflected immediately without waiting for a hardware event.
+ */
+ for (i = 0; i < pcdev->nr_lines; i++) {
+ if (pcdev->no_of_pse_pi || pcdev->pi[i].np)
+ pse_led_update(pcdev, i);
+ }
+
mutex_lock(&pse_list_mutex);
list_add(&pcdev->list, &pse_controller_list);
mutex_unlock(&pse_list_mutex);
@@ -1265,7 +1388,14 @@ static void pse_handle_events(struct pse_controller_dev *pcdev,
struct pse_ntf ntf = {};
int ret;
- /* Do nothing PI not described */
+ /* Update LEDs for described PIs regardless of consumer state.
+ * LED triggers are registered at controller init, before any
+ * PHY claims a PSE control, so rdev may still be NULL here.
+ */
+ if (pcdev->no_of_pse_pi || pcdev->pi[i].np)
+ pse_led_update(pcdev, i);
+
+ /* Skip regulator/netlink path for PIs without consumers */
if (!pcdev->pi[i].rdev)
continue;
diff --git a/include/linux/pse-pd/pse.h b/include/linux/pse-pd/pse.h
index 44d5d10e239d..0058636a6299 100644
--- a/include/linux/pse-pd/pse.h
+++ b/include/linux/pse-pd/pse.h
@@ -10,6 +10,7 @@
#include <linux/kfifo.h>
#include <uapi/linux/ethtool.h>
#include <uapi/linux/ethtool_netlink_generated.h>
+#include <linux/leds.h>
#include <linux/regulator/driver.h>
/* Maximum current in uA according to IEEE 802.3-2022 Table 145-1 */
@@ -266,6 +267,23 @@ struct pse_pi {
int pw_allocated_mW;
};
+#if IS_ENABLED(CONFIG_LEDS_TRIGGERS)
+/**
+ * struct pse_pi_led_triggers - LED trigger state for a PSE PI
+ *
+ * @delivering: LED trigger for power delivering state
+ * @enabled: LED trigger for admin enabled state
+ * @last_delivering: cached delivering state for change detection
+ * @last_enabled: cached enabled state for change detection
+ */
+struct pse_pi_led_triggers {
+ struct led_trigger delivering;
+ struct led_trigger enabled;
+ bool last_delivering;
+ bool last_enabled;
+};
+#endif
+
/**
* struct pse_ntf - PSE notification element
*
@@ -303,6 +321,7 @@ struct pse_ntf {
* @ntf_work: workqueue for PSE notification management
* @ntf_fifo: PSE notifications FIFO
* @ntf_fifo_lock: protect @ntf_fifo writer
+ * @pi_led_trigs: per-PI LED trigger state array
*/
struct pse_controller_dev {
const struct pse_controller_ops *ops;
@@ -327,6 +346,9 @@ struct pse_controller_dev {
struct work_struct ntf_work;
DECLARE_KFIFO_PTR(ntf_fifo, struct pse_ntf);
spinlock_t ntf_fifo_lock; /* Protect @ntf_fifo writer */
+#if IS_ENABLED(CONFIG_LEDS_TRIGGERS)
+ struct pse_pi_led_triggers *pi_led_trigs;
+#endif
};
/**
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next v3 02/12] net: airoha: Set PPE cpu port for GDM2 if loopback is enabled
From: Lorenzo Bianconi @ 2026-04-10 12:52 UTC (permalink / raw)
To: Jakub Kicinski
Cc: andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
ansuelsmth, benjamin.larsson, linux-arm-kernel, linux-mediatek,
netdev, devicetree
In-Reply-To: <20260410025720.1809934-1-kuba@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 3218 bytes --]
> This is an AI-generated review of your patch. The human sending this
> email says "For your consideration."
> ---
> net: airoha: Move airoha_qdma pointer in airoha_gdm_dev struct
>
> This commit moves the airoha_qdma pointer from the airoha_gdm_port struct
> to the airoha_gdm_dev struct. This ensures the QDMA block used depends on
> the specific net_device WAN/LAN configuration.
>
> [ ... ]
>
> > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
>
> [ ... ]
>
> > @@ -1497,9 +1498,10 @@ static void airoha_qdma_stop_napi(struct airoha_qdma *qdma)
> > }
> > }
> >
> > -static void airoha_update_hw_stats(struct airoha_gdm_port *port)
> > +static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
> > {
> > - struct airoha_eth *eth = port->qdma->eth;
> > + struct airoha_gdm_port *port = dev->port;
> > + struct airoha_eth *eth = dev->eth;
> > u32 val, i = 0;
> >
> > spin_lock(&port->stats.lock);
>
> This isn't a bug introduced by this patch, but does this spin_lock()
> carry a deadlock risk?
>
> Because ndo_get_stats64() can be called from atomic context (e.g., from a
> softirq), if a process context caller holds port->stats.lock and is
> interrupted by a softirq on the same CPU that also triggers dev_get_stats(),
> the softirq could spin forever waiting for the lock.
>
> Should this be upgraded to spin_lock_bh() to ensure local softirqs are
> disabled during the critical section?
I was not able to spot any point in the networking stack where
ndo_get_stats64 callback is run from a softirq. Moreover,
airoha_update_hw_stats() is never executed in any napi in airoha_eth
driver. It seems to me spin_lock() is enough here. Am I missing something?
>
> [ ... ]
>
> > --- a/drivers/net/ethernet/airoha/airoha_eth.h
> > +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> > @@ -534,12 +534,12 @@ struct airoha_qdma {
> >
> > struct airoha_gdm_dev {
> > struct airoha_gdm_port *port;
> > + struct airoha_qdma *qdma;
> > struct net_device *dev;
> > struct airoha_eth *eth;
> > };
> >
> > struct airoha_gdm_port {
> > - struct airoha_qdma *qdma;
> > struct airoha_gdm_dev *dev;
> > int id;
>
> This isn't a bug introduced by this patch, but since the qdma pointer
> is being moved to better align with the hardware structure, should
> qos_sq_bmap, cpu_tx_packets, and fwd_tx_packets be moved to
> struct airoha_qdma as well?
>
> Because QDMA1 is shared by all WAN ports (GDM 2, 3, 4) and qos_sq_bmap
> is currently tracked per-port instead of per-QDMA, each WAN port
> independently allocates QDMA1 channels starting from index 0. Does this
> cause different ports to overwrite each other's hardware QoS configurations
> in the shared QDMA1 block?
>
> Furthermore, cpu_tx_packets and fwd_tx_packets cache per-channel ETS
> hardware counters but are single u64 scalar variables in the port structure.
> When querying stats for multiple channels, do these scalar caches get
> overwritten with values from completely different channels, resulting in
> incorrect delta calculations?
ack, I will fix it in v4.
Regards,
Lorenzo
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v3 0/4] net: move .getsockopt away from __user buffers
From: Breno Leitao @ 2026-04-10 12:52 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Kuniyuki Iwashima, Willem de Bruijn, metze, axboe,
Stanislav Fomichev, io-uring, bpf, netdev, Linus Torvalds,
linux-kernel, kernel-team
In-Reply-To: <adaJqy6Q4L7c-eTs@devvm17672.vll0.facebook.com>
Hello Stanislav,
On Wed, Apr 08, 2026 at 10:02:36AM -0700, Stanislav Fomichev wrote:
> On 04/08, Breno Leitao wrote:
>
> LGTM! Not sure what's your plan for the selftest? You wanna keep it
> outside or maybe repost v4 with it?
I'd be glad to include a selftest. I've already developed one covering both
protocols in this series and can respin with it if you'd like.
Test available at:
https://github.com/leitao/linux/commit/2d9311947061f1baa43858f597dd6c54d7ccc5d2
> Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Thanks for the review and guidance.
> I'm also not sure your unconditional 'copy-optlen-back' will work for every
> proto, but I think we can put something into sockopt_t to make it avoid
> the copy if needed in the future.
Good point. I'd prefer not to over-engineer this now, but keep it
straightforward to add later if needed. This could be easily achieved with
something like:
typedef struct sockopt {
struct iov_iter iter_in;
struct iov_iter iter_out;
int optlen;
+ bool optlen_dirty; /* set by callback when optlen should be written back */
} sockopt_t;
Wrapper becomes:
if (opt.optlen_dirty &&
copy_to_sockptr(optlen, &opt.optlen, sizeof(int)))
return -EFAULT;
and the protocol callback would need to set
opt->optlen_dirty = true;
I don't think this is needed yet, and if we do need it, it would be better
to review and commit them together, making the rationale clearer for
future developers/LLM agents.
What do you think?
Thanks,
--breno
^ permalink raw reply
* Re: [PATCH] udp: Force compute_score to always inline
From: Willem de Bruijn @ 2026-04-10 13:02 UTC (permalink / raw)
To: Gabriel Krisman Bertazi, willemdebruijn.kernel, davem, dsahern,
edumazet, kuba, pabeni, kuniyu
Cc: horms, netdev, Gabriel Krisman Bertazi
In-Reply-To: <20260409221532.69090-1-krisman@suse.de>
Gabriel Krisman Bertazi wrote:
> Back in 2024 I reported a 7-12% regression on an iperf3 UDP loopback
> thoughput test that we traced to the extra overhead of calling
> compute_score on two places, introduced by commit f0ea27e7bfe1 ("udp:
> re-score reuseport groups when connected sockets are present"). At the
> time, I pointed out the overhead was caused by the multiple calls,
> associated with cpu-specific mitigations, and merged commit
> 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites") to
> jump back explicitly, to force the rescore call in a single place.
>
> Recently though, we got another regression report against a newer distro
> version, which a team colleague traced back to the same root-cause.
> Turns out that once we updated to gcc-13, the compiler got smart enough
> to unroll the loop, undoing my previous mitigation. Let's bite the
> bullet and __always_inline compute_score on both ipv4 and ipv6 to
> prevent gcc from de-optimizing it again in the future. These functions
> are only called in two places each, udpX_lib_lookup1 and
> udpX_lib_lookup2, so the extra size shouldn't be a problem and it is hot
> enough to be very visible in profilings. In fact, with gcc13, forcing
> the inline will prevent gcc from unrolling the fix from commit
> 50aee97d1511, so we don't end up increasing udpX_lib_lookup2 at all.
>
> I haven't recollected the results myself, as I don't have access to the
> machine at the moment. But the same colleague reported 4.67%
> inprovement with this patch in the loopback benchmark, solving the
> regression report within noise margins.
>
> Fixes: 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites")
> Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
Acked-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply
* Re: [PATCH] udp: Force compute_score to always inline
From: Willem de Bruijn @ 2026-04-10 13:04 UTC (permalink / raw)
To: Gabriel Krisman Bertazi, willemdebruijn.kernel, davem, dsahern,
edumazet, kuba, pabeni, kuniyu
Cc: horms, netdev, Gabriel Krisman Bertazi
In-Reply-To: <20260409221532.69090-1-krisman@suse.de>
Gabriel Krisman Bertazi wrote:
> Back in 2024 I reported a 7-12% regression on an iperf3 UDP loopback
> thoughput test that we traced to the extra overhead of calling
> compute_score on two places, introduced by commit f0ea27e7bfe1 ("udp:
> re-score reuseport groups when connected sockets are present"). At the
> time, I pointed out the overhead was caused by the multiple calls,
> associated with cpu-specific mitigations, and merged commit
> 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites") to
> jump back explicitly, to force the rescore call in a single place.
>
> Recently though, we got another regression report against a newer distro
> version, which a team colleague traced back to the same root-cause.
> Turns out that once we updated to gcc-13, the compiler got smart enough
> to unroll the loop, undoing my previous mitigation. Let's bite the
> bullet and __always_inline compute_score on both ipv4 and ipv6 to
> prevent gcc from de-optimizing it again in the future. These functions
> are only called in two places each, udpX_lib_lookup1 and
> udpX_lib_lookup2, so the extra size shouldn't be a problem and it is hot
> enough to be very visible in profilings. In fact, with gcc13, forcing
> the inline will prevent gcc from unrolling the fix from commit
> 50aee97d1511, so we don't end up increasing udpX_lib_lookup2 at all.
>
> I haven't recollected the results myself, as I don't have access to the
> machine at the moment. But the same colleague reported 4.67%
> inprovement with this patch in the loopback benchmark, solving the
> regression report within noise margins.
>
> Fixes: 50aee97d1511 ("udp: Avoid call to compute_score on multiple sites")
> Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
Spotted this a tad late: should the comment udp4_lib_lookup2 be
updated: "compute_score is too long of a function to be inline .."
^ permalink raw reply
* [PATCH net-next] net: Rename ifq_idx to rxq_idx in netif_mp_* helpers
From: Daniel Borkmann @ 2026-04-10 13:06 UTC (permalink / raw)
To: netdev; +Cc: kuba, dw, pabeni, razor
Rename the leftover ifq_idx parameter naming to rxq_idx to be
consistent with the rest of the file and the header declaration.
Back then this was taken out of the queue leasing series given
the cleanup is independent. No functional change.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/netdev/20260131160237.07789674@kernel.org
---
net/core/netdev_rx_queue.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/net/core/netdev_rx_queue.c b/net/core/netdev_rx_queue.c
index 8771e06a0afe..de4dac4c88b3 100644
--- a/net/core/netdev_rx_queue.c
+++ b/net/core/netdev_rx_queue.c
@@ -275,14 +275,14 @@ int netif_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
return ret;
}
-static void __netif_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx,
+static void __netif_mp_close_rxq(struct net_device *dev, unsigned int rxq_idx,
const struct pp_memory_provider_params *old_p)
{
struct netdev_queue_config qcfg[2];
struct netdev_rx_queue *rxq;
int err;
- rxq = __netif_get_rx_queue(dev, ifq_idx);
+ rxq = __netif_get_rx_queue(dev, rxq_idx);
/* Callers holding a netdev ref may get here after we already
* went thru shutdown via dev_memory_provider_uninstall().
@@ -295,28 +295,28 @@ static void __netif_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx,
rxq->mp_params.mp_priv != old_p->mp_priv))
return;
- netdev_queue_config(dev, ifq_idx, &qcfg[0]);
+ netdev_queue_config(dev, rxq_idx, &qcfg[0]);
memset(&rxq->mp_params, 0, sizeof(rxq->mp_params));
- netdev_queue_config(dev, ifq_idx, &qcfg[1]);
+ netdev_queue_config(dev, rxq_idx, &qcfg[1]);
- err = netdev_rx_queue_reconfig(dev, ifq_idx, &qcfg[0], &qcfg[1]);
+ err = netdev_rx_queue_reconfig(dev, rxq_idx, &qcfg[0], &qcfg[1]);
WARN_ON(err && err != -ENETDOWN);
}
-void netif_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx,
+void netif_mp_close_rxq(struct net_device *dev, unsigned int rxq_idx,
const struct pp_memory_provider_params *old_p)
{
- if (WARN_ON_ONCE(ifq_idx >= dev->real_num_rx_queues))
+ if (WARN_ON_ONCE(rxq_idx >= dev->real_num_rx_queues))
return;
- if (!netif_rxq_is_leased(dev, ifq_idx))
- return __netif_mp_close_rxq(dev, ifq_idx, old_p);
+ if (!netif_rxq_is_leased(dev, rxq_idx))
+ return __netif_mp_close_rxq(dev, rxq_idx, old_p);
- if (!__netif_get_rx_queue_lease(&dev, &ifq_idx, NETIF_VIRT_TO_PHYS)) {
+ if (!__netif_get_rx_queue_lease(&dev, &rxq_idx, NETIF_VIRT_TO_PHYS)) {
WARN_ON_ONCE(1);
return;
}
netdev_lock(dev);
- __netif_mp_close_rxq(dev, ifq_idx, old_p);
+ __netif_mp_close_rxq(dev, rxq_idx, old_p);
netdev_unlock(dev);
}
@@ -339,11 +339,11 @@ void netif_rxq_cleanup_unlease(struct netdev_rx_queue *phys_rxq,
struct netdev_rx_queue *virt_rxq)
{
struct pp_memory_provider_params *p = &phys_rxq->mp_params;
- unsigned int ifq_idx = get_netdev_rx_queue_index(phys_rxq);
+ unsigned int rxq_idx = get_netdev_rx_queue_index(phys_rxq);
if (!p->mp_ops)
return;
__netif_mp_uninstall_rxq(virt_rxq, p);
- __netif_mp_close_rxq(phys_rxq->dev, ifq_idx, p);
+ __netif_mp_close_rxq(phys_rxq->dev, rxq_idx, p);
}
--
2.43.0
^ permalink raw reply related
* [PATCH net-next] net: stmmac: enable RPS and RBU interrupts
From: Russell King (Oracle) @ 2026-04-10 13:07 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-stm32, netdev,
Paolo Abeni, Sam Edwards
Enable receive process stopped and receive buffer unavailable
interrupts, so that the statistic counters can be updated.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
Since we are seeing receive buffer exhaustion on several platforms,
let's enable the interrupts so the statistics we publish via ethtool -S
actually work to aid diagnosis. I've been in two minds about whether
to send this patch, but given the problems with stmmac at the moment,
I think it should be merged.
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
index af6580332d49..43b036d4e95b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
@@ -99,6 +99,8 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs,
#define DMA_CHAN_INTR_ENA_NIE_4_10 BIT(15)
#define DMA_CHAN_INTR_ENA_AIE_4_10 BIT(14)
#define DMA_CHAN_INTR_ENA_FBE BIT(12)
+#define DMA_CHAN_INTR_ENA_RPS BIT(8)
+#define DMA_CHAN_INTR_ENA_RBU BIT(7)
#define DMA_CHAN_INTR_ENA_RIE BIT(6)
#define DMA_CHAN_INTR_ENA_TIE BIT(0)
@@ -107,6 +109,8 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs,
DMA_CHAN_INTR_ENA_TIE)
#define DMA_CHAN_INTR_ABNORMAL (DMA_CHAN_INTR_ENA_AIE | \
+ DMA_CHAN_INTR_ENA_RPS | \
+ DMA_CHAN_INTR_ENA_RBU | \
DMA_CHAN_INTR_ENA_FBE)
/* DMA default interrupt mask for 4.00 */
#define DMA_CHAN_INTR_DEFAULT_MASK (DMA_CHAN_INTR_NORMAL | \
@@ -117,6 +121,8 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs,
DMA_CHAN_INTR_ENA_TIE)
#define DMA_CHAN_INTR_ABNORMAL_4_10 (DMA_CHAN_INTR_ENA_AIE_4_10 | \
+ DMA_CHAN_INTR_ENA_RPS | \
+ DMA_CHAN_INTR_ENA_RBU | \
DMA_CHAN_INTR_ENA_FBE)
/* DMA default interrupt mask for 4.10a */
#define DMA_CHAN_INTR_DEFAULT_MASK_4_10 (DMA_CHAN_INTR_NORMAL_4_10 | \
--
2.47.3
^ permalink raw reply related
* Re: [PATCH 2/4] net: ionic: Add PHC state page for user space access
From: Allen Hubbe @ 2026-04-10 13:10 UTC (permalink / raw)
To: Jakub Kicinski, Abhijit Gangurde
Cc: jgg, leon, brett.creeley, andrew+netdev, davem, edumazet, pabeni,
nikhil.agarwal, linux-rdma, netdev, linux-kernel
In-Reply-To: <20260401170600.312a23d1@kernel.org>
On 4/1/2026 8:06 PM, Jakub Kicinski wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
>
>
> On Wed, 1 Apr 2026 15:54:59 +0530 Abhijit Gangurde wrote:
>> diff --git a/include/uapi/rdma/ionic-abi.h b/include/uapi/rdma/ionic-abi.h
>> index 7b589d3e9728..97f695510380 100644
>> --- a/include/uapi/rdma/ionic-abi.h
>> +++ b/include/uapi/rdma/ionic-abi.h
>> @@ -112,4 +112,15 @@ struct ionic_srq_resp {
>> __aligned_u64 rq_cmb_offset;
>> };
>>
>> +struct ionic_phc_state {
>> + __u32 seq;
>> + __u32 rsvd;
>> + __aligned_u64 mask;
>> + __aligned_u64 tick;
>> + __aligned_u64 nsec;
>> + __aligned_u64 frac;
>> + __u32 mult;
>> + __u32 shift;
>> +};
>
> You're just exposing kernel timecounter internals.
> Why is this ionic uAPI and not something reusable by other drivers?
The simple answer is just following the same approach as an existing
implementation. See struct mlx5_ib_clock_info and
mlx5_update_clock_info_page().
Making this common might risk presuming that other implementations will
be a similar design. Compare these to the sfc driver. The clock is
quite different from ionic and mlx5, not using timecounter, because
instead of a free-running cycle counter the hardware itself provides an
adjustable clock for timestamping.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox