https://bugs.gentoo.org/904657
https://github.com/openzfs/zfs/issues/14555
https://github.com/openzfs/zfs/commit/976bf9b6a61919638d42ed79cd207132785d128a

From 976bf9b6a61919638d42ed79cd207132785d128a Mon Sep 17 00:00:00 2001
From: Shengqi Chen <harry-chen@outlook.com>
Date: Tue, 9 Jan 2024 08:05:24 +0800
Subject: [PATCH] Linux 6.2 compat: add check for kernel_neon_* availability

This patch adds check for `kernel_neon_*` symbols on arm and arm64
platforms to address the following issues:

1. Linux 6.2+ on arm64 has exported them with `EXPORT_SYMBOL_GPL`, so
   license compatibility must be checked before use.
2. On both arm and arm64, the definitions of these symbols are guarded
   by `CONFIG_KERNEL_MODE_NEON`, but their declarations are still
   present. Checking in configuration phase only leads to MODPOST
   errors (undefined references).

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Shengqi Chen <harry-chen@outlook.com>
Closes #15711
Closes #14555
Closes: #15401
--- a/config/kernel-fpu.m4
+++ b/config/kernel-fpu.m4
@@ -79,6 +79,12 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [
 		__kernel_fpu_end();
 	], [], [ZFS_META_LICENSE])
 
+	ZFS_LINUX_TEST_SRC([kernel_neon], [
+		#include <asm/neon.h>
+	], [
+		kernel_neon_begin();
+		kernel_neon_end();
+	], [], [ZFS_META_LICENSE])
 ])
 
 AC_DEFUN([ZFS_AC_KERNEL_FPU], [
@@ -105,9 +111,20 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
 			AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
 			    [kernel exports FPU functions])
 		],[
-			AC_MSG_RESULT(internal)
-			AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1,
-			    [kernel fpu internal])
+			dnl #
+			dnl # ARM neon symbols (only on arm and arm64)
+			dnl # could be GPL-only on arm64 after Linux 6.2
+			dnl #
+			ZFS_LINUX_TEST_RESULT([kernel_neon_license],[
+				AC_MSG_RESULT(kernel_neon_*)
+				AC_DEFINE(HAVE_KERNEL_NEON, 1,
+				    [kernel has kernel_neon_* functions])
+			],[
+				# catch-all
+				AC_MSG_RESULT(internal)
+				AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1,
+				    [kernel fpu internal])
+			])
 		])
 	])
 ])
--- a/include/os/linux/kernel/linux/simd_aarch64.h
+++ b/include/os/linux/kernel/linux/simd_aarch64.h
@@ -71,9 +71,15 @@
 #define	ID_AA64PFR0_EL1		sys_reg(3, 0, 0, 1, 0)
 #define	ID_AA64ISAR0_EL1	sys_reg(3, 0, 0, 6, 0)
 
+#if (defined(HAVE_KERNEL_NEON) && defined(CONFIG_KERNEL_MODE_NEON))
 #define	kfpu_allowed()		1
 #define	kfpu_begin()		kernel_neon_begin()
 #define	kfpu_end()		kernel_neon_end()
+#else
+#define	kfpu_allowed()		0
+#define	kfpu_begin()		do {} while (0)
+#define	kfpu_end()		do {} while (0)
+#endif
 #define	kfpu_init()		(0)
 #define	kfpu_fini()		do {} while (0)
 
--- a/include/os/linux/kernel/linux/simd_arm.h
+++ b/include/os/linux/kernel/linux/simd_arm.h
@@ -53,9 +53,15 @@
 #include <asm/elf.h>
 #include <asm/hwcap.h>
 
+#if (defined(HAVE_KERNEL_NEON) && defined(CONFIG_KERNEL_MODE_NEON))
 #define	kfpu_allowed()		1
 #define	kfpu_begin()		kernel_neon_begin()
 #define	kfpu_end()		kernel_neon_end()
+#else
+#define	kfpu_allowed()		0
+#define	kfpu_begin()		do {} while (0)
+#define	kfpu_end()		do {} while (0)
+#endif
 #define	kfpu_init()		(0)
 #define	kfpu_fini()		do {} while (0)
 

