* Re: [PATCH v2] raid6: arm64: add SVE optimized implementation for syndrome generation
From: Ard Biesheuvel @ 2026-03-24 8:00 UTC (permalink / raw)
To: Demian Shulhan, Song Liu, Yu Kuai, Will Deacon, Catalin Marinas,
Mark Rutland, broonie, linux-arm-kernel, robin.murphy,
Christoph Hellwig
Cc: Li Nan, linux-raid, linux-kernel
In-Reply-To: <20260318150245.3080719-1-demyansh@gmail.com>
Hi Damian,
On Wed, 18 Mar 2026, at 16:02, Demian Shulhan wrote:
> Implement Scalable Vector Extension (SVE) optimized routines for RAID6
> syndrome generation and recovery on ARM64.
>
> The SVE instruction set allows for variable vector lengths (from 128 to
> 2048 bits), scaling automatically with the hardware capabilities. This
> implementation handles arbitrary SVE vector lengths using the `cntb`
> instruction to determine the runtime vector length.
>
> The implementation introduces `svex1`, `svex2`, and `svex4` algorithms.
> The `svex4` algorithm utilizes loop unrolling by 4 blocks per iteration
> and manual software pipelining (interleaving memory loads with XORs)
> to minimize instruction dependency stalls and maximize CPU pipeline
> utilization and memory bandwidth.
>
> Performance was tested on an AWS Graviton3 (Neoverse-V1) instance which
> features 256-bit SVE vector length. The `svex4` implementation outperforms
> the existing 128-bit `neonx4` baseline for syndrome generation:
>
> raid6: svex4 gen() 19688 MB/s
...
> raid6: neonx4 gen() 19612 MB/s
You're being very generous characterising a 0.3% speedup as 'outperforms'
But the real problem here is that the kernel-mode SIMD API only supports NEON and not SVE, and preserves/restores only the 128-bit view on the NEON/SVE register file. So any context switch or softirq that uses kernel-mode SIMD too, and your SVE register values will get truncated.
Once we encounter a good use case for SVE in the kernel, we might reconsider this, but as it stands, this patch should not be applied.
(leaving the reply untrimmed for the benefit of the cc'ees I added)
> raid6: neonx2 gen() 16248 MB/s
> raid6: neonx1 gen() 13591 MB/s
> raid6: using algorithm svex4 gen() 19688 MB/s
> raid6: .... xor() 11212 MB/s, rmw enabled
> raid6: using neon recovery algorithm
>
> Note that for the recovery path (`xor_syndrome`), NEON may still be
> selected dynamically by the algorithm benchmark, as the recovery
> workload is heavily memory-bound.
>
> Signed-off-by: Demian Shulhan <demyansh@gmail.com>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes:
> https://lore.kernel.org/oe-kbuild-all/202603181940.cFwYmYoi-lkp@intel.com/
> ---
> include/linux/raid/pq.h | 3 +
> lib/raid6/Makefile | 5 +
> lib/raid6/algos.c | 5 +
> lib/raid6/sve.c | 675 ++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 688 insertions(+)
> create mode 100644 lib/raid6/sve.c
>
> diff --git a/include/linux/raid/pq.h b/include/linux/raid/pq.h
> index 2467b3be15c9..787cc57aea9d 100644
> --- a/include/linux/raid/pq.h
> +++ b/include/linux/raid/pq.h
> @@ -140,6 +140,9 @@ extern const struct raid6_calls raid6_neonx1;
> extern const struct raid6_calls raid6_neonx2;
> extern const struct raid6_calls raid6_neonx4;
> extern const struct raid6_calls raid6_neonx8;
> +extern const struct raid6_calls raid6_svex1;
> +extern const struct raid6_calls raid6_svex2;
> +extern const struct raid6_calls raid6_svex4;
>
> /* Algorithm list */
> extern const struct raid6_calls * const raid6_algos[];
> diff --git a/lib/raid6/Makefile b/lib/raid6/Makefile
> index 5be0a4e60ab1..6cdaa6f206fb 100644
> --- a/lib/raid6/Makefile
> +++ b/lib/raid6/Makefile
> @@ -8,6 +8,7 @@ raid6_pq-$(CONFIG_X86) += recov_ssse3.o recov_avx2.o
> mmx.o sse1.o sse2.o avx2.o
> raid6_pq-$(CONFIG_ALTIVEC) += altivec1.o altivec2.o altivec4.o
> altivec8.o \
> vpermxor1.o vpermxor2.o vpermxor4.o
> vpermxor8.o
> raid6_pq-$(CONFIG_KERNEL_MODE_NEON) += neon.o neon1.o neon2.o neon4.o
> neon8.o recov_neon.o recov_neon_inner.o
> +raid6_pq-$(CONFIG_ARM64_SVE) += sve.o
> raid6_pq-$(CONFIG_S390) += s390vx8.o recov_s390xc.o
> raid6_pq-$(CONFIG_LOONGARCH) += loongarch_simd.o recov_loongarch_simd.o
> raid6_pq-$(CONFIG_RISCV_ISA_V) += rvv.o recov_rvv.o
> @@ -67,6 +68,10 @@ CFLAGS_REMOVE_neon2.o += $(CC_FLAGS_NO_FPU)
> CFLAGS_REMOVE_neon4.o += $(CC_FLAGS_NO_FPU)
> CFLAGS_REMOVE_neon8.o += $(CC_FLAGS_NO_FPU)
> CFLAGS_REMOVE_recov_neon_inner.o += $(CC_FLAGS_NO_FPU)
> +
> +CFLAGS_sve.o += $(CC_FLAGS_FPU)
> +CFLAGS_REMOVE_sve.o += $(CC_FLAGS_NO_FPU)
> +
> targets += neon1.c neon2.c neon4.c neon8.c
> $(obj)/neon%.c: $(src)/neon.uc $(src)/unroll.awk FORCE
> $(call if_changed,unroll)
> diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
> index 799e0e5eac26..0ae73c3a4be3 100644
> --- a/lib/raid6/algos.c
> +++ b/lib/raid6/algos.c
> @@ -66,6 +66,11 @@ const struct raid6_calls * const raid6_algos[] = {
> &raid6_neonx2,
> &raid6_neonx1,
> #endif
> +#ifdef CONFIG_ARM64_SVE
> + &raid6_svex4,
> + &raid6_svex2,
> + &raid6_svex1,
> +#endif
> #ifdef CONFIG_LOONGARCH
> #ifdef CONFIG_CPU_HAS_LASX
> &raid6_lasx,
> diff --git a/lib/raid6/sve.c b/lib/raid6/sve.c
> new file mode 100644
> index 000000000000..d52937f806d4
> --- /dev/null
> +++ b/lib/raid6/sve.c
> @@ -0,0 +1,675 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * RAID-6 syndrome calculation using ARM SVE instructions
> + */
> +
> +#include <linux/raid/pq.h>
> +
> +#ifdef __KERNEL__
> +#include <asm/simd.h>
> +#include <linux/cpufeature.h>
> +#else
> +#define scoped_ksimd()
> +#define system_supports_sve() (1)
> +#endif
> +
> +static void raid6_sve1_gen_syndrome_real(int disks, unsigned long
> bytes, void **ptrs)
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = disks - 3;
> +
> + p = dptr[z0 + 1];
> + q = dptr[z0 + 2];
> +
> + asm volatile(
> + ".arch armv8.2-a+sve\n"
> + "ptrue p0.b\n"
> + "cntb x3\n"
> + "mov w4, #0x1d\n"
> + "dup z4.b, w4\n"
> + "mov x5, #0\n"
> +
> + "0:\n"
> + "ldr x6, [%[dptr], %[z0], lsl #3]\n"
> + "ld1b z0.b, p0/z, [x6, x5]\n"
> + "mov z1.d, z0.d\n"
> +
> + "mov w7, %w[z0]\n"
> + "sub w7, w7, #1\n"
> +
> + "1:\n"
> + "cmp w7, #0\n"
> + "blt 2f\n"
> +
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> +
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> +
> + "sxtw x8, w7\n"
> + "ldr x6, [%[dptr], x8, lsl #3]\n"
> + "ld1b z2.b, p0/z, [x6, x5]\n"
> +
> + "eor z1.d, z1.d, z2.d\n"
> + "eor z0.d, z0.d, z2.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 1b\n"
> + "2:\n"
> +
> + "st1b z0.b, p0, [%[p], x5]\n"
> + "st1b z1.b, p0, [%[q], x5]\n"
> +
> + "add x5, x5, x3\n"
> + "cmp x5, %[bytes]\n"
> + "blt 0b\n"
> + :
> + : [dptr] "r" (dptr), [z0] "r" (z0), [bytes] "r" (bytes),
> + [p] "r" (p), [q] "r" (q)
> + : "memory", "p0", "x3", "x4", "x5", "x6", "x7", "x8",
> + "z0", "z1", "z2", "z3", "z4"
> + );
> +}
> +
> +static void raid6_sve1_xor_syndrome_real(int disks, int start, int
> stop,
> + unsigned long bytes, void **ptrs)
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = stop;
> +
> + p = dptr[disks - 2];
> + q = dptr[disks - 1];
> +
> + asm volatile(
> + ".arch armv8.2-a+sve\n"
> + "ptrue p0.b\n"
> + "cntb x3\n"
> + "mov w4, #0x1d\n"
> + "dup z4.b, w4\n"
> + "mov x5, #0\n"
> +
> + "0:\n"
> + "ldr x6, [%[dptr], %[z0], lsl #3]\n"
> + "ld1b z1.b, p0/z, [x6, x5]\n"
> + "ld1b z0.b, p0/z, [%[p], x5]\n"
> + "eor z0.d, z0.d, z1.d\n"
> +
> + "mov w7, %w[z0]\n"
> + "sub w7, w7, #1\n"
> +
> + "1:\n"
> + "cmp w7, %w[start]\n"
> + "blt 2f\n"
> +
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> +
> + "sxtw x8, w7\n"
> + "ldr x6, [%[dptr], x8, lsl #3]\n"
> + "ld1b z2.b, p0/z, [x6, x5]\n"
> +
> + "eor z1.d, z1.d, z2.d\n"
> + "eor z0.d, z0.d, z2.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 1b\n"
> + "2:\n"
> +
> + "mov w7, %w[start]\n"
> + "sub w7, w7, #1\n"
> + "3:\n"
> + "cmp w7, #0\n"
> + "blt 4f\n"
> +
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 3b\n"
> + "4:\n"
> +
> + "ld1b z2.b, p0/z, [%[q], x5]\n"
> + "eor z1.d, z1.d, z2.d\n"
> +
> + "st1b z0.b, p0, [%[p], x5]\n"
> + "st1b z1.b, p0, [%[q], x5]\n"
> +
> + "add x5, x5, x3\n"
> + "cmp x5, %[bytes]\n"
> + "blt 0b\n"
> + :
> + : [dptr] "r" (dptr), [z0] "r" (z0), [bytes] "r" (bytes),
> + [p] "r" (p), [q] "r" (q), [start] "r" (start)
> + : "memory", "p0", "x3", "x4", "x5", "x6", "x7", "x8",
> + "z0", "z1", "z2", "z3", "z4"
> + );
> +}
> +
> +static void raid6_sve2_gen_syndrome_real(int disks, unsigned long
> bytes, void **ptrs)
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = disks - 3;
> +
> + p = dptr[z0 + 1];
> + q = dptr[z0 + 2];
> +
> + asm volatile(
> + ".arch armv8.2-a+sve\n"
> + "ptrue p0.b\n"
> + "cntb x3\n"
> + "mov w4, #0x1d\n"
> + "dup z4.b, w4\n"
> + "mov x5, #0\n"
> +
> + "0:\n"
> + "ldr x6, [%[dptr], %[z0], lsl #3]\n"
> + "ld1b z0.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z5.b, p0/z, [x6, x8]\n"
> + "mov z1.d, z0.d\n"
> + "mov z6.d, z5.d\n"
> +
> + "mov w7, %w[z0]\n"
> + "sub w7, w7, #1\n"
> +
> + "1:\n"
> + "cmp w7, #0\n"
> + "blt 2f\n"
> +
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> +
> + "mov z8.d, z6.d\n"
> + "asr z8.b, p0/m, z8.b, #7\n"
> + "lsl z6.b, p0/m, z6.b, #1\n"
> + "and z8.d, z8.d, z4.d\n"
> + "eor z6.d, z6.d, z8.d\n"
> +
> + "sxtw x8, w7\n"
> + "ldr x6, [%[dptr], x8, lsl #3]\n"
> + "ld1b z2.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z7.b, p0/z, [x6, x8]\n"
> +
> + "eor z1.d, z1.d, z2.d\n"
> + "eor z0.d, z0.d, z2.d\n"
> +
> + "eor z6.d, z6.d, z7.d\n"
> + "eor z5.d, z5.d, z7.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 1b\n"
> + "2:\n"
> +
> + "st1b z0.b, p0, [%[p], x5]\n"
> + "st1b z1.b, p0, [%[q], x5]\n"
> + "add x8, x5, x3\n"
> + "st1b z5.b, p0, [%[p], x8]\n"
> + "st1b z6.b, p0, [%[q], x8]\n"
> +
> + "add x5, x5, x3\n"
> + "add x5, x5, x3\n"
> + "cmp x5, %[bytes]\n"
> + "blt 0b\n"
> + :
> + : [dptr] "r" (dptr), [z0] "r" (z0), [bytes] "r" (bytes),
> + [p] "r" (p), [q] "r" (q)
> + : "memory", "p0", "x3", "x4", "x5", "x6", "x7", "x8",
> + "z0", "z1", "z2", "z3", "z4",
> + "z5", "z6", "z7", "z8"
> + );
> +}
> +
> +static void raid6_sve2_xor_syndrome_real(int disks, int start, int
> stop,
> + unsigned long bytes, void **ptrs)
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = stop;
> +
> + p = dptr[disks - 2];
> + q = dptr[disks - 1];
> +
> + asm volatile(
> + ".arch armv8.2-a+sve\n"
> + "ptrue p0.b\n"
> + "cntb x3\n"
> + "mov w4, #0x1d\n"
> + "dup z4.b, w4\n"
> + "mov x5, #0\n"
> +
> + "0:\n"
> + "ldr x6, [%[dptr], %[z0], lsl #3]\n"
> + "ld1b z1.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z6.b, p0/z, [x6, x8]\n"
> +
> + "ld1b z0.b, p0/z, [%[p], x5]\n"
> + "ld1b z5.b, p0/z, [%[p], x8]\n"
> +
> + "eor z0.d, z0.d, z1.d\n"
> + "eor z5.d, z5.d, z6.d\n"
> +
> + "mov w7, %w[z0]\n"
> + "sub w7, w7, #1\n"
> +
> + "1:\n"
> + "cmp w7, %w[start]\n"
> + "blt 2f\n"
> +
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> +
> + "mov z8.d, z6.d\n"
> + "asr z8.b, p0/m, z8.b, #7\n"
> + "lsl z6.b, p0/m, z6.b, #1\n"
> + "and z8.d, z8.d, z4.d\n"
> + "eor z6.d, z6.d, z8.d\n"
> +
> + "sxtw x8, w7\n"
> + "ldr x6, [%[dptr], x8, lsl #3]\n"
> + "ld1b z2.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z7.b, p0/z, [x6, x8]\n"
> +
> + "eor z1.d, z1.d, z2.d\n"
> + "eor z0.d, z0.d, z2.d\n"
> +
> + "eor z6.d, z6.d, z7.d\n"
> + "eor z5.d, z5.d, z7.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 1b\n"
> + "2:\n"
> +
> + "mov w7, %w[start]\n"
> + "sub w7, w7, #1\n"
> + "3:\n"
> + "cmp w7, #0\n"
> + "blt 4f\n"
> +
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> +
> + "mov z8.d, z6.d\n"
> + "asr z8.b, p0/m, z8.b, #7\n"
> + "lsl z6.b, p0/m, z6.b, #1\n"
> + "and z8.d, z8.d, z4.d\n"
> + "eor z6.d, z6.d, z8.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 3b\n"
> + "4:\n"
> +
> + "ld1b z2.b, p0/z, [%[q], x5]\n"
> + "eor z1.d, z1.d, z2.d\n"
> + "st1b z0.b, p0, [%[p], x5]\n"
> + "st1b z1.b, p0, [%[q], x5]\n"
> +
> + "add x8, x5, x3\n"
> + "ld1b z7.b, p0/z, [%[q], x8]\n"
> + "eor z6.d, z6.d, z7.d\n"
> + "st1b z5.b, p0, [%[p], x8]\n"
> + "st1b z6.b, p0, [%[q], x8]\n"
> +
> + "add x5, x5, x3\n"
> + "add x5, x5, x3\n"
> + "cmp x5, %[bytes]\n"
> + "blt 0b\n"
> + :
> + : [dptr] "r" (dptr), [z0] "r" (z0), [bytes] "r" (bytes),
> + [p] "r" (p), [q] "r" (q), [start] "r" (start)
> + : "memory", "p0", "x3", "x4", "x5", "x6", "x7", "x8",
> + "z0", "z1", "z2", "z3", "z4",
> + "z5", "z6", "z7", "z8"
> + );
> +}
> +
> +static void raid6_sve4_gen_syndrome_real(int disks, unsigned long
> bytes, void **ptrs)
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = disks - 3;
> +
> + p = dptr[z0 + 1];
> + q = dptr[z0 + 2];
> +
> + asm volatile(
> + ".arch armv8.2-a+sve\n"
> + "ptrue p0.b\n"
> + "cntb x3\n"
> + "mov w4, #0x1d\n"
> + "dup z4.b, w4\n"
> + "mov x5, #0\n"
> +
> + "0:\n"
> + "ldr x6, [%[dptr], %[z0], lsl #3]\n"
> + "ld1b z0.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z5.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z10.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z15.b, p0/z, [x6, x8]\n"
> +
> + "mov z1.d, z0.d\n"
> + "mov z6.d, z5.d\n"
> + "mov z11.d, z10.d\n"
> + "mov z16.d, z15.d\n"
> +
> + "mov w7, %w[z0]\n"
> + "sub w7, w7, #1\n"
> +
> + "1:\n"
> + "cmp w7, #0\n"
> + "blt 2f\n"
> +
> + // software pipelining: load data early
> + "sxtw x8, w7\n"
> + "ldr x6, [%[dptr], x8, lsl #3]\n"
> + "ld1b z2.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z7.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z12.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z17.b, p0/z, [x6, x8]\n"
> +
> + // math block 1
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> + "eor z1.d, z1.d, z2.d\n"
> + "eor z0.d, z0.d, z2.d\n"
> +
> + // math block 2
> + "mov z8.d, z6.d\n"
> + "asr z8.b, p0/m, z8.b, #7\n"
> + "lsl z6.b, p0/m, z6.b, #1\n"
> + "and z8.d, z8.d, z4.d\n"
> + "eor z6.d, z6.d, z8.d\n"
> + "eor z6.d, z6.d, z7.d\n"
> + "eor z5.d, z5.d, z7.d\n"
> +
> + // math block 3
> + "mov z13.d, z11.d\n"
> + "asr z13.b, p0/m, z13.b, #7\n"
> + "lsl z11.b, p0/m, z11.b, #1\n"
> + "and z13.d, z13.d, z4.d\n"
> + "eor z11.d, z11.d, z13.d\n"
> + "eor z11.d, z11.d, z12.d\n"
> + "eor z10.d, z10.d, z12.d\n"
> +
> + // math block 4
> + "mov z18.d, z16.d\n"
> + "asr z18.b, p0/m, z18.b, #7\n"
> + "lsl z16.b, p0/m, z16.b, #1\n"
> + "and z18.d, z18.d, z4.d\n"
> + "eor z16.d, z16.d, z18.d\n"
> + "eor z16.d, z16.d, z17.d\n"
> + "eor z15.d, z15.d, z17.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 1b\n"
> + "2:\n"
> +
> + "st1b z0.b, p0, [%[p], x5]\n"
> + "st1b z1.b, p0, [%[q], x5]\n"
> + "add x8, x5, x3\n"
> + "st1b z5.b, p0, [%[p], x8]\n"
> + "st1b z6.b, p0, [%[q], x8]\n"
> + "add x8, x8, x3\n"
> + "st1b z10.b, p0, [%[p], x8]\n"
> + "st1b z11.b, p0, [%[q], x8]\n"
> + "add x8, x8, x3\n"
> + "st1b z15.b, p0, [%[p], x8]\n"
> + "st1b z16.b, p0, [%[q], x8]\n"
> +
> + "add x8, x3, x3\n"
> + "add x5, x5, x8, lsl #1\n"
> + "cmp x5, %[bytes]\n"
> + "blt 0b\n"
> + :
> + : [dptr] "r" (dptr), [z0] "r" (z0), [bytes] "r" (bytes),
> + [p] "r" (p), [q] "r" (q)
> + : "memory", "p0", "x3", "x4", "x5", "x6", "x7", "x8",
> + "z0", "z1", "z2", "z3", "z4",
> + "z5", "z6", "z7", "z8",
> + "z10", "z11", "z12", "z13",
> + "z15", "z16", "z17", "z18"
> + );
> +}
> +
> +static void raid6_sve4_xor_syndrome_real(int disks, int start, int
> stop,
> + unsigned long bytes, void **ptrs)
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = stop;
> +
> + p = dptr[disks - 2];
> + q = dptr[disks - 1];
> +
> + asm volatile(
> + ".arch armv8.2-a+sve\n"
> + "ptrue p0.b\n"
> + "cntb x3\n"
> + "mov w4, #0x1d\n"
> + "dup z4.b, w4\n"
> + "mov x5, #0\n"
> +
> + "0:\n"
> + "ldr x6, [%[dptr], %[z0], lsl #3]\n"
> + "ld1b z1.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z6.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z11.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z16.b, p0/z, [x6, x8]\n"
> +
> + "ld1b z0.b, p0/z, [%[p], x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z5.b, p0/z, [%[p], x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z10.b, p0/z, [%[p], x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z15.b, p0/z, [%[p], x8]\n"
> +
> + "eor z0.d, z0.d, z1.d\n"
> + "eor z5.d, z5.d, z6.d\n"
> + "eor z10.d, z10.d, z11.d\n"
> + "eor z15.d, z15.d, z16.d\n"
> +
> + "mov w7, %w[z0]\n"
> + "sub w7, w7, #1\n"
> +
> + "1:\n"
> + "cmp w7, %w[start]\n"
> + "blt 2f\n"
> +
> + // software pipelining: load data early
> + "sxtw x8, w7\n"
> + "ldr x6, [%[dptr], x8, lsl #3]\n"
> + "ld1b z2.b, p0/z, [x6, x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z7.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z12.b, p0/z, [x6, x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z17.b, p0/z, [x6, x8]\n"
> +
> + // math block 1
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> + "eor z1.d, z1.d, z2.d\n"
> + "eor z0.d, z0.d, z2.d\n"
> +
> + // math block 2
> + "mov z8.d, z6.d\n"
> + "asr z8.b, p0/m, z8.b, #7\n"
> + "lsl z6.b, p0/m, z6.b, #1\n"
> + "and z8.d, z8.d, z4.d\n"
> + "eor z6.d, z6.d, z8.d\n"
> + "eor z6.d, z6.d, z7.d\n"
> + "eor z5.d, z5.d, z7.d\n"
> +
> + // math block 3
> + "mov z13.d, z11.d\n"
> + "asr z13.b, p0/m, z13.b, #7\n"
> + "lsl z11.b, p0/m, z11.b, #1\n"
> + "and z13.d, z13.d, z4.d\n"
> + "eor z11.d, z11.d, z13.d\n"
> + "eor z11.d, z11.d, z12.d\n"
> + "eor z10.d, z10.d, z12.d\n"
> +
> + // math block 4
> + "mov z18.d, z16.d\n"
> + "asr z18.b, p0/m, z18.b, #7\n"
> + "lsl z16.b, p0/m, z16.b, #1\n"
> + "and z18.d, z18.d, z4.d\n"
> + "eor z16.d, z16.d, z18.d\n"
> + "eor z16.d, z16.d, z17.d\n"
> + "eor z15.d, z15.d, z17.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 1b\n"
> + "2:\n"
> +
> + "mov w7, %w[start]\n"
> + "sub w7, w7, #1\n"
> + "3:\n"
> + "cmp w7, #0\n"
> + "blt 4f\n"
> +
> + // math block 1
> + "mov z3.d, z1.d\n"
> + "asr z3.b, p0/m, z3.b, #7\n"
> + "lsl z1.b, p0/m, z1.b, #1\n"
> + "and z3.d, z3.d, z4.d\n"
> + "eor z1.d, z1.d, z3.d\n"
> +
> + // math block 2
> + "mov z8.d, z6.d\n"
> + "asr z8.b, p0/m, z8.b, #7\n"
> + "lsl z6.b, p0/m, z6.b, #1\n"
> + "and z8.d, z8.d, z4.d\n"
> + "eor z6.d, z6.d, z8.d\n"
> +
> + // math block 3
> + "mov z13.d, z11.d\n"
> + "asr z13.b, p0/m, z13.b, #7\n"
> + "lsl z11.b, p0/m, z11.b, #1\n"
> + "and z13.d, z13.d, z4.d\n"
> + "eor z11.d, z11.d, z13.d\n"
> +
> + // math block 4
> + "mov z18.d, z16.d\n"
> + "asr z18.b, p0/m, z18.b, #7\n"
> + "lsl z16.b, p0/m, z16.b, #1\n"
> + "and z18.d, z18.d, z4.d\n"
> + "eor z16.d, z16.d, z18.d\n"
> +
> + "sub w7, w7, #1\n"
> + "b 3b\n"
> + "4:\n"
> +
> + // Load q and XOR
> + "ld1b z2.b, p0/z, [%[q], x5]\n"
> + "add x8, x5, x3\n"
> + "ld1b z7.b, p0/z, [%[q], x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z12.b, p0/z, [%[q], x8]\n"
> + "add x8, x8, x3\n"
> + "ld1b z17.b, p0/z, [%[q], x8]\n"
> +
> + "eor z1.d, z1.d, z2.d\n"
> + "eor z6.d, z6.d, z7.d\n"
> + "eor z11.d, z11.d, z12.d\n"
> + "eor z16.d, z16.d, z17.d\n"
> +
> + // Store results
> + "st1b z0.b, p0, [%[p], x5]\n"
> + "st1b z1.b, p0, [%[q], x5]\n"
> + "add x8, x5, x3\n"
> + "st1b z5.b, p0, [%[p], x8]\n"
> + "st1b z6.b, p0, [%[q], x8]\n"
> + "add x8, x8, x3\n"
> + "st1b z10.b, p0, [%[p], x8]\n"
> + "st1b z11.b, p0, [%[q], x8]\n"
> + "add x8, x8, x3\n"
> + "st1b z15.b, p0, [%[p], x8]\n"
> + "st1b z16.b, p0, [%[q], x8]\n"
> +
> + "add x8, x3, x3\n"
> + "add x5, x5, x8, lsl #1\n"
> + "cmp x5, %[bytes]\n"
> + "blt 0b\n"
> + :
> + : [dptr] "r" (dptr), [z0] "r" (z0), [bytes] "r" (bytes),
> + [p] "r" (p), [q] "r" (q), [start] "r" (start)
> + : "memory", "p0", "x3", "x4", "x5", "x6", "x7", "x8",
> + "z0", "z1", "z2", "z3", "z4",
> + "z5", "z6", "z7", "z8",
> + "z10", "z11", "z12", "z13",
> + "z15", "z16", "z17", "z18"
> + );
> +}
> +
> +#define RAID6_SVE_WRAPPER(_n) \
> + static void raid6_sve ## _n ## _gen_syndrome(int disks, \
> + size_t bytes, void **ptrs) \
> + { \
> + scoped_ksimd() \
> + raid6_sve ## _n ## _gen_syndrome_real(disks, \
> + (unsigned long)bytes, ptrs); \
> + } \
> + static void raid6_sve ## _n ## _xor_syndrome(int disks, \
> + int start, int stop, \
> + size_t bytes, void **ptrs) \
> + { \
> + scoped_ksimd() \
> + raid6_sve ## _n ## _xor_syndrome_real(disks, \
> + start, stop, (unsigned long)bytes, ptrs);\
> + } \
> + struct raid6_calls const raid6_svex ## _n = { \
> + raid6_sve ## _n ## _gen_syndrome, \
> + raid6_sve ## _n ## _xor_syndrome, \
> + raid6_have_sve, \
> + "svex" #_n, \
> + 0 \
> + }
> +
> +static int raid6_have_sve(void)
> +{
> + return system_supports_sve();
> +}
> +
> +RAID6_SVE_WRAPPER(1);
> +RAID6_SVE_WRAPPER(2);
> +RAID6_SVE_WRAPPER(4);
> --
> 2.43.0
^ permalink raw reply
* [PATCH 1/1] arm64: dts: imx8mp-tqma8mpql: Add DT overlays to explicit list
From: Alexander Stein @ 2026-03-24 7:58 UTC (permalink / raw)
To: Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Alexander Stein, imx, linux-arm-kernel, devicetree, linux-kernel
Armbian installs DT overlays using dtbs_install. For it to work all
the overlays have to be added to dtb-y explicitly.
Add the overlays for platforms supported by Armbian.
Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
---
arch/arm64/boot/dts/freescale/Makefile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 9a55a86ad385b..fb5073196fdf5 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -347,8 +347,11 @@ imx8mp-tqma8mpql-mba8mp-ras314-imx219-dtbs += imx8mp-tqma8mpql-mba8mp-ras314.dtb
imx8mp-tqma8mpql-mba8mp-ras314-lvds-tm070jvhg33-dtbs += imx8mp-tqma8mpql-mba8mp-ras314.dtb imx8mp-tqma8mpql-mba8mpxl-lvds-tm070jvhg33.dtbo
imx8mp-tqma8mpql-mba8mp-ras314-lvds-tm070jvhg33-imx219-dtbs += imx8mp-tqma8mpql-mba8mp-ras314.dtb imx8mp-tqma8mpql-mba8mpxl-lvds-tm070jvhg33.dtbo imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds-g133han01.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds-tm070jvhg33.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mpxl-lvds-tm070jvhg33.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-imx219.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-lvds-tm070jvhg33.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mp-tqma8mpql-mba8mp-ras314-lvds-tm070jvhg33-imx219.dtb
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2] tty: atmel_serial: update outdated reference to atmel_tasklet_func()
From: Greg KH @ 2026-03-24 7:58 UTC (permalink / raw)
To: Richard GENOUD
Cc: Kexin Sun, jirislaby, nicolas.ferre, alexandre.belloni,
claudiu.beznea, linux-kernel, linux-serial, linux-arm-kernel,
julia.lawall, xutong.ma, yunbolyu, ratnadiraw
In-Reply-To: <89bc9543-9fcb-4563-b6ff-01b186231ce8@bootlin.com>
On Tue, Mar 24, 2026 at 08:08:40AM +0100, Richard GENOUD wrote:
> Le 24/03/2026 à 03:48, Kexin Sun a écrit :
> > The modem-status comparison that used irq_status_prev was
> > moved from atmel_tasklet_func() into atmel_handle_status() in
> > commit d033e82db9a5 ("tty/serial: at91: handle IRQ status
> > more safely"). Update the comment accordingly.
> Double space here, but I don't think it's necessary to send another
> iteration for that.
Double spaces are the "real way", so this is all good :)
^ permalink raw reply
* Re: [PATCH] media: cedrus: validate H.264 reference list indices
From: Jernej Škrabec @ 2026-03-24 7:56 UTC (permalink / raw)
To: Maxime Ripard, Paul Kocialkowski, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Chen-Yu Tsai, Samuel Holland, Pengpeng Hou
Cc: linux-media, linux-staging, linux-arm-kernel, linux-sunxi,
linux-kernel, pengpeng, nicolas.dufresne
In-Reply-To: <20260324020431.1800-1-pengpeng@iscas.ac.cn>
CC: Nicolas
Dne torek, 24. marec 2026 ob 03:04:31 Srednjeevropski standardni čas je Pengpeng Hou napisal(a):
> Cedrus validates HEVC slice reference lists in cedrus_try_ctrl(), but
> the H.264 path still consumes ref_pic_list0/ref_pic_list1 indices
> straight from the stateless slice control. Those indices are later
> used to index the fixed-size decode_params->dpb[] array in
> _cedrus_write_ref_list().
>
> Reject H.264 slice controls whose active reference counts or
> reference indices exceed V4L2_H264_NUM_DPB_ENTRIES before the driver
> reaches the DPB lookup. This keeps the validation next to the existing
> Cedrus stateless control checks and avoids driver-specific
> out-of-bounds reads from malformed userspace control payloads.
>
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
This has same issue as doing it in common code, e.g. it would break
userspace.
One improvement would be to skip all indices which have value higher
or equal to V4L2_H264_NUM_DPB_ENTRIES here:
https://elixir.bootlin.com/linux/v6.19.9/source/drivers/staging/media/sunxi/cedrus/cedrus_h264.c#L212
Best regards,
Jernej
> ---
> drivers/staging/media/sunxi/cedrus/cedrus.c | 23 +++++++++++++++++++++
> 1 file changed, 23 insertions(+)
>
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
> index d68da1eaa7aa..905084c097a9 100644
> --- a/drivers/staging/media/sunxi/cedrus/cedrus.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
> @@ -42,6 +42,29 @@ static int cedrus_try_ctrl(struct v4l2_ctrl *ctrl)
> if (sps->bit_depth_luma_minus8 != 0)
> /* Only 8-bit is supported */
> return -EINVAL;
> + } else if (ctrl->id == V4L2_CID_STATELESS_H264_SLICE_PARAMS) {
> + const struct v4l2_ctrl_h264_slice_params *slice = ctrl->p_new.p_h264_slice_params;
> + unsigned int i;
> +
> + if (slice->num_ref_idx_l0_active_minus1 >=
> + V4L2_H264_NUM_DPB_ENTRIES)
> + return -EINVAL;
> +
> + for (i = 0; i <= slice->num_ref_idx_l0_active_minus1; i++)
> + if (slice->ref_pic_list0[i].index >=
> + V4L2_H264_NUM_DPB_ENTRIES)
> + return -EINVAL;
> +
> + if (slice->slice_type == V4L2_H264_SLICE_TYPE_B) {
> + if (slice->num_ref_idx_l1_active_minus1 >=
> + V4L2_H264_NUM_DPB_ENTRIES)
> + return -EINVAL;
> +
> + for (i = 0; i <= slice->num_ref_idx_l1_active_minus1; i++)
> + if (slice->ref_pic_list1[i].index >=
> + V4L2_H264_NUM_DPB_ENTRIES)
> + return -EINVAL;
> + }
> } else if (ctrl->id == V4L2_CID_STATELESS_HEVC_SPS) {
> const struct v4l2_ctrl_hevc_sps *sps = ctrl->p_new.p_hevc_sps;
> struct cedrus_ctx *ctx = container_of(ctrl->handler, struct cedrus_ctx, hdl);
>
^ permalink raw reply
* Re: [PATCH] firmware: arm_scmi: clock: Relax check in scmi_clock_protocol_init
From: Sudeep Holla @ 2026-03-24 7:49 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Cristian Marussi, Sudeep Holla, Jacky Bai, arm-scmi,
linux-arm-kernel, linux-kernel, Peng Fan
In-Reply-To: <20260324-scmi-clock-fix-v1-v1-1-65c21935824b@nxp.com>
On Tue, Mar 24, 2026 at 02:24:14PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> On i.MX95, the SCMI Clock protocol defines several reserved clock IDs that
> are not backed by real clock devices
> (see arch/arm64/boot/dts/freescale/imx95-clock.h).
>
> For these reserved IDs, the SCMI firmware correctly returns NOT_FOUND in
> response to the CLOCK_ATTRIBUTES command. According to the SCMI Clock
> specification, NOT_FOUND is expected when a clock_id does not correspond to
> a valid clock device.
>
> The recent hardening added in scmi_clock_protocol_init() treats any error
> return as fatal, causing SCMI clock probe to fail and preventing i.MX9
> platforms from booting.
>
> Relax the check so that -ENOENT is treated as a non-fatal condition.
>
I understand the use-case and the fix here, but still wonder if this
should be treated as quirk or handle it in the core. I am inclined to
latter as reserved SCMI clock/resource ID seems to be trend in its usage
and hard to classify as quirks.
Cristain, agree or have a different view ?
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v7 14/20] coresight: Control path with range
From: Leo Yan @ 2026-03-24 7:48 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: Mike Leach, James Clark, Yeoreum Yun, Mark Rutland, Will Deacon,
Yabin Cui, Keita Morisaki, Yuanfang Zhang, Greg Kroah-Hartman,
Alexander Shishkin, coresight, linux-arm-kernel
In-Reply-To: <45af1506-c08d-4f7a-b07b-90666092680b@arm.com>
On Mon, Mar 23, 2026 at 10:01:52AM +0000, Suzuki K Poulose wrote:
[...]
> > +static struct coresight_node *
> > +coresight_path_last_node(struct coresight_path *path)
> > +{
> > + return list_last_entry(&path->path_list, struct coresight_node, link);
> > +}
> > +
>
> nit: This could be used for in coresight_get_sink().
Will do.
> > +static bool coresight_path_nodes_in_order(struct coresight_path *path,
> > + struct coresight_node *from,
> > + struct coresight_node *to)
>
> I am not very clear what this is supposed to do and what it is doing ?
> Are we verifying that the nodes @from and @to are in order ? As, in the
> the link is from @from to @to ? In that case what you do may not be
> sufficient ?
My purpose is that coresight_path_nodes_in_order() checks if *from and
*to are sequential on the link. This is a internal function to detect
any buggy code written in callers.
An assumption is all callers must obtain nodes from the path before
passing them in coresight_path_nodes_in_order(). Therefore, the check
is simplified to only verify that *from appears before *to.
> Rather, we should walk the path from @from and return if we find @to on the
> walk. Otherwise return false ? In any case,this need a comment on
> the top.
Sure, I will refine the walk code like this way and add a comment.
> Also I don't think this check is really needed. If we don't find the
> @to, simply disable the entire path.
If we allow @to to be NULL, we may also need to allow @from to be NULL
(e.g. in the enable path case).
Instead, callers can fetch the first and last nodes using helpers and
explicitly pass them to the enable and disable functions. Although this
introduces some duplicate code in callers, it avoids complexity in the
enable and disable functions.
> > +{
> > + struct coresight_node *nd;
> > +
> > + /* Callers must fetch nodes from the path */
> > + if (WARN_ON_ONCE(!from || !to))
> > + return false;
> > +
> > + list_for_each_entry(nd, &path->path_list, link) {
> > + if (nd == from)
> > + return true;
> > + if (nd == to)
> > + return false;
> > + }
> > +
> > + return false;
> > +}
> > +
> > /*
> > - * coresight_disable_path_from : Disable components in the given path beyond
> > - * @nd in the list. If @nd is NULL, all the components, except the SOURCE are
> > - * disabled.
> > + * coresight_disable_path_from_to : Disable components in the given @path
> > + * between @from and @to.
> > + *
> > + * The range excludes @from but includes @to. @from is exclusive to handle the
> > + * case where it is the source (the first node in the path), as the source has
> > + * its own disable function.
>
> Why not break that "hack" and always include @from and let the caller now
> use this helper to disable everything after the @source ?
Will do for this and below suggestions.
Thanks,
Leo
^ permalink raw reply
* [PATCH] dt-bindings: sound: mediatek,mt8173-rt5650-rt5514: convert to DT schema
From: Khushal Chitturi @ 2026-03-24 7:46 UTC (permalink / raw)
To: lgirdwood, broonie
Cc: robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
koro.chen, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, Khushal Chitturi
Convert the Mediatek MT8173 with RT5650 and RT5514 sound card
bindings to YAML schema.
Signed-off-by: Khushal Chitturi <khushalchitturi@gmail.com>
---
.../sound/mediatek,mt8173-rt5650-rt5514.yaml | 41 +++++++++++++++++++
.../bindings/sound/mt8173-rt5650-rt5514.txt | 15 -------
2 files changed, 41 insertions(+), 15 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt8173-rt5650-rt5514.yaml
delete mode 100644 Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8173-rt5650-rt5514.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8173-rt5650-rt5514.yaml
new file mode 100644
index 000000000000..05bb18006e08
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8173-rt5650-rt5514.yaml
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt8173-rt5650-rt5514.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8173 with RT5650 and RT5514 audio codecs
+
+maintainers:
+ - Koro Chen <koro.chen@mediatek.com>
+
+properties:
+ compatible:
+ const: mediatek,mt8173-rt5650-rt5514
+
+ mediatek,audio-codec:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: Phandles of rt5650 and rt5514 codecs
+ items:
+ - description: phandle of rt5650 codec
+ - description: phandle of rt5514 codec
+
+ mediatek,platform:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: The phandle of MT8173 ASoC platform.
+
+additionalProperties: false
+
+required:
+ - compatible
+ - mediatek,audio-codec
+ - mediatek,platform
+
+examples:
+ - |
+ sound {
+ compatible = "mediatek,mt8173-rt5650-rt5514";
+ mediatek,audio-codec = <&rt5650 &rt5514>;
+ mediatek,platform = <&afe>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt
deleted file mode 100644
index e8b3c80c6fff..000000000000
--- a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-MT8173 with RT5650 RT5514 CODECS
-
-Required properties:
-- compatible : "mediatek,mt8173-rt5650-rt5514"
-- mediatek,audio-codec: the phandles of rt5650 and rt5514 codecs
-- mediatek,platform: the phandle of MT8173 ASoC platform
-
-Example:
-
- sound {
- compatible = "mediatek,mt8173-rt5650-rt5514";
- mediatek,audio-codec = <&rt5650 &rt5514>;
- mediatek,platform = <&afe>;
- };
-
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v2] raid6: arm64: add SVE optimized implementation for syndrome generation
From: Christoph Hellwig @ 2026-03-24 7:45 UTC (permalink / raw)
To: Demian Shulhan
Cc: Song Liu, Yu Kuai, Li Nan, linux-raid, linux-kernel,
kernel test robot, Catalin Marinas, Ard Biesheuvel, Will Deacon,
linux-arm-kernel
In-Reply-To: <20260318150245.3080719-1-demyansh@gmail.com>
Hi Damian,
thanks for looking into this.
I've added the arm64 maintainers and arm list as that's your best bet
for someone actually understanding the low-level assembly code.
On Wed, Mar 18, 2026 at 03:02:45PM +0000, Demian Shulhan wrote:
> Note that for the recovery path (`xor_syndrome`), NEON may still be
> selected dynamically by the algorithm benchmark, as the recovery
> workload is heavily memory-bound.
The recovery side has no benchmarking, you need to manually select
a priority.
Note that I just sent out a "cleanup the RAID6 P/Q library" series that
make this more explicit. It also make it clear by prioritizing
implementations using better instructions available we can short-cut
the generation side probing path a lot, which might be worth looking
into for this.
I'm also curious if you looked why the 4x unroll is slower than
the lesser unroll, and if that is inherent in the implementation. Or
just an effect of the small number of disks in that we don't actually
have 4 disks to unroll for every other iteration. I.e. what would the
numbers be if RAID6_TEST_DISKS was increased to 10 or 18?
I plan into potentially select the unrolling variants based on the
number of "disks" to calculate over as a follow-on.
We'll have to wait for review on my series, but I'd love to just rebase
this ontop if possible. I can offer to do the work, but I'd need to
run it past you for testing and final review.
> +static void raid6_sve1_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs)
Overly long line.
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = disks - 3;
> +
> + p = dptr[z0 + 1];
> + q = dptr[z0 + 2];
I know all this is derived from existing code, but as I started to hate
that I'll add my cosmetic comments:
This would read nicer by initializing at declaration time:
u8 **dptr = (u8 **)ptrs;
long z0 = disks - 3;
u8 *p = dptr[z0 + 1];
u8 *q = dptr[z0 + 2];
Also z0 might better be named z_last or last_disk, or stop as in the
_xor variant routines.
> + asm volatile(
But I wonder if just implementing the entire routine as assembly in a
.S file would make more sense than this anyway?
> +static void raid6_sve1_xor_syndrome_real(int disks, int start, int stop,
> + unsigned long bytes, void **ptrs)
> +{
> + u8 **dptr = (u8 **)ptrs;
> + u8 *p, *q;
> + long z0 = stop;
> +
> + p = dptr[disks - 2];
> + q = dptr[disks - 1];
> +
> + asm volatile(
Same comments here, plus just dropping z0 vs using stop directly.
> +#define RAID6_SVE_WRAPPER(_n) \
> + static void raid6_sve ## _n ## _gen_syndrome(int disks, \
> + size_t bytes, void **ptrs) \
> + { \
> + scoped_ksimd() \
> + raid6_sve ## _n ## _gen_syndrome_real(disks, \
> + (unsigned long)bytes, ptrs); \
Missing indentation after the scoped_ksimd(). A lot of other code uses
separate compilation units for the SIMD code, which seems pretty useful
to avoid mixing SIMD with non-SIMD code. That would also combine nicely
with the suggestion above to implement the low-level routines entirely
in assembly.
I'll leave comments on the actual assembly details to people that
actually know ARM64 assembly.
^ permalink raw reply
* Re: [PATCH net-next v5 1/3] dt-bindings: ethernet: eswin: add clock sampling control
From: 李志 @ 2026-03-24 7:42 UTC (permalink / raw)
To: krzk+dt
Cc: linux-arm-kernel, rmk+kernel, mcoquelin.stm32, robh, kuba,
edumazet, davem, andrew+netdev, alexandre.torgue, devicetree,
pabeni, netdev, conor+dt, linux-riscv, alex, aou, palmer, pjw,
linux-stm32, maxime.chevallier, ningyu, linmin, pinkesh.vaghela,
linux-kernel, pritesh.patel, weishangjuan, horms, Conor Dooley
In-Reply-To: <20260324073137.396-1-lizhi2@eswincomputing.com>
Hi Krzysztof,
This version keeps the compatible naming from v4. Do you have any
comments or suggestions on the compatible or binding?
Thanks,
Zhi Li
> -----原始邮件-----
> 发件人: lizhi2@eswincomputing.com
> 发送时间:2026-03-24 15:31:36 (星期二)
> 收件人: devicetree@vger.kernel.org, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, netdev@vger.kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, rmk+kernel@armlinux.org.uk, pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu, alex@ghiti.fr, linux-riscv@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, maxime.chevallier@bootlin.com
> 抄送: ningyu@eswincomputing.com, linmin@eswincomputing.com, pinkesh.vaghela@einfochips.com, pritesh.patel@einfochips.com, weishangjuan@eswincomputing.com, horms@kernel.org, "Zhi Li" <lizhi2@eswincomputing.com>, "Conor Dooley" <conor.dooley@microchip.com>
> 主题: [PATCH net-next v5 1/3] dt-bindings: ethernet: eswin: add clock sampling control
>
> From: Zhi Li <lizhi2@eswincomputing.com>
>
> Due to chip backend reasons, there is already an approximately 4-5 ns
> skew between the RX clock and data of the eth1 MAC controller inside
> the silicon.
>
> For 1000M, the RX clock must be inverted since it is not possible to
> meet the RGMII timing requirements using only rx-internal-delay-ps on
> the MAC together with the standard 2 ns delay on the PHY. Therefore,
> even on a properly designed board, eth1 still requires RX clock
> inversion.
>
> This behaviour effectively breaks the RGMII timing assumptions at the
> SoC level.
>
> For the TX path of eth1, there is also a skew between the TX clock
> and data on the MAC controller inside the silicon. This skew happens
> to be approximately 2 ns. Therefore, it can be considered that the
> 2 ns delay of TX is provided by the MAC, so the TX is compliant with
> the RGMII standard.
>
> For 10/100 operation, the approximately 4-5 ns skew in the chip does
> not break the standard. The RGMII timing table (Section 3.3) specifies
> that for 10/100 operation the maximum value is unspecified:
> https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors/20655/1/RGMIIv2_0_final_hp.pdf
>
> Due to the eth1 silicon behavior described above, a new compatible
> string "eswin,eic7700-qos-eth-clk-inversion" is added to the device
> tree. This allows the driver to handle the differences between eth1
> and eth0 through dedicated logic.
>
> The rx-internal-delay-ps and tx-internal-delay-ps properties now use
> minimum and maximum constraints to reflect the actual hardware delay
> range (0-2540 ps) applied in 20 ps steps. This relaxes the binding
> validation compared to the previous enum-based definition and avoids
> regressions for existing DTBs while keeping the same hardware limits.
>
> Treat the RX/TX internal delay properties as optional, board-specific
> tuning knobs and remove them from the example to avoid encouraging
> their use.
>
> In addition, the binding now includes additional background information
> about the HSP CSR registers accessed by the MAC. The TXD and RXD delay
> control registers are included so the driver can explicitly clear any
> residual configuration left by the bootloader.
>
> Background reference for the High-Speed Subsystem and HSP CSR block is
> available in Chapter 10 ("High-Speed Interface") of the EIC7700X SoC
> Technical Reference Manual, Part 4
> (EIC7700X_SoC_Technical_Reference_Manual_Part4.pdf):
> https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual/releases
>
> There are currently no in-tree users of the EIC7700 Ethernet driver, so
> these changes are safe.
>
> Fixes: 888bd0eca93c ("dt-bindings: ethernet: eswin: Document for EIC7700 SoC")
> Signed-off-by: Zhi Li <lizhi2@eswincomputing.com>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> ---
> .../bindings/net/eswin,eic7700-eth.yaml | 69 +++++++++++++++----
> 1 file changed, 55 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml
> index 91e8cd1db67b..0b27719feb7d 100644
> --- a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml
> +++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml
> @@ -20,6 +20,7 @@ select:
> contains:
> enum:
> - eswin,eic7700-qos-eth
> + - eswin,eic7700-qos-eth-clk-inversion
> required:
> - compatible
>
> @@ -29,7 +30,9 @@ allOf:
> properties:
> compatible:
> items:
> - - const: eswin,eic7700-qos-eth
> + - enum:
> + - eswin,eic7700-qos-eth
> + - eswin,eic7700-qos-eth-clk-inversion
> - const: snps,dwmac-5.20
>
> reg:
> @@ -63,16 +66,29 @@ properties:
> - const: stmmaceth
>
> rx-internal-delay-ps:
> - enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400]
> + minimum: 0
> + maximum: 2540
> + multipleOf: 20
>
> tx-internal-delay-ps:
> - enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400]
> + minimum: 0
> + maximum: 2540
> + multipleOf: 20
>
> eswin,hsp-sp-csr:
> description:
> HSP CSR is to control and get status of different high-speed peripherals
> (such as Ethernet, USB, SATA, etc.) via register, which can tune
> board-level's parameters of PHY, etc.
> +
> + Additional background information about the High-Speed Subsystem
> + and the HSP CSR block is available in Chapter 10 ("High-Speed Interface")
> + of the EIC7700X SoC Technical Reference Manual, Part 4
> + (EIC7700X_SoC_Technical_Reference_Manual_Part4.pdf). The manual is
> + publicly available at
> + https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual/releases
> +
> + This reference is provided for background information only.
> $ref: /schemas/types.yaml#/definitions/phandle-array
> items:
> - items:
> @@ -82,6 +98,8 @@ properties:
> - description: Offset of AXI clock controller Low-Power request
> register
> - description: Offset of register controlling TX/RX clock delay
> + - description: Offset of register controlling TXD delay
> + - description: Offset of register controlling RXD delay
>
> required:
> - compatible
> @@ -93,8 +111,6 @@ required:
> - phy-mode
> - resets
> - reset-names
> - - rx-internal-delay-ps
> - - tx-internal-delay-ps
> - eswin,hsp-sp-csr
>
> unevaluatedProperties: false
> @@ -104,24 +120,49 @@ examples:
> ethernet@50400000 {
> compatible = "eswin,eic7700-qos-eth", "snps,dwmac-5.20";
> reg = <0x50400000 0x10000>;
> + interrupt-parent = <&plic>;
> + interrupts = <61>;
> + interrupt-names = "macirq";
> clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>,
> <&d0_clock 193>;
> clock-names = "axi", "cfg", "stmmaceth", "tx";
> + resets = <&reset 95>;
> + reset-names = "stmmaceth";
> + eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118 0x114 0x11c>;
> + phy-handle = <&gmac0_phy0>;
> + phy-mode = "rgmii-id";
> + snps,aal;
> + snps,fixed-burst;
> + snps,tso;
> + snps,axi-config = <&stmmac_axi_setup_gmac0>;
> +
> + stmmac_axi_setup_gmac0: stmmac-axi-config {
> + snps,blen = <0 0 0 0 16 8 4>;
> + snps,rd_osr_lmt = <2>;
> + snps,wr_osr_lmt = <2>;
> + };
> + };
> +
> + ethernet@50410000 {
> + compatible = "eswin,eic7700-qos-eth-clk-inversion", "snps,dwmac-5.20";
> + reg = <0x50410000 0x10000>;
> interrupt-parent = <&plic>;
> - interrupts = <61>;
> + interrupts = <70>;
> interrupt-names = "macirq";
> - phy-mode = "rgmii-id";
> - phy-handle = <&phy0>;
> - resets = <&reset 95>;
> + clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>,
> + <&d0_clock 194>;
> + clock-names = "axi", "cfg", "stmmaceth", "tx";
> + resets = <&reset 94>;
> reset-names = "stmmaceth";
> - rx-internal-delay-ps = <200>;
> - tx-internal-delay-ps = <200>;
> - eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118>;
> - snps,axi-config = <&stmmac_axi_setup>;
> + eswin,hsp-sp-csr = <&hsp_sp_csr 0x200 0x208 0x218 0x214 0x21c>;
> + phy-handle = <&gmac1_phy0>;
> + phy-mode = "rgmii-id";
> snps,aal;
> snps,fixed-burst;
> snps,tso;
> - stmmac_axi_setup: stmmac-axi-config {
> + snps,axi-config = <&stmmac_axi_setup_gmac1>;
> +
> + stmmac_axi_setup_gmac1: stmmac-axi-config {
> snps,blen = <0 0 0 0 16 8 4>;
> snps,rd_osr_lmt = <2>;
> snps,wr_osr_lmt = <2>;
> --
> 2.25.1
^ permalink raw reply
* [PATCH net-next v5 3/3] riscv: dts: eswin: eic7700-hifive-premier-p550: enable Ethernet controller
From: lizhi2 @ 2026-03-24 7:34 UTC (permalink / raw)
To: devicetree, andrew+netdev, davem, edumazet, kuba, robh, krzk+dt,
conor+dt, netdev, pabeni, mcoquelin.stm32, alexandre.torgue,
rmk+kernel, pjw, palmer, aou, alex, linux-riscv, linux-stm32,
linux-arm-kernel, linux-kernel, maxime.chevallier
Cc: ningyu, linmin, pinkesh.vaghela, pritesh.patel, weishangjuan,
horms, Zhi Li
In-Reply-To: <20260324073017.376-1-lizhi2@eswincomputing.com>
From: Zhi Li <lizhi2@eswincomputing.com>
Enable the on-board Gigabit Ethernet controller on the
HiFive Premier P550 development board.
Signed-off-by: Zhi Li <lizhi2@eswincomputing.com>
---
.../dts/eswin/eic7700-hifive-premier-p550.dts | 42 ++++++++++++
arch/riscv/boot/dts/eswin/eic7700.dtsi | 66 +++++++++++++++++++
2 files changed, 108 insertions(+)
diff --git a/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts b/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
index 131ed1fc6b2e..5a40be1d2a25 100644
--- a/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
+++ b/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
@@ -13,6 +13,8 @@ / {
aliases {
serial0 = &uart0;
+ ethernet0 = &gmac0;
+ ethernet1 = &gmac1;
};
chosen {
@@ -20,6 +22,46 @@ chosen {
};
};
+&gmac0 {
+ phy-handle = <&gmac0_phy0>;
+ phy-mode = "rgmii-id";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio106_pins>;
+ rx-internal-delay-ps = <20>;
+ tx-internal-delay-ps = <100>;
+ status = "okay";
+
+ mdio {
+ gmac0_phy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0>;
+ reset-gpios = <&gpioD 10 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <80000>;
+ };
+ };
+};
+
+&gmac1 {
+ phy-handle = <&gmac1_phy0>;
+ phy-mode = "rgmii-rxid";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio111_pins>;
+ rx-internal-delay-ps = <200>;
+ tx-internal-delay-ps = <200>;
+ status = "okay";
+
+ mdio {
+ gmac1_phy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0>;
+ reset-gpios = <&gpioD 15 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <10000>;
+ reset-deassert-us = <80000>;
+ };
+ };
+};
+
&uart0 {
status = "okay";
};
diff --git a/arch/riscv/boot/dts/eswin/eic7700.dtsi b/arch/riscv/boot/dts/eswin/eic7700.dtsi
index c3ed93008bca..f1a01d5736a1 100644
--- a/arch/riscv/boot/dts/eswin/eic7700.dtsi
+++ b/arch/riscv/boot/dts/eswin/eic7700.dtsi
@@ -5,6 +5,8 @@
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+
/ {
#address-cells = <2>;
#size-cells = <2>;
@@ -295,6 +297,70 @@ uart4: serial@50940000 {
status = "disabled";
};
+ gmac0: ethernet@50400000 {
+ compatible = "eswin,eic7700-qos-eth", "snps,dwmac-5.20";
+ reg = <0x0 0x50400000 0x0 0x10000>;
+ interrupts = <61>;
+ interrupt-names = "macirq";
+ clocks = <&clk 186>,
+ <&clk 171>,
+ <&clk 40>,
+ <&clk 193>;
+ clock-names = "axi", "cfg", "stmmaceth", "tx";
+ resets = <&reset 95>;
+ reset-names = "stmmaceth";
+ eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118 0x114 0x11c>;
+ snps,aal;
+ snps,fixed-burst;
+ snps,tso;
+ snps,axi-config = <&stmmac_axi_setup_gmac0>;
+ status = "disabled";
+
+ stmmac_axi_setup_gmac0: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <2>;
+ snps,wr_osr_lmt = <2>;
+ };
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ gmac1: ethernet@50410000 {
+ compatible = "eswin,eic7700-qos-eth-clk-inversion", "snps,dwmac-5.20";
+ reg = <0x0 0x50410000 0x0 0x10000>;
+ interrupts = <70>;
+ interrupt-names = "macirq";
+ clocks = <&clk 186>,
+ <&clk 171>,
+ <&clk 40>,
+ <&clk 194>;
+ clock-names = "axi", "cfg", "stmmaceth", "tx";
+ resets = <&reset 94>;
+ reset-names = "stmmaceth";
+ eswin,hsp-sp-csr = <&hsp_sp_csr 0x200 0x208 0x218 0x214 0x21c>;
+ snps,aal;
+ snps,fixed-burst;
+ snps,tso;
+ snps,axi-config = <&stmmac_axi_setup_gmac1>;
+ status = "disabled";
+
+ stmmac_axi_setup_gmac1: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <2>;
+ snps,wr_osr_lmt = <2>;
+ };
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
gpio@51600000 {
compatible = "snps,dw-apb-gpio";
reg = <0x0 0x51600000 0x0 0x80>;
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v5 2/3] net: stmmac: eic7700: enable clocks before syscon access and correct RX sampling timing
From: lizhi2 @ 2026-03-24 7:32 UTC (permalink / raw)
To: devicetree, andrew+netdev, davem, edumazet, kuba, robh, krzk+dt,
conor+dt, netdev, pabeni, mcoquelin.stm32, alexandre.torgue,
rmk+kernel, pjw, palmer, aou, alex, linux-riscv, linux-stm32,
linux-arm-kernel, linux-kernel, maxime.chevallier
Cc: ningyu, linmin, pinkesh.vaghela, pritesh.patel, weishangjuan,
horms, Zhi Li
In-Reply-To: <20260324073017.376-1-lizhi2@eswincomputing.com>
From: Zhi Li <lizhi2@eswincomputing.com>
The second Ethernet controller (eth1) on the Eswin EIC7700 SoC may fail
to sample RX data correctly at Gigabit speed due to EIC7700-specific
receive clock to data skew at the MAC input in the silicon.
The existing internal delay configuration does not provide sufficient
adjustment range to compensate for this condition at 1000Mbps.
Update the EIC7700 DWMAC glue driver to apply EIC7700-specific clock
sampling inversion only during Gigabit operation on MAC instances
that require it.
TXD and RXD delay registers are explicitly cleared during initialization
to override any residual configuration left by the bootloader. All HSP
CSR register accesses are performed only after the required clocks are
enabled.
Fixes: ea77dbbdbc4e ("net: stmmac: add Eswin EIC7700 glue driver")
Signed-off-by: Zhi Li <lizhi2@eswincomputing.com>
---
.../ethernet/stmicro/stmmac/dwmac-eic7700.c | 183 ++++++++++++++----
1 file changed, 140 insertions(+), 43 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c
index bcb8e000e720..33144611da8d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c
@@ -28,20 +28,40 @@
/*
* TX/RX Clock Delay Bit Masks:
- * - TX Delay: bits [14:8] — TX_CLK delay (unit: 0.1ns per bit)
- * - RX Delay: bits [30:24] — RX_CLK delay (unit: 0.1ns per bit)
+ * - TX Delay: bits [14:8] — TX_CLK delay (unit: 0.02ns per bit)
+ * - TX Invert : bit [15]
+ * - RX Delay: bits [30:24] — RX_CLK delay (unit: 0.02ns per bit)
+ * - RX Invert : bit [31]
*/
#define EIC7700_ETH_TX_ADJ_DELAY GENMASK(14, 8)
#define EIC7700_ETH_RX_ADJ_DELAY GENMASK(30, 24)
+#define EIC7700_ETH_TX_INV_DELAY BIT(15)
+#define EIC7700_ETH_RX_INV_DELAY BIT(31)
-#define EIC7700_MAX_DELAY_UNIT 0x7F
+#define EIC7700_MAX_DELAY_STEPS 0x7F
+#define EIC7700_DELAY_STEP_PS 20
+#define EIC7700_MAX_DELAY_PS \
+ (EIC7700_MAX_DELAY_STEPS * EIC7700_DELAY_STEP_PS)
static const char * const eic7700_clk_names[] = {
"tx", "axi", "cfg",
};
+struct eic7700_dwmac_data {
+ bool rgmii_rx_clk_invert;
+};
+
struct eic7700_qos_priv {
+ struct device *dev;
struct plat_stmmacenet_data *plat_dat;
+ struct regmap *eic7700_hsp_regmap;
+ u32 eth_axi_lp_ctrl_offset;
+ u32 eth_phy_ctrl_offset;
+ u32 eth_txd_offset;
+ u32 eth_clk_offset;
+ u32 eth_rxd_offset;
+ u32 eth_clk_dly_param;
+ bool eth_rx_clk_inv;
};
static int eic7700_clks_config(void *priv, bool enabled)
@@ -61,8 +81,28 @@ static int eic7700_clks_config(void *priv, bool enabled)
static int eic7700_dwmac_init(struct device *dev, void *priv)
{
struct eic7700_qos_priv *dwc = priv;
+ int ret;
+
+ ret = eic7700_clks_config(dwc, true);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(dwc->eic7700_hsp_regmap,
+ dwc->eth_phy_ctrl_offset,
+ EIC7700_ETH_TX_CLK_SEL |
+ EIC7700_ETH_PHY_INTF_SELI);
+ if (ret) {
+ eic7700_clks_config(dwc, false);
+ return ret;
+ }
+
+ regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_axi_lp_ctrl_offset,
+ EIC7700_ETH_CSYSREQ_VAL);
+
+ regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_txd_offset, 0);
+ regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_rxd_offset, 0);
- return eic7700_clks_config(dwc, true);
+ return 0;
}
static void eic7700_dwmac_exit(struct device *dev, void *priv)
@@ -88,18 +128,35 @@ static int eic7700_dwmac_resume(struct device *dev, void *priv)
return ret;
}
+static void eic7700_dwmac_fix_speed(void *priv, phy_interface_t interface,
+ int speed, unsigned int mode)
+{
+ struct eic7700_qos_priv *dwc = (struct eic7700_qos_priv *)priv;
+ u32 dly_param = dwc->eth_clk_dly_param;
+
+ switch (speed) {
+ case SPEED_1000:
+ if (dwc->eth_rx_clk_inv)
+ dly_param |= EIC7700_ETH_RX_INV_DELAY;
+ break;
+ case SPEED_100:
+ case SPEED_10:
+ break;
+ default:
+ dev_err(dwc->dev, "invalid speed %u\n", speed);
+ break;
+ }
+
+ regmap_write(dwc->eic7700_hsp_regmap, dwc->eth_clk_offset, dly_param);
+}
+
static int eic7700_dwmac_probe(struct platform_device *pdev)
{
+ const struct eic7700_dwmac_data *data;
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
struct eic7700_qos_priv *dwc_priv;
- struct regmap *eic7700_hsp_regmap;
- u32 eth_axi_lp_ctrl_offset;
- u32 eth_phy_ctrl_offset;
- u32 eth_phy_ctrl_regset;
- u32 eth_rxd_dly_offset;
- u32 eth_dly_param = 0;
- u32 delay_ps;
+ u32 delay_ps, val;
int i, ret;
ret = stmmac_get_platform_resources(pdev, &stmmac_res);
@@ -116,70 +173,95 @@ static int eic7700_dwmac_probe(struct platform_device *pdev)
if (!dwc_priv)
return -ENOMEM;
+ dwc_priv->dev = &pdev->dev;
+
+ data = device_get_match_data(&pdev->dev);
+ if (!data)
+ return dev_err_probe(&pdev->dev,
+ -EINVAL, "no match data found\n");
+
+ dwc_priv->eth_rx_clk_inv = data->rgmii_rx_clk_invert;
+
/* Read rx-internal-delay-ps and update rx_clk delay */
if (!of_property_read_u32(pdev->dev.of_node,
"rx-internal-delay-ps", &delay_ps)) {
- u32 val = min(delay_ps / 100, EIC7700_MAX_DELAY_UNIT);
+ if (delay_ps % EIC7700_DELAY_STEP_PS)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "rx delay must be multiple of %dps\n",
+ EIC7700_DELAY_STEP_PS);
+
+ if (delay_ps > EIC7700_MAX_DELAY_PS)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "rx delay out of range\n");
- eth_dly_param &= ~EIC7700_ETH_RX_ADJ_DELAY;
- eth_dly_param |= FIELD_PREP(EIC7700_ETH_RX_ADJ_DELAY, val);
- } else {
- return dev_err_probe(&pdev->dev, -EINVAL,
- "missing required property rx-internal-delay-ps\n");
+ val = delay_ps / EIC7700_DELAY_STEP_PS;
+
+ dwc_priv->eth_clk_dly_param &= ~EIC7700_ETH_RX_ADJ_DELAY;
+ dwc_priv->eth_clk_dly_param |=
+ FIELD_PREP(EIC7700_ETH_RX_ADJ_DELAY, val);
}
/* Read tx-internal-delay-ps and update tx_clk delay */
if (!of_property_read_u32(pdev->dev.of_node,
"tx-internal-delay-ps", &delay_ps)) {
- u32 val = min(delay_ps / 100, EIC7700_MAX_DELAY_UNIT);
+ if (delay_ps % EIC7700_DELAY_STEP_PS)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "tx delay must be multiple of %dps\n",
+ EIC7700_DELAY_STEP_PS);
+
+ if (delay_ps > EIC7700_MAX_DELAY_PS)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "tx delay out of range\n");
+
+ val = delay_ps / EIC7700_DELAY_STEP_PS;
- eth_dly_param &= ~EIC7700_ETH_TX_ADJ_DELAY;
- eth_dly_param |= FIELD_PREP(EIC7700_ETH_TX_ADJ_DELAY, val);
- } else {
- return dev_err_probe(&pdev->dev, -EINVAL,
- "missing required property tx-internal-delay-ps\n");
+ dwc_priv->eth_clk_dly_param &= ~EIC7700_ETH_TX_ADJ_DELAY;
+ dwc_priv->eth_clk_dly_param |=
+ FIELD_PREP(EIC7700_ETH_TX_ADJ_DELAY, val);
}
- eic7700_hsp_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
- "eswin,hsp-sp-csr");
- if (IS_ERR(eic7700_hsp_regmap))
+ dwc_priv->eic7700_hsp_regmap =
+ syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "eswin,hsp-sp-csr");
+ if (IS_ERR(dwc_priv->eic7700_hsp_regmap))
return dev_err_probe(&pdev->dev,
- PTR_ERR(eic7700_hsp_regmap),
+ PTR_ERR(dwc_priv->eic7700_hsp_regmap),
"Failed to get hsp-sp-csr regmap\n");
ret = of_property_read_u32_index(pdev->dev.of_node,
"eswin,hsp-sp-csr",
- 1, ð_phy_ctrl_offset);
+ 1, &dwc_priv->eth_phy_ctrl_offset);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"can't get eth_phy_ctrl_offset\n");
- regmap_read(eic7700_hsp_regmap, eth_phy_ctrl_offset,
- ð_phy_ctrl_regset);
- eth_phy_ctrl_regset |=
- (EIC7700_ETH_TX_CLK_SEL | EIC7700_ETH_PHY_INTF_SELI);
- regmap_write(eic7700_hsp_regmap, eth_phy_ctrl_offset,
- eth_phy_ctrl_regset);
-
ret = of_property_read_u32_index(pdev->dev.of_node,
"eswin,hsp-sp-csr",
- 2, ð_axi_lp_ctrl_offset);
+ 2, &dwc_priv->eth_axi_lp_ctrl_offset);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"can't get eth_axi_lp_ctrl_offset\n");
- regmap_write(eic7700_hsp_regmap, eth_axi_lp_ctrl_offset,
- EIC7700_ETH_CSYSREQ_VAL);
+ ret = of_property_read_u32_index(pdev->dev.of_node,
+ "eswin,hsp-sp-csr",
+ 3, &dwc_priv->eth_clk_offset);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "can't get eth_clk_offset\n");
ret = of_property_read_u32_index(pdev->dev.of_node,
"eswin,hsp-sp-csr",
- 3, ð_rxd_dly_offset);
+ 4, &dwc_priv->eth_txd_offset);
if (ret)
return dev_err_probe(&pdev->dev, ret,
- "can't get eth_rxd_dly_offset\n");
+ "can't get eth_txd_offset\n");
- regmap_write(eic7700_hsp_regmap, eth_rxd_dly_offset,
- eth_dly_param);
+ ret = of_property_read_u32_index(pdev->dev.of_node,
+ "eswin,hsp-sp-csr",
+ 5, &dwc_priv->eth_rxd_offset);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "can't get eth_rxd_offset\n");
plat_dat->num_clks = ARRAY_SIZE(eic7700_clk_names);
plat_dat->clks = devm_kcalloc(&pdev->dev,
@@ -208,12 +290,27 @@ static int eic7700_dwmac_probe(struct platform_device *pdev)
plat_dat->exit = eic7700_dwmac_exit;
plat_dat->suspend = eic7700_dwmac_suspend;
plat_dat->resume = eic7700_dwmac_resume;
+ plat_dat->fix_mac_speed = eic7700_dwmac_fix_speed;
return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
}
+static const struct eic7700_dwmac_data eic7700_dwmac_data = {
+ .rgmii_rx_clk_invert = false,
+};
+
+static const struct eic7700_dwmac_data eic7700_dwmac_data_clk_inversion = {
+ .rgmii_rx_clk_invert = true,
+};
+
static const struct of_device_id eic7700_dwmac_match[] = {
- { .compatible = "eswin,eic7700-qos-eth" },
+ { .compatible = "eswin,eic7700-qos-eth",
+ .data = &eic7700_dwmac_data,
+ },
+ {
+ .compatible = "eswin,eic7700-qos-eth-clk-inversion",
+ .data = &eic7700_dwmac_data_clk_inversion,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, eic7700_dwmac_match);
--
2.25.1
^ permalink raw reply related
* [PATCH net-next v5 1/3] dt-bindings: ethernet: eswin: add clock sampling control
From: lizhi2 @ 2026-03-24 7:31 UTC (permalink / raw)
To: devicetree, andrew+netdev, davem, edumazet, kuba, robh, krzk+dt,
conor+dt, netdev, pabeni, mcoquelin.stm32, alexandre.torgue,
rmk+kernel, pjw, palmer, aou, alex, linux-riscv, linux-stm32,
linux-arm-kernel, linux-kernel, maxime.chevallier
Cc: ningyu, linmin, pinkesh.vaghela, pritesh.patel, weishangjuan,
horms, Zhi Li, Conor Dooley
In-Reply-To: <20260324073017.376-1-lizhi2@eswincomputing.com>
From: Zhi Li <lizhi2@eswincomputing.com>
Due to chip backend reasons, there is already an approximately 4-5 ns
skew between the RX clock and data of the eth1 MAC controller inside
the silicon.
For 1000M, the RX clock must be inverted since it is not possible to
meet the RGMII timing requirements using only rx-internal-delay-ps on
the MAC together with the standard 2 ns delay on the PHY. Therefore,
even on a properly designed board, eth1 still requires RX clock
inversion.
This behaviour effectively breaks the RGMII timing assumptions at the
SoC level.
For the TX path of eth1, there is also a skew between the TX clock
and data on the MAC controller inside the silicon. This skew happens
to be approximately 2 ns. Therefore, it can be considered that the
2 ns delay of TX is provided by the MAC, so the TX is compliant with
the RGMII standard.
For 10/100 operation, the approximately 4-5 ns skew in the chip does
not break the standard. The RGMII timing table (Section 3.3) specifies
that for 10/100 operation the maximum value is unspecified:
https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors/20655/1/RGMIIv2_0_final_hp.pdf
Due to the eth1 silicon behavior described above, a new compatible
string "eswin,eic7700-qos-eth-clk-inversion" is added to the device
tree. This allows the driver to handle the differences between eth1
and eth0 through dedicated logic.
The rx-internal-delay-ps and tx-internal-delay-ps properties now use
minimum and maximum constraints to reflect the actual hardware delay
range (0-2540 ps) applied in 20 ps steps. This relaxes the binding
validation compared to the previous enum-based definition and avoids
regressions for existing DTBs while keeping the same hardware limits.
Treat the RX/TX internal delay properties as optional, board-specific
tuning knobs and remove them from the example to avoid encouraging
their use.
In addition, the binding now includes additional background information
about the HSP CSR registers accessed by the MAC. The TXD and RXD delay
control registers are included so the driver can explicitly clear any
residual configuration left by the bootloader.
Background reference for the High-Speed Subsystem and HSP CSR block is
available in Chapter 10 ("High-Speed Interface") of the EIC7700X SoC
Technical Reference Manual, Part 4
(EIC7700X_SoC_Technical_Reference_Manual_Part4.pdf):
https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual/releases
There are currently no in-tree users of the EIC7700 Ethernet driver, so
these changes are safe.
Fixes: 888bd0eca93c ("dt-bindings: ethernet: eswin: Document for EIC7700 SoC")
Signed-off-by: Zhi Li <lizhi2@eswincomputing.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/net/eswin,eic7700-eth.yaml | 69 +++++++++++++++----
1 file changed, 55 insertions(+), 14 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml
index 91e8cd1db67b..0b27719feb7d 100644
--- a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml
+++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml
@@ -20,6 +20,7 @@ select:
contains:
enum:
- eswin,eic7700-qos-eth
+ - eswin,eic7700-qos-eth-clk-inversion
required:
- compatible
@@ -29,7 +30,9 @@ allOf:
properties:
compatible:
items:
- - const: eswin,eic7700-qos-eth
+ - enum:
+ - eswin,eic7700-qos-eth
+ - eswin,eic7700-qos-eth-clk-inversion
- const: snps,dwmac-5.20
reg:
@@ -63,16 +66,29 @@ properties:
- const: stmmaceth
rx-internal-delay-ps:
- enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400]
+ minimum: 0
+ maximum: 2540
+ multipleOf: 20
tx-internal-delay-ps:
- enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400]
+ minimum: 0
+ maximum: 2540
+ multipleOf: 20
eswin,hsp-sp-csr:
description:
HSP CSR is to control and get status of different high-speed peripherals
(such as Ethernet, USB, SATA, etc.) via register, which can tune
board-level's parameters of PHY, etc.
+
+ Additional background information about the High-Speed Subsystem
+ and the HSP CSR block is available in Chapter 10 ("High-Speed Interface")
+ of the EIC7700X SoC Technical Reference Manual, Part 4
+ (EIC7700X_SoC_Technical_Reference_Manual_Part4.pdf). The manual is
+ publicly available at
+ https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual/releases
+
+ This reference is provided for background information only.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
@@ -82,6 +98,8 @@ properties:
- description: Offset of AXI clock controller Low-Power request
register
- description: Offset of register controlling TX/RX clock delay
+ - description: Offset of register controlling TXD delay
+ - description: Offset of register controlling RXD delay
required:
- compatible
@@ -93,8 +111,6 @@ required:
- phy-mode
- resets
- reset-names
- - rx-internal-delay-ps
- - tx-internal-delay-ps
- eswin,hsp-sp-csr
unevaluatedProperties: false
@@ -104,24 +120,49 @@ examples:
ethernet@50400000 {
compatible = "eswin,eic7700-qos-eth", "snps,dwmac-5.20";
reg = <0x50400000 0x10000>;
+ interrupt-parent = <&plic>;
+ interrupts = <61>;
+ interrupt-names = "macirq";
clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>,
<&d0_clock 193>;
clock-names = "axi", "cfg", "stmmaceth", "tx";
+ resets = <&reset 95>;
+ reset-names = "stmmaceth";
+ eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118 0x114 0x11c>;
+ phy-handle = <&gmac0_phy0>;
+ phy-mode = "rgmii-id";
+ snps,aal;
+ snps,fixed-burst;
+ snps,tso;
+ snps,axi-config = <&stmmac_axi_setup_gmac0>;
+
+ stmmac_axi_setup_gmac0: stmmac-axi-config {
+ snps,blen = <0 0 0 0 16 8 4>;
+ snps,rd_osr_lmt = <2>;
+ snps,wr_osr_lmt = <2>;
+ };
+ };
+
+ ethernet@50410000 {
+ compatible = "eswin,eic7700-qos-eth-clk-inversion", "snps,dwmac-5.20";
+ reg = <0x50410000 0x10000>;
interrupt-parent = <&plic>;
- interrupts = <61>;
+ interrupts = <70>;
interrupt-names = "macirq";
- phy-mode = "rgmii-id";
- phy-handle = <&phy0>;
- resets = <&reset 95>;
+ clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>,
+ <&d0_clock 194>;
+ clock-names = "axi", "cfg", "stmmaceth", "tx";
+ resets = <&reset 94>;
reset-names = "stmmaceth";
- rx-internal-delay-ps = <200>;
- tx-internal-delay-ps = <200>;
- eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118>;
- snps,axi-config = <&stmmac_axi_setup>;
+ eswin,hsp-sp-csr = <&hsp_sp_csr 0x200 0x208 0x218 0x214 0x21c>;
+ phy-handle = <&gmac1_phy0>;
+ phy-mode = "rgmii-id";
snps,aal;
snps,fixed-burst;
snps,tso;
- stmmac_axi_setup: stmmac-axi-config {
+ snps,axi-config = <&stmmac_axi_setup_gmac1>;
+
+ stmmac_axi_setup_gmac1: stmmac-axi-config {
snps,blen = <0 0 0 0 16 8 4>;
snps,rd_osr_lmt = <2>;
snps,wr_osr_lmt = <2>;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH 0/5] arm64: dts: Add Corstone1000-A320 platform
From: Sudeep Holla @ 2026-03-24 7:31 UTC (permalink / raw)
To: Krzysztof Kozlowski, Conor Dooley, Liviu Dudau, Lorenzo Pieralisi,
Rob Herring (Arm)
Cc: Sudeep Holla, Frazer Carsley, Hugues Kamba Mpiana,
Abdellatif El Khlifi, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260320-dt-corstone1000-a320-v1-0-a549dfcfe8da@kernel.org>
On Fri, 20 Mar 2026 11:47:13 -0500, Rob Herring (Arm) wrote:
> The Corstone1000-A320 is a new Corstone1000 variation with Cortex-A320
> cores and an Ethos-U85 NPU. This series adds the new compatible strings,
> restructures the .dtsi files to handle the common parts, and then adds
> the new Corstone1000-A320 FVP platform.
Applied to sudeep.holla/linux (for-next/juno/updates), thanks!
[1/5] dt-bindings: arm,corstone1000: Add "arm,corstone1000-a320-fvp"
https://git.kernel.org/sudeep.holla/c/f9d162866f2f
[2/5] dt-bindings: npu: arm,ethos: Add "arm,corstone1000-ethos-u85"
https://git.kernel.org/sudeep.holla/c/55de145c8ec2
[3/5] arm64: dts: arm/corstone1000: Move cpu nodes
https://git.kernel.org/sudeep.holla/c/903528ac234a
[4/5] arm64: dts: arm/corstone1000: Move FVP peripherals to separate .dtsi
https://git.kernel.org/sudeep.holla/c/9c3904f94fdb
[5/5] arm64: dts: arm/corstone1000: Add corstone-1000-a320
https://git.kernel.org/sudeep.holla/c/87599f1843d3
--
Regards,
Sudeep
^ permalink raw reply
* [PATCH net-next v5 0/3] net: stmmac: eic7700: fix EIC7700 eth1 RX sampling timing
From: lizhi2 @ 2026-03-24 7:30 UTC (permalink / raw)
To: devicetree, andrew+netdev, davem, edumazet, kuba, robh, krzk+dt,
conor+dt, netdev, pabeni, mcoquelin.stm32, alexandre.torgue,
rmk+kernel, pjw, palmer, aou, alex, linux-riscv, linux-stm32,
linux-arm-kernel, linux-kernel, maxime.chevallier
Cc: ningyu, linmin, pinkesh.vaghela, pritesh.patel, weishangjuan,
horms, Zhi Li
From: Zhi Li <lizhi2@eswincomputing.com>
v4 -> v5:
- eswin,eic7700-eth.yaml:
- Add Acked-by from Conor Dooley
- No functional changes
- Update dwmac-eic7700.c:
- Disable clocks on the error path to fix a clock leak in
eic7700_dwmac_init() when regmap_set_bits() fails
(reported by Simon Horman <horms@kernel.org>)
- Link to v4:
https://lore.kernel.org/lkml/20260313075234.1567-1-lizhi2@eswincomputing.com/
v3 -> v4:
- Update eswin,eic7700-eth.yaml:
- Improve commit message in dt-bindings patch to clarify the
hardware difference of the eth1 MAC and why a new compatible
string is required.
- Move the newly added eswin,hsp-sp-csr item to the end of the list
to avoid inserting entries in the middle of the binding schema.
- Simplify the compatible schema by replacing the previous oneOf
construct with an enum.
- Update dwmac-eic7700.c:
- Fix build issues.
- Adjust code to match the updated binding definition.
- Update DTS/DTSI descriptions:
- Move SoC-level descriptions to the .dtsi file.
- Keep board-specific configuration in the .dts file.
- Link to v3:
https://lore.kernel.org/lkml/20260303061525.846-1-lizhi2@eswincomputing.com/
v2 -> v3:
- Update eswin,eic7700-eth.yaml:
- Extend rx-internal-delay-ps and tx-internal-delay-ps range
from 0-2400 to 0-2540 to match the full 7-bit hardware delay
field (127 * 20 ps).
- Add "multipleOf: 20" constraint to reflect the 20 ps hardware
step size.
- Make rx-internal-delay-ps and tx-internal-delay-ps optional.
A well-designed board should not require internal delay tuning.
- Remove rx-internal-delay-ps and tx-internal-delay-ps from the
example to avoid encouraging blind copy into board DTs.
- Update dwmac-eic7700.c:
- Treat rx-internal-delay-ps and tx-internal-delay-ps as optional
DT properties.
- Apply delay configuration only when properties are present.
- Keep TX/RX delay registers cleared by default to ensure a
deterministic state when no delay is specified.
- Describe Ethernet configuration for the HiFive Premier P550 board:
- Add GMAC controller nodes for the HiFive Premier P550 board
to describe the on-board Ethernet configuration.
The Ethernet controller depends on clock, reset, pinctrl
and HSP subsystem providers which are currently under
upstream review. These dependent nodes will be submitted
separately once the corresponding drivers are merged.
Due to these missing dependencies, dt-binding-check may
report warnings or failures for this series.
- No functional changes to RX clock inversion logic.
- Link to v2:
https://lore.kernel.org/lkml/20260209094628.886-1-lizhi2@eswincomputing.com/
- This series is based on the EIC7700 clock support series:
https://lore.kernel.org/all/20260210095008.726-1-dongxuyang@eswincomputing.com/
The clock series is currently under review.
v1 -> v2:
- Update eswin,eic7700-eth.yaml:
- Drop the vendor-specific properties eswin,rx-clk-invert and
eswin,tx-clk-invert.
- Introduce a distinct compatible string
"eswin,eic7700-qos-eth-clk-inversion" to describe MAC instances that
require internal RGMII clock inversion.
This models the SoC-specific hardware difference directly via the
compatible string and avoids per-board configuration properties.
- Change rx-internal-delay-ps and tx-internal-delay-ps from enum to
minimum/maximum to reflect the actual delay range (0-2400 ps)
- Add reference to High-Speed Subsystem documentation in eswin,hsp-sp-csr
description. The HSP CSR block is described in Chapter 10
("High-Speed Interface") of the EIC7700X SoC Technical Reference Manual,
Part 4 (EIC7700X_SoC_Technical_Reference_Manual_Part4.pdf):
https://github.com/eswincomputing/EIC7700X-SoC-Technical-Reference-Manual/releases
- Update dwmac-eic7700.c:
- Remove handling of eswin,rx-clk-invert and eswin,tx-clk-invert
properties.
- Select RX clock inversion based on the new
"eswin,eic7700-qos-eth-clk-inversion" compatible string, using
match data to apply the required configuration for affected MAC
instances (eth1).
- Link to v1:
https://lore.kernel.org/lkml/20260109080601.1262-1-lizhi2@eswincomputing.com/
Zhi Li (3):
dt-bindings: ethernet: eswin: add clock sampling control
net: stmmac: eic7700: enable clocks before syscon access and correct
RX sampling timing
riscv: dts: eswin: eic7700-hifive-premier-p550: enable Ethernet
controller
.../bindings/net/eswin,eic7700-eth.yaml | 69 +++++--
.../dts/eswin/eic7700-hifive-premier-p550.dts | 42 ++++
arch/riscv/boot/dts/eswin/eic7700.dtsi | 66 +++++++
.../ethernet/stmicro/stmmac/dwmac-eic7700.c | 183 ++++++++++++++----
4 files changed, 303 insertions(+), 57 deletions(-)
--
2.25.1
^ permalink raw reply
* Re: (subset) [PATCH v4 0/2] Add scmi powerdomain for sky1
From: Manivannan Sadhasivam @ 2026-03-24 7:17 UTC (permalink / raw)
To: lpieralisi, kwilczynski, robh, bhelgaas, krzk+dt, conor+dt,
peter.chen, Gary Yang
Cc: linux-pci, devicetree, linux-kernel, linux-arm-kernel,
cix-kernel-upstream
In-Reply-To: <20260313114914.1564115-1-gary.yang@cixtech.com>
On Fri, 13 Mar 2026 19:49:12 +0800, Gary Yang wrote:
> v4 changes:
> - Pass dts build check with below commands:
> make O=$OUTKNL dt_binding_check
> make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=cix,sky1-pcie-host.yaml
> make O=$OUTKNL CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb
> scripts/checkpatch.pl 000*.patch
> - delete power-domain-names property
>
> [...]
Applied, thanks!
[1/2] dt-bindings: PCI: cix,sky1-pcie-host: Add power-domains
commit: 94c62cf0698c0edbf1f118dd80ea19d0ff5d834e
Best regards,
--
Manivannan Sadhasivam <mani@kernel.org>
^ permalink raw reply
* Re: [PATCH v4 1/2] dt-bindings: PCI: cix,sky1-pcie-host: Add power-domains
From: Manivannan Sadhasivam @ 2026-03-24 7:13 UTC (permalink / raw)
To: Peter Chen
Cc: Krzysztof Kozlowski, Gary Yang, lpieralisi, kwilczynski, robh,
bhelgaas, krzk+dt, conor+dt, linux-pci, devicetree, linux-kernel,
linux-arm-kernel, cix-kernel-upstream
In-Reply-To: <abfEO6iW3NcnMyNx@nchen-desktop>
On Mon, Mar 16, 2026 at 04:50:03PM +0800, Peter Chen wrote:
> On 26-03-14 10:26:11, Krzysztof Kozlowski wrote:
> > EXTERNAL EMAIL
> >
> > On Fri, Mar 13, 2026 at 07:49:13PM +0800, Gary Yang wrote:
> > > The Sky1 PCIe controller resides in a dedicated power domain managed
> > > via SCMI. Add the power-domains property to the binding to allow
> > > describing this dependency.
> > >
> > > Signed-off-by: Gary Yang <gary.yang@cixtech.com>
> > > ---
> > > Documentation/devicetree/bindings/pci/cix,sky1-pcie-host.yaml | 3 +++
> > > 1 file changed, 3 insertions(+)
> >
> > Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> >
> Thank Krzysztof for kindly review it.
>
> Mani, I assume this patch will go to PCIe tree, right?
>
Yes, I'll take it.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* [PATCH v2 1/1] ARM: dts: microchip: sama7d65: add Cortex-A7 PMU node
From: Mihai Sain @ 2026-03-24 7:09 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, claudiu.beznea, robh, krzk+dt,
conor+dt
Cc: linux-arm-kernel, devicetree, linux-kernel, Mihai Sain
In-Reply-To: <20260324070927.1496-1-mihai.sain@microchip.com>
Add the Performance Monitoring Unit (PMU) node with the appropriate
compatible string and interrupt line so that perf and other
PMU-based tooling can function correctly on this SoC.
[root@SAMA7D65 ~]$ dmesg | grep -i pmu
[ 1.487869] hw-perfevents: enabled with armv7_cortex_a7 PMU driver, 5 (8000000f) counters available
[root@SAMA7D65 ~]$ perf list hw
List of pre-defined events (to be used in -e or -M):
branch-instructions OR branches [Hardware event]
branch-misses [Hardware event]
bus-cycles [Hardware event]
cache-misses [Hardware event]
cache-references [Hardware event]
cpu-cycles OR cycles [Hardware event]
instructions [Hardware event]
Signed-off-by: Mihai Sain <mihai.sain@microchip.com>
---
arch/arm/boot/dts/microchip/sama7d65.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/microchip/sama7d65.dtsi b/arch/arm/boot/dts/microchip/sama7d65.dtsi
index e21556f46384..ed1ec952531c 100644
--- a/arch/arm/boot/dts/microchip/sama7d65.dtsi
+++ b/arch/arm/boot/dts/microchip/sama7d65.dtsi
@@ -45,6 +45,11 @@ L2: l2-cache {
};
};
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
clocks {
main_xtal: clock-mainxtal {
compatible = "fixed-clock";
--
2.53.0
^ permalink raw reply related
* [PATCH v2 0/1] Add Cortex-A7 PMU node for SAMA7D65 MPU
From: Mihai Sain @ 2026-03-24 7:09 UTC (permalink / raw)
To: nicolas.ferre, alexandre.belloni, claudiu.beznea, robh, krzk+dt,
conor+dt
Cc: linux-arm-kernel, devicetree, linux-kernel, Mihai Sain
This patch adds the Performance Monitoring Unit (PMU) node for SAMA7D65 MPU.
Changelog:
v1 -> v2:
- Remove the interrupt-affinity property
Mihai Sain (1):
ARM: dts: microchip: sama7d65: add Cortex-A7 PMU node
arch/arm/boot/dts/microchip/sama7d65.dtsi | 5 +++++
1 file changed, 5 insertions(+)
base-commit: c369299895a591d96745d6492d4888259b004a9e
--
2.53.0
^ permalink raw reply
* Re: [PATCH v2] tty: atmel_serial: update outdated reference to atmel_tasklet_func()
From: Richard GENOUD @ 2026-03-24 7:08 UTC (permalink / raw)
To: Kexin Sun, gregkh, jirislaby
Cc: nicolas.ferre, alexandre.belloni, claudiu.beznea, linux-kernel,
linux-serial, linux-arm-kernel, julia.lawall, xutong.ma, yunbolyu,
ratnadiraw
In-Reply-To: <20260324024857.3244-1-kexinsun@smail.nju.edu.cn>
Le 24/03/2026 à 03:48, Kexin Sun a écrit :
> The modem-status comparison that used irq_status_prev was
> moved from atmel_tasklet_func() into atmel_handle_status() in
> commit d033e82db9a5 ("tty/serial: at91: handle IRQ status
> more safely"). Update the comment accordingly.
Double space here, but I don't think it's necessary to send another
iteration for that.
>
> Assisted-by: unnamed:deepseek-v3.2 coccinelle
> Signed-off-by: Kexin Sun <kexinsun@smail.nju.edu.cn>
Acked-by Richard Genoud <richard.genoud@bootlin.com>
> ---
> drivers/tty/serial/atmel_serial.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index 08dd8f887956..5d8c1cfc1c60 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -1927,7 +1927,7 @@ static int atmel_startup(struct uart_port *port)
> atmel_uart_writel(port, ATMEL_US_FMR, fmr);
> }
>
> - /* Save current CSR for comparison in atmel_tasklet_func() */
> + /* Save current CSR for comparison in atmel_handle_status() */
> atmel_port->irq_status_prev = atmel_uart_readl(port, ATMEL_US_CSR);
>
> /*
Thanks!
^ permalink raw reply
* Re: [PATCH v2 2/4] iio: adc: meson-saradc: add support for Meson S4
From: Krzysztof Kozlowski @ 2026-03-24 7:07 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Nick Xie, neil.armstrong, khilman, martin.blumenstingl, jbrunet,
dlechner, andy, krzk+dt, robh, conor+dt, linux-iio, linux-amlogic,
linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260323200501.6c116226@jic23-huawei>
On 23/03/2026 21:05, Jonathan Cameron wrote:
> On Mon, 23 Mar 2026 08:54:21 +0100
> Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
>> On Mon, Mar 23, 2026 at 09:34:06AM +0800, Nick Xie wrote:
>>> Add support for the SARADC found on the Amlogic Meson S4 SoC.
>>> According to the documentation and current testing, it is fully
>>> compatible with the G12A parameter set, so we reuse
>>> `meson_sar_adc_g12a_data` for this new compatible string.
>>>
>>> Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>>> Signed-off-by: Nick Xie <nick@khadas.com>
>>> ---
>>> drivers/iio/adc/meson_saradc.c | 8 ++++++++
>>> 1 file changed, 8 insertions(+)
>>>
>>> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
>>> index 47cd350498a0d..3ac48b7842c4f 100644
>>> --- a/drivers/iio/adc/meson_saradc.c
>>> +++ b/drivers/iio/adc/meson_saradc.c
>>> @@ -1313,6 +1313,11 @@ static const struct meson_sar_adc_data meson_sar_adc_g12a_data = {
>>> .name = "meson-g12a-saradc",
>>> };
>>>
>>> +static const struct meson_sar_adc_data meson_sar_adc_s4_data = {
>>> + .param = &meson_sar_adc_g12a_param,
>>> + .name = "meson-s4-saradc",
>>> +};
>>> +
>>> static const struct of_device_id meson_sar_adc_of_match[] = {
>>> {
>>> .compatible = "amlogic,meson8-saradc",
>>> @@ -1341,6 +1346,9 @@ static const struct of_device_id meson_sar_adc_of_match[] = {
>>> }, {
>>> .compatible = "amlogic,meson-g12a-saradc",
>>> .data = &meson_sar_adc_g12a_data,
>>> + }, {
>>> + .compatible = "amlogic,meson-s4-saradc",
>>
>> The point of compatible devices is to not add such entries. Drop.
> It's used for naming in the userspace ABI which is supposed to reflect the part number.
Indeed, I saw this pattern in more places. Does userspace need it? There
is no "compatible" entry shown?
If there is no, then probably this could be automated by taking the name
from compatible after ',', but that would be out of scope for this set,
so here it is fine.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH 6.12.y] media: nxp: imx8-isi: Fix streaming cleanup on release
From: Robert Garcia @ 2026-03-24 7:05 UTC (permalink / raw)
To: stable, Richard Leitner
Cc: Hans Verkuil, Laurent Pinchart, Mauro Carvalho Chehab, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, linux-media,
Robert Garcia, imx, linux-arm-kernel, linux-kernel
From: Richard Leitner <richard.leitner@linux.dev>
[ Upstream commit 47773031a148ad7973b809cc7723cba77eda2b42 ]
The current implementation unconditionally calls
mxc_isi_video_cleanup_streaming() in mxc_isi_video_release(). This can
lead to situations where any release call (like from a simple
"v4l2-ctl -l") may release a currently streaming queue when called on
such a device.
This is reproducible on an i.MX8MP board by streaming from an ISI
capture device using gstreamer:
gst-launch-1.0 -v v4l2src device=/dev/videoX ! \
video/x-raw,format=GRAY8,width=1280,height=800,framerate=1/120 ! \
fakesink
While this stream is running, querying the caps of the same device
provokes the error state:
v4l2-ctl -l -d /dev/videoX
This results in the following trace:
[ 155.452152] ------------[ cut here ]------------
[ 155.452163] WARNING: CPU: 0 PID: 1708 at drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c:713 mxc_isi_pipe_irq_handler+0x19c/0x1b0 [imx8_isi]
[ 157.004248] Modules linked in: cfg80211 rpmsg_ctrl rpmsg_char rpmsg_tty virtio_rpmsg_bus rpmsg_ns rpmsg_core rfkill nft_ct nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables mcp251x6
[ 157.053499] CPU: 0 UID: 0 PID: 1708 Comm: python3 Not tainted 6.15.4-00114-g1f61ca5cad76 #1 PREEMPT
[ 157.064369] Hardware name: imx8mp_board_01 (DT)
[ 157.068205] pstate: 400000c5 (nZcv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 157.075169] pc : mxc_isi_pipe_irq_handler+0x19c/0x1b0 [imx8_isi]
[ 157.081195] lr : mxc_isi_pipe_irq_handler+0x38/0x1b0 [imx8_isi]
[ 157.087126] sp : ffff800080003ee0
[ 157.090438] x29: ffff800080003ee0 x28: ffff0000c3688000 x27: 0000000000000000
[ 157.097580] x26: 0000000000000000 x25: ffff0000c1e7ac00 x24: ffff800081b5ad50
[ 157.104723] x23: 00000000000000d1 x22: 0000000000000000 x21: ffff0000c25e4000
[ 157.111866] x20: 0000000060000200 x19: ffff80007a0608d0 x18: 0000000000000000
[ 157.119008] x17: ffff80006a4e3000 x16: ffff800080000000 x15: 0000000000000000
[ 157.126146] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
[ 157.133287] x11: 0000000000000040 x10: ffff0000c01445f0 x9 : ffff80007a053a38
[ 157.140425] x8 : ffff0000c04004b8 x7 : 0000000000000000 x6 : 0000000000000000
[ 157.147567] x5 : ffff0000c0400490 x4 : ffff80006a4e3000 x3 : ffff0000c25e4000
[ 157.154706] x2 : 0000000000000000 x1 : ffff8000825c0014 x0 : 0000000060000200
[ 157.161850] Call trace:
[ 157.164296] mxc_isi_pipe_irq_handler+0x19c/0x1b0 [imx8_isi] (P)
[ 157.170319] __handle_irq_event_percpu+0x58/0x218
[ 157.175029] handle_irq_event+0x54/0xb8
[ 157.178867] handle_fasteoi_irq+0xac/0x248
[ 157.182968] handle_irq_desc+0x48/0x68
[ 157.186723] generic_handle_domain_irq+0x24/0x38
[ 157.191346] gic_handle_irq+0x54/0x120
[ 157.195098] call_on_irq_stack+0x24/0x30
[ 157.199027] do_interrupt_handler+0x88/0x98
[ 157.203212] el0_interrupt+0x44/0xc0
[ 157.206792] __el0_irq_handler_common+0x18/0x28
[ 157.211328] el0t_64_irq_handler+0x10/0x20
[ 157.215429] el0t_64_irq+0x198/0x1a0
[ 157.219009] ---[ end trace 0000000000000000 ]---
Address this issue by moving the streaming preparation and cleanup to
the vb2 .prepare_streaming() and .unprepare_streaming() operations. This
also simplifies the driver by allowing direct usage of the
vb2_ioctl_streamon() and vb2_ioctl_streamoff() helpers, and removal of
the manual cleanup from mxc_isi_video_release().
Link: https://lore.kernel.org/r/20250813212451.22140-2-laurent.pinchart@ideasonboard.com
Signed-off-by: Richard Leitner <richard.leitner@linux.dev>
Co-developed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Richard Leitner <richard.leitner@linux.dev> # i.MX8MP
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
[ Minor context change fixed. ]
Signed-off-by: Robert Garcia <rob_garcia@163.com>
---
.../platform/nxp/imx8-isi/imx8-isi-video.c | 156 +++++++-----------
1 file changed, 58 insertions(+), 98 deletions(-)
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
index a71eb30323c8..4e6c3540de35 100644
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
@@ -937,6 +937,49 @@ static void mxc_isi_video_init_channel(struct mxc_isi_video *video)
mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix);
}
+static int mxc_isi_vb2_prepare_streaming(struct vb2_queue *q)
+{
+ struct mxc_isi_video *video = vb2_get_drv_priv(q);
+ struct media_device *mdev = &video->pipe->isi->media_dev;
+ struct media_pipeline *pipe;
+ int ret;
+
+ /* Get a pipeline for the video node and start it. */
+ scoped_guard(mutex, &mdev->graph_mutex) {
+ ret = mxc_isi_pipe_acquire(video->pipe,
+ &mxc_isi_video_frame_write_done);
+ if (ret)
+ return ret;
+
+ pipe = media_entity_pipeline(&video->vdev.entity)
+ ? : &video->pipe->pipe;
+
+ ret = __video_device_pipeline_start(&video->vdev, pipe);
+ if (ret)
+ goto err_release;
+ }
+
+ /* Verify that the video format matches the output of the subdev. */
+ ret = mxc_isi_video_validate_format(video);
+ if (ret)
+ goto err_stop;
+
+ /* Allocate buffers for discard operation. */
+ ret = mxc_isi_video_alloc_discard_buffers(video);
+ if (ret)
+ goto err_stop;
+
+ video->is_streaming = true;
+
+ return 0;
+
+err_stop:
+ video_device_pipeline_stop(&video->vdev);
+err_release:
+ mxc_isi_pipe_release(video->pipe);
+ return ret;
+}
+
static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct mxc_isi_video *video = vb2_get_drv_priv(q);
@@ -985,6 +1028,17 @@ static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q)
mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR);
}
+static void mxc_isi_vb2_unprepare_streaming(struct vb2_queue *q)
+{
+ struct mxc_isi_video *video = vb2_get_drv_priv(q);
+
+ mxc_isi_video_free_discard_buffers(video);
+ video_device_pipeline_stop(&video->vdev);
+ mxc_isi_pipe_release(video->pipe);
+
+ video->is_streaming = false;
+}
+
static const struct vb2_ops mxc_isi_vb2_qops = {
.queue_setup = mxc_isi_vb2_queue_setup,
.buf_init = mxc_isi_vb2_buffer_init,
@@ -992,8 +1046,10 @@ static const struct vb2_ops mxc_isi_vb2_qops = {
.buf_queue = mxc_isi_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
+ .prepare_streaming = mxc_isi_vb2_prepare_streaming,
.start_streaming = mxc_isi_vb2_start_streaming,
.stop_streaming = mxc_isi_vb2_stop_streaming,
+ .unprepare_streaming = mxc_isi_vb2_unprepare_streaming,
};
/* -----------------------------------------------------------------------------
@@ -1147,97 +1203,6 @@ static int mxc_isi_video_s_fmt(struct file *file, void *priv,
return 0;
}
-static int mxc_isi_video_streamon(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct mxc_isi_video *video = video_drvdata(file);
- struct media_device *mdev = &video->pipe->isi->media_dev;
- struct media_pipeline *pipe;
- int ret;
-
- if (vb2_queue_is_busy(&video->vb2_q, file))
- return -EBUSY;
-
- /*
- * Get a pipeline for the video node and start it. This must be done
- * here and not in the queue .start_streaming() handler, so that
- * pipeline start errors can be reported from VIDIOC_STREAMON and not
- * delayed until subsequent VIDIOC_QBUF calls.
- */
- mutex_lock(&mdev->graph_mutex);
-
- ret = mxc_isi_pipe_acquire(video->pipe, &mxc_isi_video_frame_write_done);
- if (ret) {
- mutex_unlock(&mdev->graph_mutex);
- return ret;
- }
-
- pipe = media_entity_pipeline(&video->vdev.entity) ? : &video->pipe->pipe;
-
- ret = __video_device_pipeline_start(&video->vdev, pipe);
- if (ret) {
- mutex_unlock(&mdev->graph_mutex);
- goto err_release;
- }
-
- mutex_unlock(&mdev->graph_mutex);
-
- /* Verify that the video format matches the output of the subdev. */
- ret = mxc_isi_video_validate_format(video);
- if (ret)
- goto err_stop;
-
- /* Allocate buffers for discard operation. */
- ret = mxc_isi_video_alloc_discard_buffers(video);
- if (ret)
- goto err_stop;
-
- ret = vb2_streamon(&video->vb2_q, type);
- if (ret)
- goto err_free;
-
- video->is_streaming = true;
-
- return 0;
-
-err_free:
- mxc_isi_video_free_discard_buffers(video);
-err_stop:
- video_device_pipeline_stop(&video->vdev);
-err_release:
- mxc_isi_pipe_release(video->pipe);
- return ret;
-}
-
-static void mxc_isi_video_cleanup_streaming(struct mxc_isi_video *video)
-{
- lockdep_assert_held(&video->lock);
-
- if (!video->is_streaming)
- return;
-
- mxc_isi_video_free_discard_buffers(video);
- video_device_pipeline_stop(&video->vdev);
- mxc_isi_pipe_release(video->pipe);
-
- video->is_streaming = false;
-}
-
-static int mxc_isi_video_streamoff(struct file *file, void *priv,
- enum v4l2_buf_type type)
-{
- struct mxc_isi_video *video = video_drvdata(file);
- int ret;
-
- ret = vb2_ioctl_streamoff(file, priv, type);
- if (ret)
- return ret;
-
- mxc_isi_video_cleanup_streaming(video);
-
- return 0;
-}
-
static int mxc_isi_video_enum_framesizes(struct file *file, void *priv,
struct v4l2_frmsizeenum *fsize)
{
@@ -1293,9 +1258,8 @@ static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = {
.vidioc_expbuf = vb2_ioctl_expbuf,
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
-
- .vidioc_streamon = mxc_isi_video_streamon,
- .vidioc_streamoff = mxc_isi_video_streamoff,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_enum_framesizes = mxc_isi_video_enum_framesizes,
@@ -1334,10 +1298,6 @@ static int mxc_isi_video_release(struct file *file)
if (ret)
dev_err(video->pipe->isi->dev, "%s fail\n", __func__);
- mutex_lock(&video->lock);
- mxc_isi_video_cleanup_streaming(video);
- mutex_unlock(&video->lock);
-
pm_runtime_put(video->pipe->isi->dev);
return ret;
}
--
2.34.1
^ permalink raw reply related
* [PATCH 17/17] raid6_kunit: randomize buffer alignment
From: Christoph Hellwig @ 2026-03-24 6:40 UTC (permalink / raw)
To: Andrew Morton
Cc: Catalin Marinas, Will Deacon, Ard Biesheuvel, Huacai Chen,
WANG Xuerui, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy (CS GROUP), Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Herbert Xu, Dan Williams,
Chris Mason, David Sterba, Arnd Bergmann, Song Liu, Yu Kuai,
Li Nan, linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
linux-riscv, linux-s390, linux-crypto, linux-btrfs, linux-arch,
linux-raid
In-Reply-To: <20260324064115.3217136-1-hch@lst.de>
Add code to add random alignment to the buffers to test the case where
they are not page aligned, and to move the buffers to the end of the
allocation so that they are next to the vmalloc guard page.
This does not include the recovery buffers as the recovery requires
page alignment.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
lib/raid/raid6/tests/raid6_kunit.c | 41 +++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 6 deletions(-)
diff --git a/lib/raid/raid6/tests/raid6_kunit.c b/lib/raid/raid6/tests/raid6_kunit.c
index a0a473643e91..d2fd4a9b74d4 100644
--- a/lib/raid/raid6/tests/raid6_kunit.c
+++ b/lib/raid/raid6/tests/raid6_kunit.c
@@ -20,6 +20,7 @@ MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static struct rnd_state rng;
static void *test_buffers[RAID6_KUNIT_MAX_BUFFERS];
+static void *aligned_buffers[RAID6_KUNIT_MAX_BUFFERS];
static void *test_recov_buffers[RAID6_KUNIT_MAX_FAILURES];
static size_t test_buflen;
@@ -43,6 +44,14 @@ static unsigned int random_length(unsigned int max_length)
return (rand32() % (max_length + 1)) & ~511;
}
+/* Generate a random alignment that is a multiple of 64. */
+static unsigned int random_alignment(unsigned int max_alignment)
+{
+ if (max_alignment == 0)
+ return 0;
+ return (rand32() % (max_alignment + 1)) & ~63;
+}
+
static void makedata(int start, int stop)
{
int i;
@@ -73,7 +82,7 @@ static void test_recover_one(struct kunit *test, unsigned int nr_buffers,
for (i = 0; i < RAID6_KUNIT_MAX_FAILURES; i++)
memset(test_recov_buffers[i], 0xf0, test_buflen);
- memcpy(dataptrs, test_buffers, sizeof(dataptrs));
+ memcpy(dataptrs, aligned_buffers, sizeof(dataptrs));
dataptrs[faila] = test_recov_buffers[0];
dataptrs[failb] = test_recov_buffers[1];
@@ -95,13 +104,13 @@ static void test_recover_one(struct kunit *test, unsigned int nr_buffers,
ta->recov->data2(nr_buffers, len, faila, failb, dataptrs);
}
- KUNIT_EXPECT_MEMEQ_MSG(test, test_buffers[faila], test_recov_buffers[0],
+ KUNIT_EXPECT_MEMEQ_MSG(test, aligned_buffers[faila], dataptrs[faila],
len,
"faila miscompared: %3d[%c] buffers %u len %u (failb=%3d[%c])\n",
faila, member_type(nr_buffers, faila),
nr_buffers, len,
failb, member_type(nr_buffers, failb));
- KUNIT_EXPECT_MEMEQ_MSG(test, test_buffers[failb], test_recov_buffers[1],
+ KUNIT_EXPECT_MEMEQ_MSG(test, aligned_buffers[failb], dataptrs[failb],
len,
"failb miscompared: %3d[%c] buffers %u len %u (faila=%3d[%c])\n",
failb, member_type(nr_buffers, failb),
@@ -140,9 +149,9 @@ static void test_rmw_one(struct kunit *test, unsigned int nr_buffers,
{
const struct test_args *ta = test->param_value;
- ta->gen->xor_syndrome(nr_buffers, p1, p2, len, test_buffers);
+ ta->gen->xor_syndrome(nr_buffers, p1, p2, len, aligned_buffers);
makedata(p1, p2);
- ta->gen->xor_syndrome(nr_buffers, p1, p2, len, test_buffers);
+ ta->gen->xor_syndrome(nr_buffers, p1, p2, len, aligned_buffers);
test_recover(test, nr_buffers, len);
}
@@ -168,13 +177,33 @@ static void raid6_test_one(struct kunit *test)
unsigned int nr_buffers =
(rand32() % (RAID6_KUNIT_MAX_BUFFERS - 2)) + 3;
unsigned int len = random_length(RAID6_KUNIT_MAX_BYTES);
+ unsigned int max_alignment;
+ int i;
/* Nuke syndromes */
memset(test_buffers[nr_buffers - 2], 0xee, test_buflen);
memset(test_buffers[nr_buffers - 1], 0xee, test_buflen);
+ /*
+ * If we're not using the entire buffer size, inject randomize alignment
+ * into the buffer.
+ */
+ max_alignment = RAID6_KUNIT_MAX_BYTES - len;
+ if (rand32() % 2 == 0) {
+ /* Use random alignments mod 64 */
+ for (i = 0; i < nr_buffers; i++)
+ aligned_buffers[i] = test_buffers[i] +
+ random_alignment(max_alignment);
+ } else {
+ /* Go up to the guard page, to catch buffer overreads */
+ unsigned int align = test_buflen - len;
+
+ for (i = 0; i < nr_buffers; i++)
+ aligned_buffers[i] = test_buffers[i] + align;
+ }
+
/* Generate assumed good syndrome */
- ta->gen->gen_syndrome(nr_buffers, len, test_buffers);
+ ta->gen->gen_syndrome(nr_buffers, len, aligned_buffers);
test_recover(test, nr_buffers, len);
--
2.47.3
^ permalink raw reply related
* [PATCH 16/17] raid6_kunit: randomize parameters and increase limits
From: Christoph Hellwig @ 2026-03-24 6:40 UTC (permalink / raw)
To: Andrew Morton
Cc: Catalin Marinas, Will Deacon, Ard Biesheuvel, Huacai Chen,
WANG Xuerui, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy (CS GROUP), Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Herbert Xu, Dan Williams,
Chris Mason, David Sterba, Arnd Bergmann, Song Liu, Yu Kuai,
Li Nan, linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
linux-riscv, linux-s390, linux-crypto, linux-btrfs, linux-arch,
linux-raid
In-Reply-To: <20260324064115.3217136-1-hch@lst.de>
The current test has double-quadratic behavior in the selection for
the updated ("XORed") disks, and in the selection of updated pointers,
which makes scaling it to more tests difficult. At the same time it
only ever tests with the maximum number of disks, which leaves a
coverage hole for smaller ones.
Fix this by randomizing the total number, failed disks and regions
to update, and increasing the upper number of tests disks.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
lib/raid/raid6/tests/raid6_kunit.c | 188 +++++++++++++++++++----------
1 file changed, 124 insertions(+), 64 deletions(-)
diff --git a/lib/raid/raid6/tests/raid6_kunit.c b/lib/raid/raid6/tests/raid6_kunit.c
index ba6cfabc67a4..a0a473643e91 100644
--- a/lib/raid/raid6/tests/raid6_kunit.c
+++ b/lib/raid/raid6/tests/raid6_kunit.c
@@ -13,13 +13,15 @@
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
#define RAID6_KUNIT_SEED 42
+#define RAID6_KUNIT_NUM_TEST_ITERS 10
+#define RAID6_KUNIT_MAX_BUFFERS 64 /* Including P and Q */
#define RAID6_KUNIT_MAX_FAILURES 2
-
-#define NDISKS 16 /* Including P and Q */
+#define RAID6_KUNIT_MAX_BYTES PAGE_SIZE
static struct rnd_state rng;
-static void *test_buffers[NDISKS];
+static void *test_buffers[RAID6_KUNIT_MAX_BUFFERS];
static void *test_recov_buffers[RAID6_KUNIT_MAX_FAILURES];
+static size_t test_buflen;
struct test_args {
unsigned int recov_idx;
@@ -30,105 +32,162 @@ struct test_args {
static struct test_args args;
+static u32 rand32(void)
+{
+ return prandom_u32_state(&rng);
+}
+
+/* Generate a random length that is a multiple of 512. */
+static unsigned int random_length(unsigned int max_length)
+{
+ return (rand32() % (max_length + 1)) & ~511;
+}
+
static void makedata(int start, int stop)
{
int i;
for (i = start; i <= stop; i++)
- prandom_bytes_state(&rng, test_buffers[i], PAGE_SIZE);
+ prandom_bytes_state(&rng, test_buffers[i], test_buflen);
}
-static char member_type(int d)
+static char member_type(unsigned int nr_buffers, int d)
{
- switch (d) {
- case NDISKS-2:
+ if (d == nr_buffers - 2)
return 'P';
- case NDISKS-1:
+ if (d == nr_buffers - 1)
return 'Q';
- default:
- return 'D';
- }
+ return 'D';
}
-static void test_recover(struct kunit *test, int faila, int failb)
+static void test_recover_one(struct kunit *test, unsigned int nr_buffers,
+ unsigned int len, int faila, int failb)
{
const struct test_args *ta = test->param_value;
- void *dataptrs[NDISKS];
+ void *dataptrs[RAID6_KUNIT_MAX_BUFFERS];
int i;
+ if (faila > failb)
+ swap(faila, failb);
+
for (i = 0; i < RAID6_KUNIT_MAX_FAILURES; i++)
- memset(test_recov_buffers[i], 0xf0, PAGE_SIZE);
+ memset(test_recov_buffers[i], 0xf0, test_buflen);
memcpy(dataptrs, test_buffers, sizeof(dataptrs));
dataptrs[faila] = test_recov_buffers[0];
dataptrs[failb] = test_recov_buffers[1];
- if (faila > failb)
- swap(faila, failb);
-
- if (failb == NDISKS - 1) {
+ if (failb == nr_buffers - 1) {
/*
* We don't implement the data+Q failure scenario, since it
* is equivalent to a RAID-5 failure (XOR, then recompute Q).
*/
- if (faila != NDISKS - 2)
+ if (WARN_ON_ONCE(faila != nr_buffers - 2))
return;
/* P+Q failure. Just rebuild the syndrome. */
- ta->gen->gen_syndrome(NDISKS, PAGE_SIZE, dataptrs);
- } else if (failb == NDISKS - 2) {
+ ta->gen->gen_syndrome(nr_buffers, len, dataptrs);
+ } else if (failb == nr_buffers - 2) {
/* data+P failure. */
- ta->recov->datap(NDISKS, PAGE_SIZE, faila, dataptrs);
+ ta->recov->datap(nr_buffers, len, faila, dataptrs);
} else {
/* data+data failure. */
- ta->recov->data2(NDISKS, PAGE_SIZE, faila, failb, dataptrs);
+ ta->recov->data2(nr_buffers, len, faila, failb, dataptrs);
}
KUNIT_EXPECT_MEMEQ_MSG(test, test_buffers[faila], test_recov_buffers[0],
- PAGE_SIZE,
- "faila miscompared: %3d[%c] (failb=%3d[%c])\n",
- faila, member_type(faila),
- failb, member_type(failb));
+ len,
+ "faila miscompared: %3d[%c] buffers %u len %u (failb=%3d[%c])\n",
+ faila, member_type(nr_buffers, faila),
+ nr_buffers, len,
+ failb, member_type(nr_buffers, failb));
KUNIT_EXPECT_MEMEQ_MSG(test, test_buffers[failb], test_recov_buffers[1],
- PAGE_SIZE,
- "failb miscompared: %3d[%c] (faila=%3d[%c])\n",
- failb, member_type(failb),
- faila, member_type(faila));
+ len,
+ "failb miscompared: %3d[%c] buffers %u len %u (faila=%3d[%c])\n",
+ failb, member_type(nr_buffers, failb),
+ nr_buffers, len,
+ faila, member_type(nr_buffers, faila));
}
-static void raid6_test(struct kunit *test)
+static void test_recover(struct kunit *test, unsigned int nr_buffers,
+ unsigned int len)
+{
+ int iterations, i;
+
+ /* Test P+Q recovery */
+ test_recover_one(test, nr_buffers, len, nr_buffers - 2, nr_buffers - 1);
+
+ /* Test data+P recovery */
+ for (i = 0; i < nr_buffers - 2; i++)
+ test_recover_one(test, nr_buffers, len, i, nr_buffers - 2);
+
+ /* Test data+data recovery using random sampling */
+ iterations = nr_buffers * 2; /* should provide good enough coverage */
+ for (i = 0; i < iterations; i++) {
+ int faila = rand32() % (nr_buffers - 2), failb;
+
+ do {
+ failb = rand32() % (nr_buffers - 2);
+ } while (failb == faila);
+
+ test_recover_one(test, nr_buffers, len, faila, failb);
+ }
+}
+
+/* Simulate rmw run */
+static void test_rmw_one(struct kunit *test, unsigned int nr_buffers,
+ unsigned int len, int p1, int p2)
+{
+ const struct test_args *ta = test->param_value;
+
+ ta->gen->xor_syndrome(nr_buffers, p1, p2, len, test_buffers);
+ makedata(p1, p2);
+ ta->gen->xor_syndrome(nr_buffers, p1, p2, len, test_buffers);
+ test_recover(test, nr_buffers, len);
+}
+
+static void test_rmw(struct kunit *test, unsigned int nr_buffers,
+ unsigned int len)
+{
+ int iterations = nr_buffers / 2, i;
+
+ for (i = 0; i < iterations; i++) {
+ int p1 = rand32() % (nr_buffers - 2);
+ int p2 = rand32() % (nr_buffers - 2);
+
+ if (p2 < p1)
+ swap(p1, p2);
+ test_rmw_one(test, nr_buffers, len, p1, p2);
+ }
+}
+
+static void raid6_test_one(struct kunit *test)
{
const struct test_args *ta = test->param_value;
- int i, j, p1, p2;
+ /* including P/Q we need at least three buffers */
+ unsigned int nr_buffers =
+ (rand32() % (RAID6_KUNIT_MAX_BUFFERS - 2)) + 3;
+ unsigned int len = random_length(RAID6_KUNIT_MAX_BYTES);
/* Nuke syndromes */
- memset(test_buffers[NDISKS - 2], 0xee, PAGE_SIZE);
- memset(test_buffers[NDISKS - 1], 0xee, PAGE_SIZE);
+ memset(test_buffers[nr_buffers - 2], 0xee, test_buflen);
+ memset(test_buffers[nr_buffers - 1], 0xee, test_buflen);
/* Generate assumed good syndrome */
- ta->gen->gen_syndrome(NDISKS, PAGE_SIZE, test_buffers);
-
- for (i = 0; i < NDISKS - 1; i++)
- for (j = i + 1; j < NDISKS; j++)
- test_recover(test, i, j);
-
- if (!ta->gen->xor_syndrome)
- return;
-
- for (p1 = 0; p1 < NDISKS - 2; p1++) {
- for (p2 = p1; p2 < NDISKS - 2; p2++) {
- /* Simulate rmw run */
- ta->gen->xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
- test_buffers);
- makedata(p1, p2);
- ta->gen->xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
- test_buffers);
-
- for (i = 0; i < NDISKS - 1; i++)
- for (j = i + 1; j < NDISKS; j++)
- test_recover(test, i, j);
- }
- }
+ ta->gen->gen_syndrome(nr_buffers, len, test_buffers);
+
+ test_recover(test, nr_buffers, len);
+
+ if (ta->gen->xor_syndrome)
+ test_rmw(test, nr_buffers, len);
+}
+
+static void raid6_test(struct kunit *test)
+{
+ int i;
+
+ for (i = 0; i < RAID6_KUNIT_NUM_TEST_ITERS; i++)
+ raid6_test_one(test);
}
static const void *raid6_gen_params(struct kunit *test, const void *prev,
@@ -172,23 +231,24 @@ static int raid6_suite_init(struct kunit_suite *suite)
* so that it is immediately followed by a guard page. This allows
* buffer overreads to be detected, even in assembly code.
*/
+ test_buflen = round_up(RAID6_KUNIT_MAX_BYTES, PAGE_SIZE);
for (i = 0; i < RAID6_KUNIT_MAX_FAILURES; i++) {
- test_recov_buffers[i] = vmalloc(PAGE_SIZE);
+ test_recov_buffers[i] = vmalloc(test_buflen);
if (!test_recov_buffers[i])
goto out_free_recov_buffers;
}
- for (i = 0; i < NDISKS; i++) {
- test_buffers[i] = vmalloc(PAGE_SIZE);
+ for (i = 0; i < RAID6_KUNIT_MAX_BUFFERS; i++) {
+ test_buffers[i] = vmalloc(test_buflen);
if (!test_buffers[i])
goto out_free_buffers;
}
- makedata(0, NDISKS - 1);
+ makedata(0, RAID6_KUNIT_MAX_BUFFERS - 1);
return 0;
out_free_buffers:
- for (i = 0; i < NDISKS; i++)
+ for (i = 0; i < RAID6_KUNIT_MAX_BUFFERS; i++)
vfree(test_buffers[i]);
out_free_recov_buffers:
for (i = 0; i < RAID6_KUNIT_MAX_FAILURES; i++)
@@ -200,7 +260,7 @@ static void raid6_suite_exit(struct kunit_suite *suite)
{
int i;
- for (i = 0; i < NDISKS; i++)
+ for (i = 0; i < RAID6_KUNIT_MAX_BUFFERS; i++)
vfree(test_buffers[i]);
for (i = 0; i < RAID6_KUNIT_MAX_FAILURES; i++)
vfree(test_recov_buffers[i]);
--
2.47.3
^ permalink raw reply related
* Re: [PATCH v4 1/2] dt-bindings: PCI: cix,sky1-pcie-host: Add power-domains
From: Peter Chen @ 2026-03-24 6:44 UTC (permalink / raw)
To: mani, bhelgaas
Cc: Gary Yang, lpieralisi, kwilczynski, robh, krzk+dt, conor+dt,
linux-pci, devicetree, linux-kernel, linux-arm-kernel,
cix-kernel-upstream
In-Reply-To: <abfEO6iW3NcnMyNx@nchen-desktop>
On 26-03-16 16:50:03, Peter Chen wrote:
> On 26-03-14 10:26:11, Krzysztof Kozlowski wrote:
> > EXTERNAL EMAIL
> >
> > On Fri, Mar 13, 2026 at 07:49:13PM +0800, Gary Yang wrote:
> > > The Sky1 PCIe controller resides in a dedicated power domain managed
> > > via SCMI. Add the power-domains property to the binding to allow
> > > describing this dependency.
> > >
> > > Signed-off-by: Gary Yang <gary.yang@cixtech.com>
> > > ---
> > > Documentation/devicetree/bindings/pci/cix,sky1-pcie-host.yaml | 3 +++
> > > 1 file changed, 3 insertions(+)
> >
> > Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> >
> Thank Krzysztof for kindly review it.
>
> Mani, I assume this patch will go to PCIe tree, right?
>
Hi Bjorn,
Will this patch go to PCIe tree or I queue it at CIX SoC tree since
there is no driver change.
--
Best regards,
Peter
^ permalink raw reply
* [PATCH 15/17] raid6_kunit: cleanup dataptr handling
From: Christoph Hellwig @ 2026-03-24 6:40 UTC (permalink / raw)
To: Andrew Morton
Cc: Catalin Marinas, Will Deacon, Ard Biesheuvel, Huacai Chen,
WANG Xuerui, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy (CS GROUP), Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Heiko Carstens,
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Herbert Xu, Dan Williams,
Chris Mason, David Sterba, Arnd Bergmann, Song Liu, Yu Kuai,
Li Nan, linux-kernel, linux-arm-kernel, loongarch, linuxppc-dev,
linux-riscv, linux-s390, linux-crypto, linux-btrfs, linux-arch,
linux-raid
In-Reply-To: <20260324064115.3217136-1-hch@lst.de>
Move the global dataptr array into test_recover() as all sites that fill
data or parity can use test_buffers directly, and this localized the
override for the failed slots to the recovery testing routine.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
lib/raid/raid6/tests/raid6_kunit.c | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/lib/raid/raid6/tests/raid6_kunit.c b/lib/raid/raid6/tests/raid6_kunit.c
index 1793b952a595..ba6cfabc67a4 100644
--- a/lib/raid/raid6/tests/raid6_kunit.c
+++ b/lib/raid/raid6/tests/raid6_kunit.c
@@ -18,7 +18,6 @@ MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
#define NDISKS 16 /* Including P and Q */
static struct rnd_state rng;
-static void *dataptrs[NDISKS];
static void *test_buffers[NDISKS];
static void *test_recov_buffers[RAID6_KUNIT_MAX_FAILURES];
@@ -35,10 +34,8 @@ static void makedata(int start, int stop)
{
int i;
- for (i = start; i <= stop; i++) {
+ for (i = start; i <= stop; i++)
prandom_bytes_state(&rng, test_buffers[i], PAGE_SIZE);
- dataptrs[i] = test_buffers[i];
- }
}
static char member_type(int d)
@@ -56,11 +53,13 @@ static char member_type(int d)
static void test_recover(struct kunit *test, int faila, int failb)
{
const struct test_args *ta = test->param_value;
+ void *dataptrs[NDISKS];
int i;
for (i = 0; i < RAID6_KUNIT_MAX_FAILURES; i++)
memset(test_recov_buffers[i], 0xf0, PAGE_SIZE);
+ memcpy(dataptrs, test_buffers, sizeof(dataptrs));
dataptrs[faila] = test_recov_buffers[0];
dataptrs[failb] = test_recov_buffers[1];
@@ -73,7 +72,7 @@ static void test_recover(struct kunit *test, int faila, int failb)
* is equivalent to a RAID-5 failure (XOR, then recompute Q).
*/
if (faila != NDISKS - 2)
- goto skip;
+ return;
/* P+Q failure. Just rebuild the syndrome. */
ta->gen->gen_syndrome(NDISKS, PAGE_SIZE, dataptrs);
@@ -95,10 +94,6 @@ static void test_recover(struct kunit *test, int faila, int failb)
"failb miscompared: %3d[%c] (faila=%3d[%c])\n",
failb, member_type(failb),
faila, member_type(faila));
-
-skip:
- dataptrs[faila] = test_buffers[faila];
- dataptrs[failb] = test_buffers[failb];
}
static void raid6_test(struct kunit *test)
@@ -111,7 +106,7 @@ static void raid6_test(struct kunit *test)
memset(test_buffers[NDISKS - 1], 0xee, PAGE_SIZE);
/* Generate assumed good syndrome */
- ta->gen->gen_syndrome(NDISKS, PAGE_SIZE, (void **)&dataptrs);
+ ta->gen->gen_syndrome(NDISKS, PAGE_SIZE, test_buffers);
for (i = 0; i < NDISKS - 1; i++)
for (j = i + 1; j < NDISKS; j++)
@@ -124,10 +119,10 @@ static void raid6_test(struct kunit *test)
for (p2 = p1; p2 < NDISKS - 2; p2++) {
/* Simulate rmw run */
ta->gen->xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
- (void **)&dataptrs);
+ test_buffers);
makedata(p1, p2);
ta->gen->xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
- (void **)&dataptrs);
+ test_buffers);
for (i = 0; i < NDISKS - 1; i++)
for (j = i + 1; j < NDISKS; j++)
--
2.47.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox