diff options
Diffstat (limited to 'sys/compat/linuxkpi/common/include')
272 files changed, 19911 insertions, 2386 deletions
diff --git a/sys/compat/linuxkpi/common/include/acpi/acpi.h b/sys/compat/linuxkpi/common/include/acpi/acpi.h index b6579f42774e..9bb435591daa 100644 --- a/sys/compat/linuxkpi/common/include/acpi/acpi.h +++ b/sys/compat/linuxkpi/common/include/acpi/acpi.h @@ -1,8 +1,12 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org> * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,12 +29,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ACPI_ACPI_H_ -#define _ACPI_ACPI_H_ +#ifndef _LINUXKPI_ACPI_ACPI_H_ +#define _LINUXKPI_ACPI_ACPI_H_ + +/* + * LINUXKPI_WANT_LINUX_ACPI is a temporary workaround to allow drm-kmod + * to update all needed branches without breaking builds. + * Once that happened and checks are implemented based on __FreeBSD_version + * we will remove these conditions again. + */ /* * FreeBSD import of ACPICA has a typedef for BOOLEAN which conflicts with @@ -48,8 +57,8 @@ typedef int64_t INT64; #include <contrib/dev/acpica/include/acpi.h> #undef BOOLEAN +typedef ACPI_IO_ADDRESS acpi_io_address; typedef ACPI_HANDLE acpi_handle; -typedef ACPI_OBJECT acpi_object; typedef ACPI_OBJECT_HANDLER acpi_object_handler; typedef ACPI_OBJECT_TYPE acpi_object_type; typedef ACPI_STATUS acpi_status; @@ -57,12 +66,62 @@ typedef ACPI_STRING acpi_string; typedef ACPI_SIZE acpi_size; typedef ACPI_WALK_CALLBACK acpi_walk_callback; +union linuxkpi_acpi_object { + acpi_object_type type; + struct { + acpi_object_type type; + UINT64 value; + } integer; + struct { + acpi_object_type type; + UINT32 length; + char *pointer; + } string; + struct { + acpi_object_type type; + UINT32 length; + UINT8 *pointer; + } buffer; + struct { + acpi_object_type type; + UINT32 count; + union linuxkpi_acpi_object *elements; + } package; + struct { + acpi_object_type type; + acpi_object_type actual_type; + acpi_handle handle; + } reference; + struct { + acpi_object_type type; + UINT32 proc_id; + acpi_io_address pblk_address; + UINT32 pblk_length; + } processor; + struct { + acpi_object_type type; + UINT32 system_level; + UINT32 resource_order; + } power_resource; +}; + +#ifdef LINUXKPI_WANT_LINUX_ACPI +struct linuxkpi_acpi_buffer { + acpi_size length; /* Length in bytes of the buffer */ + void *pointer; /* pointer to buffer */ +}; + +typedef struct linuxkpi_acpi_buffer lkpi_acpi_buffer_t; +#else +typedef ACPI_BUFFER lkpi_acpi_buffer_t; +#endif + static inline ACPI_STATUS acpi_evaluate_object(ACPI_HANDLE Object, ACPI_STRING Pathname, - ACPI_OBJECT_LIST *ParameterObjects, ACPI_BUFFER *ReturnObjectBuffer) + ACPI_OBJECT_LIST *ParameterObjects, lkpi_acpi_buffer_t *ReturnObjectBuffer) { return (AcpiEvaluateObject( - Object, Pathname, ParameterObjects, ReturnObjectBuffer)); + Object, Pathname, ParameterObjects, (ACPI_BUFFER *)ReturnObjectBuffer)); } static inline const char * @@ -72,7 +131,7 @@ acpi_format_exception(ACPI_STATUS Exception) } static inline ACPI_STATUS -acpi_get_handle(ACPI_HANDLE Parent, ACPI_STRING Pathname, +acpi_get_handle(ACPI_HANDLE Parent, const char *Pathname, ACPI_HANDLE *RetHandle) { return (AcpiGetHandle(Parent, Pathname, RetHandle)); @@ -85,9 +144,9 @@ acpi_get_data(ACPI_HANDLE ObjHandle, ACPI_OBJECT_HANDLER Handler, void **Data) } static inline ACPI_STATUS -acpi_get_name(ACPI_HANDLE Object, UINT32 NameType, ACPI_BUFFER *RetPathPtr) +acpi_get_name(ACPI_HANDLE Object, UINT32 NameType, lkpi_acpi_buffer_t *RetPathPtr) { - return (AcpiGetName(Object, NameType, RetPathPtr)); + return (AcpiGetName(Object, NameType, (ACPI_BUFFER *)RetPathPtr)); } static inline ACPI_STATUS @@ -97,4 +156,15 @@ acpi_get_table(ACPI_STRING Signature, UINT32 Instance, return (AcpiGetTable(Signature, Instance, OutTable)); } -#endif /* _ACPI_ACPI_H_ */ +static inline void +acpi_put_table(ACPI_TABLE_HEADER *Table) +{ + AcpiPutTable(Table); +} + +#ifdef LINUXKPI_WANT_LINUX_ACPI +#define acpi_object linuxkpi_acpi_object +#define acpi_buffer linuxkpi_acpi_buffer +#endif + +#endif /* _LINUXKPI_ACPI_ACPI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h b/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h index abee5223af60..da50d25a63bb 100644 --- a/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h +++ b/sys/compat/linuxkpi/common/include/acpi/acpi_bus.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> * @@ -24,12 +24,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ACPI_ACPI_BUS_H_ -#define _ACPI_ACPI_BUS_H_ +#ifndef _LINUXKPI_ACPI_ACPI_BUS_H_ +#define _LINUXKPI_ACPI_ACPI_BUS_H_ + +/* Aliase struct acpi_device to device_t */ +#define acpi_device _device typedef char acpi_device_class[20]; @@ -39,14 +40,28 @@ struct acpi_bus_event { uint32_t data; }; +#define acpi_dev_present(...) lkpi_acpi_dev_present(__VA_ARGS__) +#define acpi_dev_get_first_match_dev(...) \ + lkpi_acpi_dev_get_first_match_dev(__VA_ARGS__) + ACPI_HANDLE bsd_acpi_get_handle(device_t bsddev); -bool acpi_check_dsm(ACPI_HANDLE handle, const char *uuid, int rev, +bool acpi_check_dsm(ACPI_HANDLE handle, const guid_t *uuid, int rev, uint64_t funcs); -ACPI_OBJECT * acpi_evaluate_dsm_typed(ACPI_HANDLE handle, const char *uuid, +ACPI_OBJECT * acpi_evaluate_dsm_typed(ACPI_HANDLE handle, const guid_t *uuid, int rev, int func, ACPI_OBJECT *argv4, ACPI_OBJECT_TYPE type); int register_acpi_notifier(struct notifier_block *nb); int unregister_acpi_notifier(struct notifier_block *nb); uint32_t acpi_target_system_state(void); +bool lkpi_acpi_dev_present(const char *hid, const char *uid, + int64_t hrv); +struct acpi_device *lkpi_acpi_dev_get_first_match_dev(const char *hid, + const char *uid, int64_t hrv); + +union linuxkpi_acpi_object; + +union linuxkpi_acpi_object * +acpi_evaluate_dsm(ACPI_HANDLE ObjHandle, const guid_t *guid, + UINT64 rev, UINT64 func, union linuxkpi_acpi_object *arg); -#endif /* !_ACPI_ACPI_BUS_H_ */ +#endif /* _LINUXKPI_ACPI_ACPI_BUS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/acpi/actbl.h b/sys/compat/linuxkpi/common/include/acpi/actbl.h new file mode 100644 index 000000000000..dbb7db41bb66 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/acpi/actbl.h @@ -0,0 +1 @@ +#include <contrib/dev/acpica/include/actbl.h> diff --git a/sys/compat/linuxkpi/common/include/acpi/video.h b/sys/compat/linuxkpi/common/include/acpi/video.h index 5c42153356c0..fd2ffd6764d0 100644 --- a/sys/compat/linuxkpi/common/include/acpi/video.h +++ b/sys/compat/linuxkpi/common/include/acpi/video.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> * @@ -24,15 +24,39 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ACPI_VIDEO_H_ -#define _ACPI_VIDEO_H_ +#ifndef _LINUXKPI_ACPI_VIDEO_H_ +#define _LINUXKPI_ACPI_VIDEO_H_ + +#include <sys/types.h> +#include <sys/errno.h> #define ACPI_VIDEO_CLASS "video" #define ACPI_VIDEO_NOTIFY_PROBE 0x81 -#endif /* !_ACPI_VIDEO_H_ */ +static inline int +acpi_video_register(void) +{ + + return (-ENODEV); +} + +static inline void +acpi_video_unregister(void) +{ +} + +static inline void +acpi_video_register_backlight(void) +{ +} + +static inline bool +acpi_video_backlight_use_native(void) +{ + return (true); +} + +#endif /* _LINUXKPI_ACPI_VIDEO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm-generic/io.h b/sys/compat/linuxkpi/common/include/asm-generic/io.h new file mode 100644 index 000000000000..8dc7eb6cf453 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm-generic/io.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_ASMGENERIC_IO_H_ +#define _LINUXKPI_ASMGENERIC_IO_H_ + +#if defined(__i386__) || defined(__amd64__) + +#include <machine/cpufunc.h> + +#define outb(a,b) outb(b,a) +#define outw(a,b) outw(b,a) +#define outl(a,b) outl(b,a) + +#endif + +#endif /* _LINUXKPI_ASMGENERIC_IO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/atomic-long.h b/sys/compat/linuxkpi/common/include/asm/atomic-long.h index c80c348f95f9..db3a94c539e5 100644 --- a/sys/compat/linuxkpi/common/include/asm/atomic-long.h +++ b/sys/compat/linuxkpi/common/include/asm/atomic-long.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ATOMIC_LONG_H_ -#define _ATOMIC_LONG_H_ +#ifndef _LINUXKPI_ASM_ATOMIC_LONG_H_ +#define _LINUXKPI_ASM_ATOMIC_LONG_H_ #include <linux/compiler.h> #include <sys/types.h> @@ -41,7 +39,7 @@ typedef struct { } atomic_long_t; #define atomic_long_add(i, v) atomic_long_add_return((i), (v)) -#define atomic_long_sub(i, v) atomic_long_add_return(-(i), (v)) +#define atomic_long_sub(i, v) atomic_long_sub_return((i), (v)) #define atomic_long_inc_return(v) atomic_long_add_return(1, (v)) #define atomic_long_inc_not_zero(v) atomic_long_add_unless((v), 1, 0) @@ -51,6 +49,12 @@ atomic_long_add_return(long i, atomic_long_t *v) return i + atomic_fetchadd_long(&v->counter, i); } +static inline long +atomic_long_sub_return(long i, atomic_long_t *v) +{ + return atomic_fetchadd_long(&v->counter, -i) - i; +} + static inline void atomic_long_set(atomic_long_t *v, long i) { @@ -130,4 +134,4 @@ atomic_long_dec_and_test(atomic_long_t *v) return i == 0 ; } -#endif /* _ATOMIC_LONG_H_ */ +#endif /* _LINUXKPI_ASM_ATOMIC_LONG_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/atomic.h b/sys/compat/linuxkpi/common/include/asm/atomic.h index 5cdfbe674ef3..edb478af8c82 100644 --- a/sys/compat/linuxkpi/common/include/asm/atomic.h +++ b/sys/compat/linuxkpi/common/include/asm/atomic.h @@ -25,12 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_ATOMIC_H_ -#define _ASM_ATOMIC_H_ +#ifndef _LINUXKPI_ASM_ATOMIC_H_ +#define _LINUXKPI_ASM_ATOMIC_H_ #include <linux/compiler.h> #include <sys/types.h> @@ -166,9 +164,7 @@ atomic_cmpxchg(atomic_t *v, int old, int new) #define LINUXKPI_ATOMIC_16(...) #endif -#if !(defined(i386) || (defined(__mips__) && !(defined(__mips_n32) || \ - defined(__mips_n64))) || (defined(__powerpc__) && \ - !defined(__powerpc64__))) +#if !(defined(i386) || (defined(__powerpc__) && !defined(__powerpc64__))) #define LINUXKPI_ATOMIC_64(...) __VA_ARGS__ #else #define LINUXKPI_ATOMIC_64(...) @@ -220,6 +216,7 @@ atomic_cmpxchg(atomic_t *v, int old, int new) __ret.val; \ }) +#define cmpxchg64(...) cmpxchg(__VA_ARGS__) #define cmpxchg_relaxed(...) cmpxchg(__VA_ARGS__) #define xchg(ptr, new) ({ \ @@ -268,6 +265,28 @@ atomic_cmpxchg(atomic_t *v, int old, int new) __ret.val; \ }) +#define try_cmpxchg(p, op, n) \ +({ \ + __typeof(p) __op = (__typeof((p)))(op); \ + __typeof(*(p)) __o = *__op; \ + __typeof(*(p)) __p = __sync_val_compare_and_swap((p), (__o), (n)); \ + if (__p != __o) \ + *__op = __p; \ + (__p == __o); \ +}) + +#define __atomic_try_cmpxchg(type, _p, _po, _n) \ +({ \ + __typeof(_po) __po = (_po); \ + __typeof(*(_po)) __r, __o = *__po; \ + __r = atomic_cmpxchg##type((_p), __o, (_n)); \ + if (unlikely(__r != __o)) \ + *__po = __r; \ + likely(__r == __o); \ +}) + +#define atomic_try_cmpxchg(_p, _po, _n) __atomic_try_cmpxchg(, _p, _po, _n) + static inline int atomic_dec_if_positive(atomic_t *v) { @@ -307,6 +326,13 @@ static inline int atomic_fetch_##op(int i, atomic_t *v) \ return (c); \ } +static inline int +atomic_fetch_inc(atomic_t *v) +{ + + return ((atomic_inc_return(v) - 1)); +} + LINUX_ATOMIC_OP(or, |) LINUX_ATOMIC_OP(and, &) LINUX_ATOMIC_OP(andnot, &~) @@ -317,4 +343,4 @@ LINUX_ATOMIC_FETCH_OP(and, &) LINUX_ATOMIC_FETCH_OP(andnot, &~) LINUX_ATOMIC_FETCH_OP(xor, ^) -#endif /* _ASM_ATOMIC_H_ */ +#endif /* _LINUXKPI_ASM_ATOMIC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/atomic64.h b/sys/compat/linuxkpi/common/include/asm/atomic64.h index b8b87bb2c685..fbfb9254b64c 100644 --- a/sys/compat/linuxkpi/common/include/asm/atomic64.h +++ b/sys/compat/linuxkpi/common/include/asm/atomic64.h @@ -22,11 +22,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_ATOMIC64_H_ -#define _ASM_ATOMIC64_H_ +#ifndef _LINUXKPI_ASM_ATOMIC64_H_ +#define _LINUXKPI_ASM_ATOMIC64_H_ #include <linux/compiler.h> #include <sys/types.h> @@ -53,6 +51,12 @@ typedef struct { #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) static inline int64_t +atomic64_fetch_add(int64_t i, atomic64_t *v) +{ + return (atomic_fetchadd_64(&v->counter, i)); +} + +static inline int64_t atomic64_add_return(int64_t i, atomic64_t *v) { return i + atomic_fetchadd_64(&v->counter, i); @@ -119,8 +123,7 @@ atomic64_fetch_add_unless(atomic64_t *v, int64_t a, int64_t u) static inline int64_t atomic64_xchg(atomic64_t *v, int64_t i) { -#if !((defined(__mips__) && !(defined(__mips_n32) || defined(__mips_n64))) || \ - (defined(__powerpc__) && !defined(__powerpc64__))) +#if !(defined(__powerpc__) && !defined(__powerpc64__)) return (atomic_swap_64(&v->counter, i)); #else int64_t ret = atomic64_read(v); @@ -145,4 +148,4 @@ atomic64_cmpxchg(atomic64_t *v, int64_t old, int64_t new) return (ret); } -#endif /* _ASM_ATOMIC64_H_ */ +#endif /* _LINUXKPI_ASM_ATOMIC64_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/barrier.h b/sys/compat/linuxkpi/common/include/asm/barrier.h new file mode 100644 index 000000000000..39c5139cb322 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/barrier.h @@ -0,0 +1,64 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_ASM_BARRIER_H_ +#define _LINUXKPI_ASM_BARRIER_H_ + +#include <sys/types.h> +#include <machine/atomic.h> + +#include <asm/atomic.h> +#include <linux/compiler.h> + +/* TODO: Check other archs for atomic_thread_fence_* useability */ +#if defined(__amd64__) || defined(__i386__) +#define smp_mb() atomic_thread_fence_seq_cst() +#define smp_wmb() atomic_thread_fence_rel() +#define smp_rmb() atomic_thread_fence_acq() +#define smp_store_mb(x, v) do { (void)xchg(&(x), v); } while (0) +#endif + +#ifndef smp_mb +#define smp_mb() mb() +#endif +#ifndef smp_wmb +#define smp_wmb() wmb() +#endif +#ifndef smp_rmb +#define smp_rmb() rmb() +#endif +#ifndef smp_store_mb +#define smp_store_mb(x, v) do { WRITE_ONCE(x, v); smp_mb(); } while (0) +#endif + +#define smp_mb__before_atomic() barrier() +#define smp_mb__after_atomic() barrier() + +#define smp_store_release(p, v) do { smp_mb(); WRITE_ONCE(*p, v); } while (0) +#define smp_load_acquire(p) ({ typeof(*p) _v = READ_ONCE(*p); smp_mb(); _v; }) + +#endif /* _LINUXKPI_ASM_BARRIER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/byteorder.h b/sys/compat/linuxkpi/common/include/asm/byteorder.h index 05e39bb52149..ad7a923ca143 100644 --- a/sys/compat/linuxkpi/common/include/asm/byteorder.h +++ b/sys/compat/linuxkpi/common/include/asm/byteorder.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_BYTEORDER_H_ -#define _ASM_BYTEORDER_H_ +#ifndef _LINUXKPI_ASM_BYTEORDER_H_ +#define _LINUXKPI_ASM_BYTEORDER_H_ #include <sys/types.h> #include <sys/endian.h> @@ -157,4 +155,4 @@ le16_add_cpu(uint16_t *var, uint16_t val) *var = cpu_to_le16(le16_to_cpu(*var) + val); } -#endif /* _ASM_BYTEORDER_H_ */ +#endif /* _LINUXKPI_ASM_BYTEORDER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/cpufeature.h b/sys/compat/linuxkpi/common/include/asm/cpufeature.h new file mode 100644 index 000000000000..84ab86af33dd --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/cpufeature.h @@ -0,0 +1,37 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_ASM_CPUFEATURE_H +#define _LINUXKPI_ASM_CPUFEATURE_H + +#if defined(__amd64__) || defined(__i386__) + +#include <sys/types.h> +#include <machine/md_var.h> + +#define X86_FEATURE_CLFLUSH 1 +#define X86_FEATURE_XMM4_1 2 +#define X86_FEATURE_PAT 3 +#define X86_FEATURE_HYPERVISOR 4 + +static inline bool +static_cpu_has(uint16_t f) +{ + switch (f) { + case X86_FEATURE_CLFLUSH: + return ((cpu_feature & CPUID_CLFSH) != 0); + case X86_FEATURE_XMM4_1: + return ((cpu_feature2 & CPUID2_SSE41) != 0); + case X86_FEATURE_PAT: + return ((cpu_feature & CPUID_PAT) != 0); + case X86_FEATURE_HYPERVISOR: + return ((cpu_feature2 & CPUID2_HV) != 0); + default: + return (false); + } +} + +#define boot_cpu_has(x) static_cpu_has(x) + +#endif + +#endif diff --git a/sys/compat/linuxkpi/common/include/asm/fcntl.h b/sys/compat/linuxkpi/common/include/asm/fcntl.h index f24624e6eeed..3820e15039f2 100644 --- a/sys/compat/linuxkpi/common/include/asm/fcntl.h +++ b/sys/compat/linuxkpi/common/include/asm/fcntl.h @@ -25,12 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_FCNTL_H_ -#define _ASM_FCNTL_H_ +#ifndef _LINUXKPI_ASM_FCNTL_H_ +#define _LINUXKPI_ASM_FCNTL_H_ #include <sys/fcntl.h> -#endif /* _ASM_FCNTL_H_ */ +#endif /* _LINUXKPI_ASM_FCNTL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/fpu/api.h b/sys/compat/linuxkpi/common/include/asm/fpu/api.h index 9c63b2e972bf..a4803bde461f 100644 --- a/sys/compat/linuxkpi/common/include/asm/fpu/api.h +++ b/sys/compat/linuxkpi/common/include/asm/fpu/api.h @@ -1,7 +1,7 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 Greg V <greg@unrelenting.technology> + * Copyright (c) 2020 Val Packett <val@packett.cool> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,8 +25,8 @@ * SUCH DAMAGE. */ -#ifndef _FPU_API_H_ -#define _FPU_API_H_ +#ifndef _LINUXKPI_ASM_FPU_API_H_ +#define _LINUXKPI_ASM_FPU_API_H_ #define kernel_fpu_begin() \ lkpi_kernel_fpu_begin() @@ -37,4 +37,4 @@ extern void lkpi_kernel_fpu_begin(void); extern void lkpi_kernel_fpu_end(void); -#endif /* _FPU_API_H_ */ +#endif /* _LINUXKPI_ASM_FPU_API_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/hypervisor.h b/sys/compat/linuxkpi/common/include/asm/hypervisor.h new file mode 100644 index 000000000000..f344a2929359 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/hypervisor.h @@ -0,0 +1,19 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_ASM_HYPERVISOR_H +#define _LINUXKPI_ASM_HYPERVISOR_H + +#if defined(__i386__) || defined(__amd64__) + +#define X86_HYPER_NATIVE 1 +#define X86_HYPER_MS_HYPERV 2 + +static inline bool +hypervisor_is_type(int type) +{ + return (type == X86_HYPER_NATIVE); +} + +#endif + +#endif diff --git a/sys/compat/linuxkpi/common/include/asm/intel-family.h b/sys/compat/linuxkpi/common/include/asm/intel-family.h new file mode 100644 index 000000000000..91ad1d1a8ff3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/intel-family.h @@ -0,0 +1,6 @@ +/* Public domain. */ + +#define INTEL_FAM6_ALDERLAKE 0x97 +#define INTEL_FAM6_ALDERLAKE_L 0x9A + +#define INTEL_FAM6_ROCKETLAKE 0xA7 diff --git a/sys/compat/linuxkpi/common/include/asm/io.h b/sys/compat/linuxkpi/common/include/asm/io.h index 24d350f4743e..63d1c8f72f8e 100644 --- a/sys/compat/linuxkpi/common/include/asm/io.h +++ b/sys/compat/linuxkpi/common/include/asm/io.h @@ -25,12 +25,17 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_IO_H_ -#define _ASM_IO_H_ +#ifndef _LINUXKPI_ASM_IO_H_ +#define _LINUXKPI_ASM_IO_H_ + +#include <sys/param.h> + +#include <vm/vm.h> +#include <vm/pmap.h> #include <linux/io.h> -#endif /* _ASM_IO_H_ */ +#define virt_to_phys(x) vtophys(x) + +#endif /* _LINUXKPI_ASM_IO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/iosf_mbi.h b/sys/compat/linuxkpi/common/include/asm/iosf_mbi.h new file mode 100644 index 000000000000..a99c9cced6a4 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/iosf_mbi.h @@ -0,0 +1,15 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_ASM_IOSF_MBI_H_ +#define _LINUXKPI_ASM_IOSF_MBI_H_ + +#define MBI_PMIC_BUS_ACCESS_BEGIN 1 +#define MBI_PMIC_BUS_ACCESS_END 2 + +#define iosf_mbi_assert_punit_acquired() +#define iosf_mbi_punit_acquire() +#define iosf_mbi_punit_release() +#define iosf_mbi_register_pmic_bus_access_notifier(x) 0 +#define iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(x) 0 + +#endif /* _LINUXKPI_ASM_IOSF_MBI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/memtype.h b/sys/compat/linuxkpi/common/include/asm/memtype.h new file mode 100644 index 000000000000..c433e54fd7bf --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/memtype.h @@ -0,0 +1,18 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_ASM_MEMTYPE_H_ +#define _LINUXKPI_ASM_MEMTYPE_H_ + +#if defined(__amd64__) || defined(__i386__) + +#include <asm/cpufeature.h> + +static inline bool +pat_enabled(void) +{ + return (boot_cpu_has(X86_FEATURE_PAT)); +} + +#endif + +#endif /* _LINUXKPI_ASM_MEMTYPE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/msr.h b/sys/compat/linuxkpi/common/include/asm/msr.h index 1697c20767a5..6f7c10f2860b 100644 --- a/sys/compat/linuxkpi/common/include/asm/msr.h +++ b/sys/compat/linuxkpi/common/include/asm/msr.h @@ -22,16 +22,14 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_MSR_H_ -#define _ASM_MSR_H_ +#ifndef _LINUXKPI_ASM_MSR_H_ +#define _LINUXKPI_ASM_MSR_H_ #include <machine/cpufunc.h> #define rdmsrl(msr, val) ((val) = rdmsr(msr)) #define rdmsrl_safe(msr, val) rdmsr_safe(msr, val) -#endif /* _ASM_MSR_H_ */ +#endif /* _LINUXKPI_ASM_MSR_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/neon.h b/sys/compat/linuxkpi/common/include/asm/neon.h new file mode 100644 index 000000000000..0488a90d6664 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/neon.h @@ -0,0 +1,40 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Val Packett <val@packett.cool> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_ASM_NEON_H_ +#define _LINUXKPI_ASM_NEON_H_ + +#define kernel_neon_begin() \ + lkpi_kernel_fpu_begin() + +#define kernel_neon_end() \ + lkpi_kernel_fpu_end() + +extern void lkpi_kernel_fpu_begin(void); +extern void lkpi_kernel_fpu_end(void); + +#endif /* _LINUXKPI_ASM_NEON_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/pgtable.h b/sys/compat/linuxkpi/common/include/asm/pgtable.h index 4831c144888d..865662d587db 100644 --- a/sys/compat/linuxkpi/common/include/asm/pgtable.h +++ b/sys/compat/linuxkpi/common/include/asm/pgtable.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_PGTABLE_H_ -#define _ASM_PGTABLE_H_ +#ifndef _LINUXKPI_ASM_PGTABLE_H_ +#define _LINUXKPI_ASM_PGTABLE_H_ #include <linux/page.h> @@ -42,4 +40,19 @@ typedef struct page *pgtable_t; #define pgprot_decrypted(prot) (prot) -#endif /* _ASM_PGTABLE_H_ */ +#if defined(__i386__) || defined(__amd64__) +#define _PAGE_BIT_PRESENT 0 +#define _PAGE_BIT_RW 1 +#define _PAGE_BIT_USER 2 +#define _PAGE_BIT_PWT 3 +#define _PAGE_BIT_PCD 4 +#define _PAGE_BIT_PAT 7 + +#define _PAGE_PRESENT (((pteval_t) 1) << _PAGE_BIT_PRESENT) +#define _PAGE_RW (((pteval_t) 1) << _PAGE_BIT_RW) +#define _PAGE_PWT (((pteval_t) 1) << _PAGE_BIT_PWT) +#define _PAGE_PCD (((pteval_t) 1) << _PAGE_BIT_PCD) +#define _PAGE_PAT (((pteval_t) 1) << _PAGE_BIT_PAT) +#endif + +#endif /* _LINUXKPI_ASM_PGTABLE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/processor.h b/sys/compat/linuxkpi/common/include/asm/processor.h new file mode 100644 index 000000000000..2bc4b6532544 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/processor.h @@ -0,0 +1,63 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_ASM_PROCESSOR_H_ +#define _LINUXKPI_ASM_PROCESSOR_H_ + +#include <sys/types.h> +#include <machine/cpufunc.h> +#include <machine/cpu.h> + +#if defined(__i386__) || defined(__amd64__) +#define X86_VENDOR_INTEL 0 +#define X86_VENDOR_CYRIX 1 +#define X86_VENDOR_AMD 2 +#define X86_VENDOR_UMC 3 +#define X86_VENDOR_CENTAUR 5 +#define X86_VENDOR_TRANSMETA 7 +#define X86_VENDOR_NSC 8 +#define X86_VENDOR_HYGON 9 +#define X86_VENDOR_NUM 12 + +#define X86_VENDOR_UNKNOWN 0xff + +struct cpuinfo_x86 { + uint8_t x86; + uint8_t x86_model; + uint16_t x86_clflush_size; + uint16_t x86_max_cores; + uint8_t x86_vendor; +}; + +extern struct cpuinfo_x86 boot_cpu_data; +extern struct cpuinfo_x86 *__cpu_data; +#define cpu_data(cpu) __cpu_data[cpu] +#endif + +#define cpu_relax() cpu_spinwait() + +#endif /* _LINUXKPI_ASM_PROCESSOR_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/set_memory.h b/sys/compat/linuxkpi/common/include/asm/set_memory.h new file mode 100644 index 000000000000..1019aaf264a0 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/set_memory.h @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2016 Matt Macy (mmacy@nextbsd.org) + * Copyright (c) 2017 Mellanox Technologies, Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_ASM_SET_MEMORY_H_ +#define _LINUXKPI_ASM_SET_MEMORY_H_ + +#include <linux/page.h> + +static inline int +set_memory_uc(unsigned long addr, int numpages) +{ + vm_size_t len; + + len = (vm_size_t)numpages << PAGE_SHIFT; + return (-pmap_change_attr(addr, len, VM_MEMATTR_UNCACHEABLE)); +} + +static inline int +set_memory_wc(unsigned long addr, int numpages) +{ +#ifdef VM_MEMATTR_WRITE_COMBINING + vm_size_t len; + + len = (vm_size_t)numpages << PAGE_SHIFT; + return (-pmap_change_attr(addr, len, VM_MEMATTR_WRITE_COMBINING)); +#else + return (set_memory_uc(addr, numpages)); +#endif +} + +static inline int +set_memory_wb(unsigned long addr, int numpages) +{ + vm_size_t len; + + len = (vm_size_t)numpages << PAGE_SHIFT; + return (-pmap_change_attr(addr, len, VM_MEMATTR_WRITE_BACK)); +} + +static inline int +set_pages_uc(struct page *page, int numpages) +{ + KASSERT(numpages == 1, ("%s: numpages %d", __func__, numpages)); + + pmap_page_set_memattr(page, VM_MEMATTR_UNCACHEABLE); + return (0); +} + +static inline int +set_pages_wc(struct page *page, int numpages) +{ + KASSERT(numpages == 1, ("%s: numpages %d", __func__, numpages)); + +#ifdef VM_MEMATTR_WRITE_COMBINING + pmap_page_set_memattr(page, VM_MEMATTR_WRITE_COMBINING); +#else + return (set_pages_uc(page, numpages)); +#endif + return (0); +} + +static inline int +set_pages_wb(struct page *page, int numpages) +{ + KASSERT(numpages == 1, ("%s: numpages %d", __func__, numpages)); + + pmap_page_set_memattr(page, VM_MEMATTR_WRITE_BACK); + return (0); +} + +static inline int +set_pages_array_wb(struct page **pages, int addrinarray) +{ + int i; + + for (i = 0; i < addrinarray; i++) + set_pages_wb(pages[i], 1); + return (0); +} + +static inline int +set_pages_array_wc(struct page **pages, int addrinarray) +{ + int i; + + for (i = 0; i < addrinarray; i++) + set_pages_wc(pages[i], 1); + return (0); +} + +static inline int +set_pages_array_uc(struct page **pages, int addrinarray) +{ + int i; + + for (i = 0; i < addrinarray; i++) + set_pages_uc(pages[i], 1); + return (0); +} + +#endif /* _LINUXKPI_ASM_SET_MEMORY_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/smp.h b/sys/compat/linuxkpi/common/include/asm/smp.h index dd25b02115a8..27c3a81ef101 100644 --- a/sys/compat/linuxkpi/common/include/asm/smp.h +++ b/sys/compat/linuxkpi/common/include/asm/smp.h @@ -22,12 +22,14 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_SMP_H_ -#define _ASM_SMP_H_ +#ifndef _LINUXKPI_ASM_SMP_H_ +#define _LINUXKPI_ASM_SMP_H_ + +#include <linux/jump_label.h> +#include <linux/preempt.h> +#include <asm/fpu/api.h> #if defined(__i386__) || defined(__amd64__) @@ -45,4 +47,4 @@ int linux_wbinvd_on_all_cpus(void); #define put_cpu() \ critical_exit() -#endif /* _ASM_SMP_H_ */ +#endif /* _LINUXKPI_ASM_SMP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/topology.h b/sys/compat/linuxkpi/common/include/asm/topology.h new file mode 100644 index 000000000000..f334d3253cfb --- /dev/null +++ b/sys/compat/linuxkpi/common/include/asm/topology.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_ASM_TOPOLOGY_H_ +#define _LINUXKPI_ASM_TOPOLOGY_H_ + +#if defined(__i386__) || defined(__amd64__) +#include <sys/smp.h> + +/* + * The following functions are defined in `arch/x86/include/asm/topology.h` + * and thus are specific to i386 and amd64. + */ + +static inline unsigned int +topology_num_cores_per_package(void) +{ + return (mp_ncores); +} + +static inline unsigned int +topology_num_threads_per_package(void) +{ + return (mp_ncpus); +} +#endif + +#endif /* _LINUXKPI_ASM_TOPOLOGY_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/types.h b/sys/compat/linuxkpi/common/include/asm/types.h index daa5d83616a2..2e61bcfdb5e6 100644 --- a/sys/compat/linuxkpi/common/include/asm/types.h +++ b/sys/compat/linuxkpi/common/include/asm/types.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_TYPES_H_ -#define _ASM_TYPES_H_ +#ifndef _LINUXKPI_ASM_TYPES_H_ +#define _LINUXKPI_ASM_TYPES_H_ #if defined(_KERNEL) || defined(_STANDALONE) @@ -61,4 +59,4 @@ typedef unsigned short umode_t; #endif /* _KERNEL || _STANDALONE */ -#endif /* _ASM_TYPES_H_ */ +#endif /* _LINUXKPI_ASM_TYPES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/uaccess.h b/sys/compat/linuxkpi/common/include/asm/uaccess.h index 102373634ba3..94354f8ddeee 100644 --- a/sys/compat/linuxkpi/common/include/asm/uaccess.h +++ b/sys/compat/linuxkpi/common/include/asm/uaccess.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_UACCESS_H_ -#define _ASM_UACCESS_H_ +#ifndef _LINUXKPI_ASM_UACCESS_H_ +#define _LINUXKPI_ASM_UACCESS_H_ #include <linux/uaccess.h> @@ -55,6 +53,9 @@ copy_from_user(void *to, const void *from, unsigned long n) #define user_access_begin(ptr, len) access_ok(ptr, len) #define user_access_end() do { } while (0) +#define user_write_access_begin(ptr, len) access_ok(ptr, len) +#define user_write_access_end() do { } while (0) + #define unsafe_get_user(x, ptr, err) do { \ if (unlikely(__get_user(x, ptr))) \ goto err; \ @@ -65,4 +66,4 @@ copy_from_user(void *to, const void *from, unsigned long n) goto err; \ } while (0) -#endif /* _ASM_UACCESS_H_ */ +#endif /* _LINUXKPI_ASM_UACCESS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/asm/unaligned.h b/sys/compat/linuxkpi/common/include/asm/unaligned.h index 7597f00f7596..e45846a3b543 100644 --- a/sys/compat/linuxkpi/common/include/asm/unaligned.h +++ b/sys/compat/linuxkpi/common/include/asm/unaligned.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 The FreeBSD Foundation + * Copyright (c) 2020,2023 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,16 +26,21 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _ASM_UNALIGNED_H -#define _ASM_UNALIGNED_H +#ifndef _LINUXKPI_ASM_UNALIGNED_H +#define _LINUXKPI_ASM_UNALIGNED_H #include <linux/types.h> #include <asm/byteorder.h> +static __inline uint16_t +get_unaligned_le16(const void *p) +{ + + return (le16_to_cpup((const __le16 *)p)); +} + static __inline uint32_t get_unaligned_le32(const void *p) { @@ -44,6 +49,15 @@ get_unaligned_le32(const void *p) } static __inline void +put_unaligned_le16(__le16 v, void *p) +{ + __le16 x; + + x = cpu_to_le16(v); + memcpy(p, &x, sizeof(x)); +} + +static __inline void put_unaligned_le32(__le32 v, void *p) { __le32 x; @@ -75,4 +89,11 @@ get_unaligned_be32(const void *p) return (be32_to_cpup((const __be32 *)p)); } -#endif /* _ASM_UNALIGNED_H */ +static __inline uint64_t +get_unaligned_be64(const void *p) +{ + + return (be64_to_cpup((const __be64 *)p)); +} + +#endif /* _LINUXKPI_ASM_UNALIGNED_H */ diff --git a/sys/compat/linuxkpi/common/include/crypto/hash.h b/sys/compat/linuxkpi/common/include/crypto/hash.h new file mode 100644 index 000000000000..bf401691722a --- /dev/null +++ b/sys/compat/linuxkpi/common/include/crypto/hash.h @@ -0,0 +1,94 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_CRYPTO_HASH_H +#define _LINUXKPI_CRYPTO_HASH_H + +#include <linux/kernel.h> /* for pr_debug */ + +struct crypto_shash { +}; + +struct shash_desc { + struct crypto_shash *tfm; +}; + +static inline struct crypto_shash * +crypto_alloc_shash(const char *algostr, int x, int y) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline void +crypto_free_shash(struct crypto_shash *csh) +{ + pr_debug("%s: TODO\n", __func__); +} + +static inline int +crypto_shash_init(struct shash_desc *desc) +{ + pr_debug("%s: TODO\n", __func__); + return (-ENXIO); +} + +static inline int +crypto_shash_final(struct shash_desc *desc, uint8_t *mic) +{ + pr_debug("%s: TODO\n", __func__); + return (-ENXIO); +} + +static inline int +crypto_shash_setkey(struct crypto_shash *csh, const uint8_t *key, size_t keylen) +{ + pr_debug("%s: TODO\n", __func__); + return (-ENXIO); +} + +static inline int +crypto_shash_update(struct shash_desc *desc, uint8_t *data, size_t datalen) +{ + pr_debug("%s: TODO\n", __func__); + return (-ENXIO); +} + +static inline void +shash_desc_zero(struct shash_desc *desc) +{ + + explicit_bzero(desc, sizeof(*desc)); +} + +/* XXX review this. */ +#define SHASH_DESC_ON_STACK(desc, tfm) \ + uint8_t ___ ## desc ## _desc[sizeof(struct shash_desc)]; \ + struct shash_desc *desc = (struct shash_desc *)___ ## desc ## _desc + +#endif /* _LINUXKPI_CRYPTO_HASH_H */ diff --git a/sys/compat/linuxkpi/common/include/kunit/static_stub.h b/sys/compat/linuxkpi/common/include/kunit/static_stub.h new file mode 100644 index 000000000000..9d425d46dbb0 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/kunit/static_stub.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_KUNIT_STATIC_STUB_H +#define _LINUXKPI_KUNIT_STATIC_STUB_H + +#define KUNIT_STATIC_STUB_REDIRECT(_fn, ...) do { } while(0) + +#endif /* _LINUXKPI_KUNIT_STATIC_STUB_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/acpi.h b/sys/compat/linuxkpi/common/include/linux/acpi.h index b1e65b9afad9..3e1ec1b20626 100644 --- a/sys/compat/linuxkpi/common/include/linux/acpi.h +++ b/sys/compat/linuxkpi/common/include/linux/acpi.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> * @@ -24,12 +24,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_ACPI_H_ -#define _LINUX_ACPI_H_ +#ifndef _LINUXKPI_LINUX_ACPI_H_ +#define _LINUXKPI_LINUX_ACPI_H_ #include <linux/device.h> #include <linux/uuid.h> @@ -41,7 +39,11 @@ #define ACPI_HANDLE(dev) \ ((dev)->bsddev != NULL ? bsd_acpi_get_handle((dev)->bsddev) : NULL) +#define acpi_device_handle(dev) \ + ((dev) != NULL ? bsd_acpi_get_handle(dev) : NULL) +static inline void acpi_dev_put(struct acpi_device *adev) {} +#define acpi_handle_debug(handle, fmt, ...) #endif -#endif /* _LINUX_ACPI_H_ */ +#endif /* _LINUXKPI_LINUX_ACPI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/acpi_amd_wbrf.h b/sys/compat/linuxkpi/common/include/linux/acpi_amd_wbrf.h new file mode 100644 index 000000000000..92c2ead41c45 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/acpi_amd_wbrf.h @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_ACPI_AMD_WBRF_H_ +#define _LINUXKPI_LINUX_ACPI_AMD_WBRF_H_ + +#include <linux/device.h> +#include <linux/notifier.h> + +#define MAX_NUM_OF_WBRF_RANGES 11 + +#define WBRF_RECORD_ADD 0x0 +#define WBRF_RECORD_REMOVE 0x1 + +struct freq_band_range { + uint64_t start; + uint64_t end; +}; + +struct wbrf_ranges_in_out { + uint64_t num_of_ranges; + struct freq_band_range band_list[MAX_NUM_OF_WBRF_RANGES]; +}; + +enum wbrf_notifier_actions { + WBRF_CHANGED, +}; + +/* + * The following functions currently have dummy implementations that, on Linux, + * are used when CONFIG_AMD_WBRF is not set at compile time. + */ + +static inline bool +acpi_amd_wbrf_supported_consumer(struct device *dev) +{ + return (false); +} + +static inline int +acpi_amd_wbrf_add_remove(struct device *dev, uint8_t action, + struct wbrf_ranges_in_out *in) +{ + return (-ENODEV); +} + +static inline bool +acpi_amd_wbrf_supported_producer(struct device *dev) +{ + return (false); +} + +static inline int +amd_wbrf_retrieve_freq_band(struct device *dev, struct wbrf_ranges_in_out *out) +{ + return (-ENODEV); +} + +static inline int +amd_wbrf_register_notifier(struct notifier_block *nb) +{ + return (-ENODEV); +} + +static inline int +amd_wbrf_unregister_notifier(struct notifier_block *nb) +{ + return (-ENODEV); +} + +#endif /* _LINUXKPI_LINUX_ACPI_AMD_WBRF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/agp_backend.h b/sys/compat/linuxkpi/common/include/linux/agp_backend.h new file mode 100644 index 000000000000..c855fd842970 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/agp_backend.h @@ -0,0 +1,28 @@ +/* Public domain */ + +#ifndef _LINUXKPI_LINUX_AGP_BACKEND_H_ +#define _LINUXKPI_LINUX_AGP_BACKEND_H_ + +#include <sys/types.h> + +struct agp_version { + uint16_t major; + uint16_t minor; +}; + +struct agp_kern_info { + struct agp_version version; + uint16_t vendor; + uint16_t device; + unsigned long mode; + unsigned long aper_base; + size_t aper_size; + int max_memory; + int current_memory; + bool cant_use_aperture; + unsigned long page_mask; +}; + +struct agp_memory; + +#endif /* _LINUXKPI_LINUX_AGP_BACKEND_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/anon_inodes.h b/sys/compat/linuxkpi/common/include/linux/anon_inodes.h index 8fa61cd4b45f..c69f6e152b17 100644 --- a/sys/compat/linuxkpi/common/include/linux/anon_inodes.h +++ b/sys/compat/linuxkpi/common/include/linux/anon_inodes.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> * @@ -26,8 +26,8 @@ * SUCH DAMAGE. */ -#ifndef _LINUX_ANON_INODES_H_ -#define _LINUX_ANON_INODES_H_ +#ifndef _LINUXKPI_LINUX_ANON_INODES_H_ +#define _LINUXKPI_LINUX_ANON_INODES_H_ #include <linux/fs.h> #include <linux/file.h> @@ -45,4 +45,4 @@ anon_inode_getfile(const char *name __unused, return (file); } -#endif /* _LINUX_ANON_INODES_H_ */ +#endif /* _LINUXKPI_LINUX_ANON_INODES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/aperture.h b/sys/compat/linuxkpi/common/include/linux/aperture.h new file mode 100644 index 000000000000..7eced3cc3cb1 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/aperture.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef _LINUX_APERTURE_H_ +#define _LINUX_APERTURE_H_ + +#include <linux/types.h> + +#define CONFIG_APERTURE_HELPERS + +struct pci_dev; +struct platform_device; + +#if defined(CONFIG_APERTURE_HELPERS) +int devm_aperture_acquire_for_platform_device(struct platform_device *pdev, + resource_size_t base, + resource_size_t size); + +int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, + const char *name); + +int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev); + +int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name); +#else +static inline int devm_aperture_acquire_for_platform_device(struct platform_device *pdev, + resource_size_t base, + resource_size_t size) +{ + return 0; +} + +static inline int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, + const char *name) +{ + return 0; +} + +static inline int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev) +{ + return 0; +} + +static inline int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name) +{ + return 0; +} +#endif + +/** + * aperture_remove_all_conflicting_devices - remove all existing framebuffers + * @name: a descriptive name of the requesting driver + * + * This function removes all graphics device drivers. Use this function on systems + * that can have their framebuffer located anywhere in memory. + * + * Returns: + * 0 on success, or a negative errno code otherwise + */ +static inline int aperture_remove_all_conflicting_devices(const char *name) +{ + return aperture_remove_conflicting_devices(0, (resource_size_t)-1, name); +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/apple-gmux.h b/sys/compat/linuxkpi/common/include/linux/apple-gmux.h new file mode 100644 index 000000000000..812a782c57d4 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/apple-gmux.h @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_APPLE_GMUX_H +#define _LINUXKPI_LINUX_APPLE_GMUX_H + +static inline bool +apple_gmux_detect(void *a, void *b) +{ + return false; +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/atomic.h b/sys/compat/linuxkpi/common/include/linux/atomic.h index f8aa5c9276e7..bc76928a7d67 100644 --- a/sys/compat/linuxkpi/common/include/linux/atomic.h +++ b/sys/compat/linuxkpi/common/include/linux/atomic.h @@ -22,15 +22,14 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_ATOMIC_H_ -#define _LINUX_ATOMIC_H_ +#ifndef _LINUXKPI_LINUX_ATOMIC_H_ +#define _LINUXKPI_LINUX_ATOMIC_H_ #include <asm/atomic.h> #include <asm/atomic64.h> #include <asm/atomic-long.h> +#include <asm/barrier.h> -#endif /* _LINUX_ATOMIC_H_ */ +#endif /* _LINUXKPI_LINUX_ATOMIC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/average.h b/sys/compat/linuxkpi/common/include/linux/average.h index 4291bf2d85be..4191a351c5c6 100644 --- a/sys/compat/linuxkpi/common/include/linux/average.h +++ b/sys/compat/linuxkpi/common/include/linux/average.h @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_AVERAGE_H -#define __LKPI_LINUX_AVERAGE_H +#ifndef _LINUXKPI_LINUX_AVERAGE_H +#define _LINUXKPI_LINUX_AVERAGE_H #include <sys/param.h> #include <sys/systm.h> @@ -89,4 +87,4 @@ return (ewma->zt >> (_p)); \ } \ -#endif /* __LKPI_LINUX_AVERAGE_H */ +#endif /* _LINUXKPI_LINUX_AVERAGE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/backlight.h b/sys/compat/linuxkpi/common/include/linux/backlight.h index b3a07c4cdcaa..4f8f7440925a 100644 --- a/sys/compat/linuxkpi/common/include/linux/backlight.h +++ b/sys/compat/linuxkpi/common/include/linux/backlight.h @@ -24,12 +24,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_BACKLIGHT_H_ -#define _LINUX_BACKLIGHT_H_ +#ifndef _LINUXKPI_LINUX_BACKLIGHT_H_ +#define _LINUXKPI_LINUX_BACKLIGHT_H_ #include <linux/notifier.h> @@ -92,6 +90,23 @@ backlight_force_update(struct backlight_device *bd, int reason) } static inline int +backlight_get_brightness(struct backlight_device *bd) +{ + + return (bd->props.brightness); +} + +static inline int +backlight_device_set_brightness(struct backlight_device *bd, int brightness) +{ + + if (brightness > bd->props.max_brightness) + return (EINVAL); + bd->props.brightness = brightness; + return (bd->ops->update_status(bd)); +} + +static inline int backlight_enable(struct backlight_device *bd) { if (bd == NULL) @@ -109,4 +124,11 @@ backlight_disable(struct backlight_device *bd) return (backlight_update_status(bd)); } -#endif /* _LINUX_BACKLIGHT_H_ */ +static inline bool +backlight_is_blank(struct backlight_device *bd) +{ + + return (bd->props.power != 0/* FB_BLANK_UNBLANK */); +} + +#endif /* _LINUXKPI_LINUX_BACKLIGHT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/bcd.h b/sys/compat/linuxkpi/common/include/linux/bcd.h index 8a40da1a330b..385819910454 100644 --- a/sys/compat/linuxkpi/common/include/linux/bcd.h +++ b/sys/compat/linuxkpi/common/include/linux/bcd.h @@ -23,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BCD_H diff --git a/sys/compat/linuxkpi/common/include/linux/bitfield.h b/sys/compat/linuxkpi/common/include/linux/bitfield.h index a805c1bca5a1..8a91b0663f37 100644 --- a/sys/compat/linuxkpi/common/include/linux/bitfield.h +++ b/sys/compat/linuxkpi/common/include/linux/bitfield.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_BITFIELD_H -#define _LINUX_BITFIELD_H +#ifndef _LINUXKPI_LINUX_BITFIELD_H +#define _LINUXKPI_LINUX_BITFIELD_H #include <linux/types.h> #include <asm/byteorder.h> @@ -86,19 +84,58 @@ _leX_encode_bits(64) _leX_encode_bits(32) _leX_encode_bits(16) -static __inline void -le32p_replace_bits(uint32_t *p, uint32_t v, uint32_t f) -{ +#define _leXp_replace_bits(_n) \ + static __inline void \ + le ## _n ## p_replace_bits(uint ## _n ## _t *p, \ + uint ## _n ## _t v, uint ## _n ## _t f) \ + { \ + *p = (*p & ~(cpu_to_le ## _n(f))) | \ + le ## _n ## _encode_bits(v, f); \ + } + +_leXp_replace_bits(64) +_leXp_replace_bits(32) +_leXp_replace_bits(16) - *p = (*p & ~(cpu_to_le32(f))) | le32_encode_bits(v, f); -} +#define _uXp_replace_bits(_n) \ + static __inline void \ + u ## _n ## p_replace_bits(uint ## _n ## _t *p, \ + uint ## _n ## _t v, uint ## _n ## _t f) \ + { \ + *p = (*p & ~f) | u ## _n ## _encode_bits(v, f); \ + } + +_uXp_replace_bits(64) +_uXp_replace_bits(32) +_uXp_replace_bits(16) +_uXp_replace_bits(8) + +#define _uX_replace_bits(_n) \ + static __inline uint ## _n ## _t \ + u ## _n ## _replace_bits(uint ## _n ## _t p, \ + uint ## _n ## _t v, uint ## _n ## _t f) \ + { \ + return ((p & ~f) | u ## _n ## _encode_bits(v, f)); \ + } + +_uX_replace_bits(64) +_uX_replace_bits(32) +_uX_replace_bits(16) +_uX_replace_bits(8) #define __bf_shf(x) (__builtin_ffsll(x) - 1) +#define FIELD_FIT(_mask, _value) \ + (!(((typeof(_mask))(_value) << __bf_shf(_mask)) & ~(_mask))) + #define FIELD_PREP(_mask, _value) \ (((typeof(_mask))(_value) << __bf_shf(_mask)) & (_mask)) +/* Likely would need extra sanity checks compared to FIELD_PREP()? */ +#define FIELD_PREP_CONST(_mask, _value) \ + (((typeof(_mask))(_value) << __bf_shf(_mask)) & (_mask)) + #define FIELD_GET(_mask, _value) \ ((typeof(_mask))(((_value) & (_mask)) >> __bf_shf(_mask))) -#endif /* _LINUX_BITFIELD_H */ +#endif /* _LINUXKPI_LINUX_BITFIELD_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/bitmap.h b/sys/compat/linuxkpi/common/include/linux/bitmap.h index 4de94333c99f..f26a0f99dc03 100644 --- a/sys/compat/linuxkpi/common/include/linux/bitmap.h +++ b/sys/compat/linuxkpi/common/include/linux/bitmap.h @@ -22,12 +22,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_BITMAP_H_ -#define _LINUX_BITMAP_H_ +#ifndef _LINUXKPI_LINUX_BITMAP_H_ +#define _LINUXKPI_LINUX_BITMAP_H_ #include <linux/bitops.h> #include <linux/slab.h> @@ -266,6 +264,27 @@ bitmap_subset(const unsigned long *pa, return (1); } +static inline bool +bitmap_intersects(const unsigned long *pa, const unsigned long *pb, + unsigned size) +{ + const unsigned end = BIT_WORD(size); + const unsigned tail = size & (BITS_PER_LONG - 1); + unsigned i; + + for (i = 0; i != end; i++) + if (pa[i] & pb[i]) + return (true); + + if (tail) { + const unsigned long mask = BITMAP_LAST_WORD_MASK(tail); + + if (pa[end] & pb[end] & mask) + return (true); + } + return (false); +} + static inline void bitmap_complement(unsigned long *dst, const unsigned long *src, const unsigned int size) @@ -289,6 +308,49 @@ bitmap_copy(unsigned long *dst, const unsigned long *src, } static inline void +bitmap_to_arr32(uint32_t *dst, const unsigned long *src, unsigned int size) +{ + const unsigned int end = howmany(size, 32); + +#ifdef __LP64__ + unsigned int i = 0; + while (i < end) { + dst[i++] = (uint32_t)(*src & UINT_MAX); + if (i < end) + dst[i++] = (uint32_t)(*src >> 32); + src++; + } +#else + bitmap_copy((unsigned long *)dst, src, size); +#endif + if ((size % 32) != 0) /* Linux uses BITS_PER_LONG. Seems to be a bug */ + dst[end - 1] &= (uint32_t)(UINT_MAX >> (32 - (size % 32))); +} + +static inline void +bitmap_from_arr32(unsigned long *dst, const uint32_t *src, + unsigned int size) +{ + const unsigned int end = BIT_WORD(size); + const unsigned int tail = size & (BITS_PER_LONG - 1); + +#ifdef __LP64__ + const unsigned int end32 = howmany(size, 32); + unsigned int i = 0; + + while (i < end32) { + dst[i++/2] = (unsigned long) *(src++); + if (i < end32) + dst[i++/2] |= ((unsigned long) *(src++)) << 32; + } +#else + bitmap_copy(dst, (const unsigned long *)src, size); +#endif + if ((size % BITS_PER_LONG) != 0) + dst[end] &= BITMAP_LAST_WORD_MASK(tail); +} + +static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, const unsigned long *src2, const unsigned int size) { @@ -332,6 +394,40 @@ bitmap_xor(unsigned long *dst, const unsigned long *src1, dst[i] = src1[i] ^ src2[i]; } +static inline void +bitmap_shift_right(unsigned long *dst, const unsigned long *src, + unsigned int shift, unsigned int size) +{ + const unsigned int end = BITS_TO_LONGS(size); + const unsigned int tail = size & (BITS_PER_LONG - 1); + const unsigned long mask = BITMAP_LAST_WORD_MASK(tail); + const unsigned int off = BIT_WORD(shift); + const unsigned int rem = shift & (BITS_PER_LONG - 1); + unsigned long left, right; + unsigned int i, srcpos; + + for (i = 0, srcpos = off; srcpos < end; i++, srcpos++) { + right = src[srcpos]; + left = 0; + + if (srcpos == end - 1) + right &= mask; + + if (rem != 0) { + right >>= rem; + if (srcpos + 1 < end) { + left = src[srcpos + 1]; + if (srcpos + 1 == end - 1) + left &= mask; + left <<= (BITS_PER_LONG - rem); + } + } + dst[i] = left | right; + } + if (off != 0) + memset(dst + end - off, 0, off * sizeof(unsigned long)); +} + static inline unsigned long * bitmap_alloc(unsigned int size, gfp_t flags) { @@ -351,4 +447,4 @@ bitmap_free(const unsigned long *bitmap) kfree(bitmap); } -#endif /* _LINUX_BITMAP_H_ */ +#endif /* _LINUXKPI_LINUX_BITMAP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/bitops.h b/sys/compat/linuxkpi/common/include/linux/bitops.h index 0d7ab376e02d..a5a7abd55287 100644 --- a/sys/compat/linuxkpi/common/include/linux/bitops.h +++ b/sys/compat/linuxkpi/common/include/linux/bitops.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_BITOPS_H_ -#define _LINUX_BITOPS_H_ +#ifndef _LINUXKPI_LINUX_BITOPS_H_ +#define _LINUXKPI_LINUX_BITOPS_H_ #include <sys/param.h> #include <sys/types.h> @@ -39,13 +37,8 @@ #define BIT(nr) (1UL << (nr)) #define BIT_ULL(nr) (1ULL << (nr)) -#ifdef __LP64__ -#define BITS_PER_LONG 64 -#else -#define BITS_PER_LONG 32 -#endif - -#define BITS_PER_LONG_LONG 64 +#define BITS_PER_LONG (__SIZEOF_LONG__ * __CHAR_BIT__) +#define BITS_PER_LONG_LONG (__SIZEOF_LONG_LONG__ * __CHAR_BIT__) #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) #define BITMAP_LAST_WORD_MASK(n) (~0UL >> (BITS_PER_LONG - (n))) @@ -56,6 +49,7 @@ #define GENMASK_ULL(h, l) (((~0ULL) >> (BITS_PER_LONG_LONG - (h) - 1)) & ((~0ULL) << (l))) #define BITS_PER_BYTE 8 #define BITS_PER_TYPE(t) (sizeof(t) * BITS_PER_BYTE) +#define BITS_TO_BYTES(n) howmany((n), BITS_PER_BYTE) #define hweight8(x) bitcount((uint8_t)(x)) #define hweight16(x) bitcount16(x) @@ -63,10 +57,10 @@ #define hweight64(x) bitcount64(x) #define hweight_long(x) bitcountl(x) -#define HWEIGHT8(x) (bitcount8((uint8_t)(x)) + 1) -#define HWEIGHT16(x) (bitcount16(x) + 1) -#define HWEIGHT32(x) (bitcount32(x) + 1) -#define HWEIGHT64(x) (bitcount64(x) + 1) +#define HWEIGHT8(x) (__builtin_popcountg((uint8_t)(x))) +#define HWEIGHT16(x) (__builtin_popcountg((uint16_t)(x))) +#define HWEIGHT32(x) (__builtin_popcountg((uint32_t)(x))) +#define HWEIGHT64(x) (__builtin_popcountg((uint64_t)(x))) static inline int __ffs(int mask) @@ -86,6 +80,12 @@ __ffsl(long mask) return (ffsl(mask) - 1); } +static inline unsigned long +__ffs64(uint64_t mask) +{ + return (ffsll(mask) - 1); +} + static inline int __flsl(long mask) { @@ -283,6 +283,15 @@ find_next_zero_bit(const unsigned long *addr, unsigned long size, #define test_bit(i, a) \ !!(READ_ONCE(((volatile const unsigned long *)(a))[BIT_WORD(i)]) & BIT_MASK(i)) +static inline void +__assign_bit(long bit, volatile unsigned long *addr, bool value) +{ + if (value) + __set_bit(bit, addr); + else + __clear_bit(bit, addr); +} + static inline int test_and_clear_bit(long bit, volatile unsigned long *var) { @@ -420,4 +429,4 @@ sign_extend32(uint32_t value, int index) return ((int32_t)(value << shift) >> shift); } -#endif /* _LINUX_BITOPS_H_ */ +#endif /* _LINUXKPI_LINUX_BITOPS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/bottom_half.h b/sys/compat/linuxkpi/common/include/linux/bottom_half.h index 9f8dc02f2798..12b170845cbc 100644 --- a/sys/compat/linuxkpi/common/include/linux/bottom_half.h +++ b/sys/compat/linuxkpi/common/include/linux/bottom_half.h @@ -22,13 +22,11 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_BOTTOM_HALF_H_ -#define _LINUX_BOTTOM_HALF_H_ +#ifndef _LINUXKPI_LINUX_BOTTOM_HALF_H_ +#define _LINUXKPI_LINUX_BOTTOM_HALF_H_ extern void local_bh_enable(void); extern void local_bh_disable(void); -#endif /* _LINUX_BOTTOM_HALF_H_ */ +#endif /* _LINUXKPI_LINUX_BOTTOM_HALF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/bsearch.h b/sys/compat/linuxkpi/common/include/linux/bsearch.h index b8cf7b19b467..fb67109e4bba 100644 --- a/sys/compat/linuxkpi/common/include/linux/bsearch.h +++ b/sys/compat/linuxkpi/common/include/linux/bsearch.h @@ -26,13 +26,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_BSEARCH_H -#define __LKPI_LINUX_BSEARCH_H +#ifndef _LINUXKPI_LINUX_BSEARCH_H +#define _LINUXKPI_LINUX_BSEARCH_H #include <sys/libkern.h> -#endif /* __LKPI_LINUX_BSEARCH_H */ +#endif /* _LINUXKPI_LINUX_BSEARCH_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/build_bug.h b/sys/compat/linuxkpi/common/include/linux/build_bug.h new file mode 100644 index 000000000000..6a026376cfc8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/build_bug.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org> + * Copyright (c) 2018 Johannes Lundberg <johalun0@gmail.com> + * Copyright (c) 2021 The FreeBSD Foundation + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC + * + * Portions of this software were developed by Bjoern A. Zeeb + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_BUILD_BUG_H_ +#define _LINUXKPI_LINUX_BUILD_BUG_H_ + +#include <sys/param.h> + +#include <linux/compiler.h> + +/* + * BUILD_BUG_ON() can happen inside functions where _Static_assert() does not + * seem to work. Use old-schoold-ish CTASSERT from before commit + * a3085588a88fa58eb5b1eaae471999e1995a29cf but also make sure we do not + * end up with an unused typedef or variable. The compiler should optimise + * it away entirely. + */ +#define _O_CTASSERT(x) _O__CTASSERT(x, __LINE__) +#define _O__CTASSERT(x, y) _O___CTASSERT(x, y) +#define _O___CTASSERT(x, y) while (0) { \ + typedef char __assert_line_ ## y[(x) ? 1 : -1]; \ + __assert_line_ ## y _x __unused; \ + _x[0] = '\0'; \ +} + +#define BUILD_BUG() do { CTASSERT(0); } while (0) +#define BUILD_BUG_ON(x) do { _O_CTASSERT(!(x)) } while (0) +#define BUILD_BUG_ON_MSG(x, msg) BUILD_BUG_ON(x) +#define BUILD_BUG_ON_NOT_POWER_OF_2(x) BUILD_BUG_ON(!powerof2(x)) +#define BUILD_BUG_ON_INVALID(expr) while (0) { (void)(expr); } +#define BUILD_BUG_ON_ZERO(x) ((int)sizeof(struct { int:-((x) != 0); })) + +#define static_assert(x, ...) __static_assert(x, ##__VA_ARGS__, #x) +#define __static_assert(x, msg, ...) _Static_assert(x, msg) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/cache.h b/sys/compat/linuxkpi/common/include/linux/cache.h index 4d1d400152ff..b02b28d08ea9 100644 --- a/sys/compat/linuxkpi/common/include/linux/cache.h +++ b/sys/compat/linuxkpi/common/include/linux/cache.h @@ -25,17 +25,16 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_CACHE_H_ -#define _LINUX_CACHE_H_ +#ifndef _LINUXKPI_LINUX_CACHE_H_ +#define _LINUXKPI_LINUX_CACHE_H_ #include <sys/param.h> #define cache_line_size() CACHE_LINE_SIZE #define L1_CACHE_BYTES CACHE_LINE_SIZE +#define L1_CACHE_ALIGN(x) ALIGN(x, CACHE_LINE_SIZE) #define SMP_CACHE_BYTES L1_CACHE_BYTES -#endif /* _LINUX_CACHE_H_ */ +#endif /* _LINUXKPI_LINUX_CACHE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/capability.h b/sys/compat/linuxkpi/common/include/linux/capability.h new file mode 100644 index 000000000000..e3dacd4e9f15 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/capability.h @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2015 Rimvydas Jasinskas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * linux/capability.h + * + * Simple capable() priv_check helper + */ + +#ifndef _LINUXKPI_LINUX_CAPABILITY_H +#define _LINUXKPI_LINUX_CAPABILITY_H + +#include <sys/types.h> +#include <sys/proc.h> +#include <sys/priv.h> + +#define CAP_SYS_ADMIN PRIV_DRIVER +#define CAP_SYS_NICE PRIV_SCHED_SETPRIORITY + +static inline bool +capable(const int tryme) +{ + return (priv_check(curthread, tryme) == 0); +} + +#endif /* _LINUXKPI_LINUX_CAPABILITY_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/cc_platform.h b/sys/compat/linuxkpi/common/include/linux/cc_platform.h new file mode 100644 index 000000000000..1544c141614b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cc_platform.h @@ -0,0 +1,21 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_CC_PLATFORM_H_ +#define _LINUXKPI_LINUX_CC_PLATFORM_H_ + +#include <linux/types.h> +#include <linux/stddef.h> + +enum cc_attr { + CC_ATTR_MEM_ENCRYPT, + CC_ATTR_GUEST_MEM_ENCRYPT, +}; + +static inline bool +cc_platform_has(enum cc_attr attr __unused) +{ + + return (false); +} + +#endif /* _LINUXKPI_LINUX_CC_PLATFORM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cdev.h b/sys/compat/linuxkpi/common/include/linux/cdev.h index 39a65472e921..d989db14c2f8 100644 --- a/sys/compat/linuxkpi/common/include/linux/cdev.h +++ b/sys/compat/linuxkpi/common/include/linux/cdev.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_CDEV_H_ -#define _LINUX_CDEV_H_ +#ifndef _LINUXKPI_LINUX_CDEV_H_ +#define _LINUXKPI_LINUX_CDEV_H_ #include <linux/kobject.h> #include <linux/sysfs.h> @@ -57,6 +55,8 @@ struct linux_cdev { u_int siref; }; +struct linux_cdev *cdev_alloc(void); + static inline void cdev_init(struct linux_cdev *cdev, const struct file_operations *ops) { @@ -66,17 +66,6 @@ cdev_init(struct linux_cdev *cdev, const struct file_operations *ops) cdev->refs = 1; } -static inline struct linux_cdev * -cdev_alloc(void) -{ - struct linux_cdev *cdev; - - cdev = kzalloc(sizeof(struct linux_cdev), M_WAITOK); - kobject_init(&cdev->kobj, &linux_cdev_ktype); - cdev->refs = 1; - return (cdev); -} - static inline void cdev_put(struct linux_cdev *p) { @@ -154,4 +143,4 @@ void linux_cdev_device_del(struct linux_cdev *, struct device *); #define cdev linux_cdev -#endif /* _LINUX_CDEV_H_ */ +#endif /* _LINUXKPI_LINUX_CDEV_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cec.h b/sys/compat/linuxkpi/common/include/linux/cec.h new file mode 100644 index 000000000000..e0854d87d85c --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cec.h @@ -0,0 +1,8 @@ +/* Public domain */ + +#ifndef _LINUXKPI_LINUX_CEC_H_ +#define _LINUXKPI_LINUX_CEC_H_ + +#define CEC_PHYS_ADDR_INVALID 0xffff + +#endif /* _LINUXKPI_LINUX_CEC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cgroup.h b/sys/compat/linuxkpi/common/include/linux/cgroup.h new file mode 100644 index 000000000000..a9dd22fd0f4c --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cgroup.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_CGROUP_H_ +#define _LINUXKPI_LINUX_CGROUP_H_ + +#include <linux/kernel_stat.h> + +#endif /* _LINUXKPI_LINUX_CGROUP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/circ_buf.h b/sys/compat/linuxkpi/common/include/linux/circ_buf.h new file mode 100644 index 000000000000..53d7fa736ef8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/circ_buf.h @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_CIRC_BUF_H_ +#define _LINUXKPI_LINUX_CIRC_BUF_H_ + +#define CIRC_CNT(head,tail,size) (((head) - (tail)) & ((size) - 1)) +#define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head) + 1),(size)) + +#endif /* _LINUXKPI_LINUX_CIRC_BUF_H_ */ + diff --git a/sys/compat/linuxkpi/common/include/linux/cleanup.h b/sys/compat/linuxkpi/common/include/linux/cleanup.h new file mode 100644 index 000000000000..5bb146f082ed --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cleanup.h @@ -0,0 +1,93 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024-2025 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + */ + +#ifndef _LINUXKPI_LINUX_CLEANUP_H +#define _LINUXKPI_LINUX_CLEANUP_H + +#define __cleanup(_f) __attribute__((__cleanup__(_f))) + +/* + * Note: "_T" are special as they are exposed into common code for + * statements. Extra care should be taken when changing the code. + */ +#define DEFINE_GUARD(_n, _dt, _lock, _unlock) \ + \ + typedef _dt guard_ ## _n ## _t; \ + \ + static inline _dt \ + guard_ ## _n ## _create( _dt _T) \ + { \ + _dt c; \ + \ + c = ({ _lock; _T; }); \ + return (c); \ + } \ + \ + static inline void \ + guard_ ## _n ## _destroy(_dt *t) \ + { \ + _dt _T; \ + \ + _T = *t; \ + if (_T) { _unlock; }; \ + } + +/* We need to keep these calls unique. */ +#define guard(_n) \ + guard_ ## _n ## _t guard_ ## _n ## _ ## __COUNTER__ \ + __cleanup(guard_ ## _n ## _destroy) = guard_ ## _n ## _create + +#define DEFINE_FREE(_n, _t, _f) \ + static inline void \ + __free_ ## _n(void *p) \ + { \ + _t _T; \ + \ + _T = *(_t *)p; \ + _f; \ + } + +#define __free(_n) __cleanup(__free_##_n) + +/* + * Given this is a _0 version it should likely be broken up into parts. + * But we have no idead what a _1, _2, ... version would do different + * until we see a call. + * This is used for a not-real-type (rcu). We use a bool to "simulate" + * the lock held. Also _T still special, may not always be used, so tag + * with __unused (or better the LinuxKPI __maybe_unused). + */ +#define DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...) \ + \ + typedef struct { \ + bool lock; \ + __VA_ARGS__; \ + } guard_ ## _n ## _t; \ + \ + static inline void \ + guard_ ## _n ## _destroy(guard_ ## _n ## _t *_T) \ + { \ + if (_T->lock) { \ + _unlock; \ + } \ + } \ + \ + static inline guard_ ## _n ## _t \ + guard_ ## _n ## _create(void) \ + { \ + guard_ ## _n ## _t _tmp; \ + guard_ ## _n ## _t *_T __maybe_unused; \ + \ + _tmp.lock = true; \ + _T = &_tmp; \ + _lock; \ + return (_tmp); \ + } + +#endif /* _LINUXKPI_LINUX_CLEANUP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/clocksource.h b/sys/compat/linuxkpi/common/include/linux/clocksource.h index f775aa6bb329..3e7664c3e57e 100644 --- a/sys/compat/linuxkpi/common/include/linux/clocksource.h +++ b/sys/compat/linuxkpi/common/include/linux/clocksource.h @@ -25,14 +25,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_CLOCKSOURCE_H -#define _LINUX_CLOCKSOURCE_H +#ifndef _LINUXKPI_LINUX_CLOCKSOURCE_H +#define _LINUXKPI_LINUX_CLOCKSOURCE_H #include <asm/types.h> #define CLOCKSOURCE_MASK(x) ((u64)(-1ULL >> ((-(x)) & 63))) -#endif /* _LINUX_CLOCKSOURCE_H */ +#endif /* _LINUXKPI_LINUX_CLOCKSOURCE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/compat.h b/sys/compat/linuxkpi/common/include/linux/compat.h index 84b7b47a36dc..8a5a6918bb7c 100644 --- a/sys/compat/linuxkpi/common/include/linux/compat.h +++ b/sys/compat/linuxkpi/common/include/linux/compat.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_COMPAT_H_ -#define _LINUX_COMPAT_H_ +#ifndef _LINUXKPI_LINUX_COMPAT_H_ +#define _LINUXKPI_LINUX_COMPAT_H_ #include <sys/param.h> #include <sys/proc.h> @@ -43,19 +41,28 @@ extern int linux_alloc_current(struct thread *, int flags); extern void linux_free_current(struct task_struct *); extern struct domainset *linux_get_vm_domain_set(int node); +#define __current_unallocated(td) \ + __predict_false((td)->td_lkpi_task == NULL) + static inline void linux_set_current(struct thread *td) { - if (__predict_false(td->td_lkpi_task == NULL)) + if (__current_unallocated(td)) lkpi_alloc_current(td, M_WAITOK); } static inline int linux_set_current_flags(struct thread *td, int flags) { - if (__predict_false(td->td_lkpi_task == NULL)) + if (__current_unallocated(td)) return (lkpi_alloc_current(td, flags)); return (0); } -#endif /* _LINUX_COMPAT_H_ */ +#define compat_ptr(x) ((void *)(uintptr_t)x) +#define ptr_to_compat(x) ((uintptr_t)x) + +typedef void fpu_safe_exec_cb_t(void *ctx); +void lkpi_fpu_safe_exec(fpu_safe_exec_cb_t func, void *ctx); + +#endif /* _LINUXKPI_LINUX_COMPAT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/compiler.h b/sys/compat/linuxkpi/common/include/linux/compiler.h index e641b1b096c3..4146c829b936 100644 --- a/sys/compat/linuxkpi/common/include/linux/compiler.h +++ b/sys/compat/linuxkpi/common/include/linux/compiler.h @@ -26,13 +26,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_COMPILER_H_ -#define _LINUX_COMPILER_H_ +#ifndef _LINUXKPI_LINUX_COMPILER_H_ +#define _LINUXKPI_LINUX_COMPILER_H_ #include <sys/cdefs.h> +#include <sys/endian.h> #define __user #define __kernel @@ -50,7 +49,9 @@ #define __cond_lock(x,c) (c) #define __bitwise #define __devinitdata +#ifndef __deprecated #define __deprecated +#endif #define __init #define __initconst #define __devinit @@ -64,10 +65,29 @@ #undef __always_inline #define __always_inline inline #define noinline __noinline +#define noinline_for_stack __noinline #define ____cacheline_aligned __aligned(CACHE_LINE_SIZE) #define ____cacheline_aligned_in_smp __aligned(CACHE_LINE_SIZE) #define fallthrough /* FALLTHROUGH */ do { } while(0) +#if __has_attribute(__nonstring__) +#define __nonstring __attribute__((__nonstring__)) +#else +#define __nonstring +#endif +#if __has_attribute(__counted_by__) +#define __counted_by(_x) __attribute__((__counted_by__(_x))) +#else +#define __counted_by(_x) +#endif +#if BYTE_ORDER == LITTLE_ENDIAN +#define __counted_by_le(_x) __counted_by(_x) +#define __counted_by_be(_x) +#else +#define __counted_by_le(_x) +#define __counted_by_be(_x) __counted_by(_x) +#endif + #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #define typeof(x) __typeof(x) @@ -79,8 +99,11 @@ #define __printf(a,b) __printflike(a,b) +#define __diag_push() +#define __diag_pop() +#define __diag_ignore_all(...) + #define barrier() __asm__ __volatile__("": : :"memory") -#define smp_mb() mb() #define lower_32_bits(n) ((u32)(n)) #define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) @@ -88,18 +111,16 @@ #define ___PASTE(a,b) a##b #define __PASTE(a,b) ___PASTE(a,b) -#define ACCESS_ONCE(x) (*(volatile __typeof(x) *)&(x)) - #define WRITE_ONCE(x,v) do { \ barrier(); \ - ACCESS_ONCE(x) = (v); \ + (*(volatile __typeof(x) *)(uintptr_t)&(x)) = (v); \ barrier(); \ } while (0) #define READ_ONCE(x) ({ \ __typeof(x) __var = ({ \ barrier(); \ - ACCESS_ONCE(x); \ + (*(const volatile __typeof(x) *)&(x)); \ }); \ barrier(); \ __var; \ @@ -112,4 +133,15 @@ #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define __must_be_array(a) __same_type(a, &(a)[0]) -#endif /* _LINUX_COMPILER_H_ */ +#define sizeof_field(_s, _m) sizeof(((_s *)0)->_m) + +#define is_signed_type(t) ((t)-1 < (t)1) +#define is_unsigned_type(t) ((t)-1 > (t)1) + +#if __has_builtin(__builtin_dynamic_object_size) +#define __struct_size(_s) __builtin_dynamic_object_size(_s, 0) +#else +#define __struct_size(_s) __builtin_object_size(_s, 0) +#endif + +#endif /* _LINUXKPI_LINUX_COMPILER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/completion.h b/sys/compat/linuxkpi/common/include/linux/completion.h index 09d499309e5a..9f8bebb4cf82 100644 --- a/sys/compat/linuxkpi/common/include/linux/completion.h +++ b/sys/compat/linuxkpi/common/include/linux/completion.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_COMPLETION_H_ -#define _LINUX_COMPLETION_H_ +#ifndef _LINUXKPI_LINUX_COMPLETION_H_ +#define _LINUXKPI_LINUX_COMPLETION_H_ #include <linux/errno.h> @@ -62,8 +60,9 @@ struct completion { extern void linux_complete_common(struct completion *, int); extern int linux_wait_for_common(struct completion *, int); -extern int linux_wait_for_timeout_common(struct completion *, int, int); +extern unsigned long linux_wait_for_timeout_common(struct completion *, + unsigned long, int); extern int linux_try_wait_for_completion(struct completion *); extern int linux_completion_done(struct completion *); -#endif /* _LINUX_COMPLETION_H_ */ +#endif /* _LINUXKPI_LINUX_COMPLETION_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/console.h b/sys/compat/linuxkpi/common/include/linux/console.h new file mode 100644 index 000000000000..09f486203815 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/console.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_CONSOLE_H_ +#define _LINUXKPI_LINUX_CONSOLE_H_ + +#include <linux/types.h> + +static inline void +console_lock(void) +{ +} + +static inline int +console_trylock(void) +{ + return (1); +} + +static inline void +console_unlock(void) +{ +} + +static inline bool +vgacon_text_force(void) +{ + + return (false); +} + +#endif /* _LINUXKPI_LINUX_CONSOLE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/container_of.h b/sys/compat/linuxkpi/common/include/linux/container_of.h new file mode 100644 index 000000000000..7210d531b055 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/container_of.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2017 Matt Macy <mmacy@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_CONTAINER_OF_H +#define _LINUXKPI_LINUX_CONTAINER_OF_H + +#include <sys/stdint.h> + +#include <linux/build_bug.h> +#include <linux/stddef.h> + +#define container_of(ptr, type, member) \ +({ \ + const __typeof(((type *)0)->member) *__p = (ptr); \ + (type *)((uintptr_t)__p - offsetof(type, member)); \ +}) + +#define container_of_const(ptr, type, member) \ + _Generic(ptr, \ + const typeof(*(ptr)) *: \ + (const type *)container_of(ptr, type, member), \ + default: \ + container_of(ptr, type, member) \ + ) + +#define typeof_member(type, member) __typeof(((type *)0)->member) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/cpu.h b/sys/compat/linuxkpi/common/include/linux/cpu.h index 5be8f3d5a0d5..43ec3d66a2e3 100644 --- a/sys/compat/linuxkpi/common/include/linux/cpu.h +++ b/sys/compat/linuxkpi/common/include/linux/cpu.h @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_CPU_H -#define __LKPI_LINUX_CPU_H +#ifndef _LINUXKPI_LINUX_CPU_H +#define _LINUXKPI_LINUX_CPU_H #include <sys/types.h> #include <sys/systm.h> @@ -44,6 +42,8 @@ typedef cpuset_t cpumask_t; extern cpumask_t cpu_online_mask; +cpumask_t *lkpi_get_static_single_cpu_mask(int); + static __inline int cpumask_next(int cpuid, cpumask_t mask) { @@ -73,4 +73,6 @@ cpumask_set_cpu(int cpu, cpumask_t *mask) CPU_SET(cpu, mask); } -#endif /* __LKPI_LINUX_CPU_H */ +#define cpumask_of(_cpu) (lkpi_get_static_single_cpu_mask(_cpu)) + +#endif /* _LINUXKPI_LINUX_CPU_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/cpufeature.h b/sys/compat/linuxkpi/common/include/linux/cpufeature.h new file mode 100644 index 000000000000..746d1a7164a8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cpufeature.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_CPUFEATURE_H_ +#define _LINUXKPI_LINUX_CPUFEATURE_H_ + +/* + * Linux includes the following header. We don't have it on FreeBSD yet, so + * let's comment this include for now. It is still referenced here because + * sometimes, consumers of headers rely voluntarily or not on the namespace + * pollution. + */ +/* #include <linux/init.h> */ +#include <linux/mod_devicetable.h> +#include <asm/cpufeature.h> + +#endif /* _LINUXKPI_LINUX_CPUFEATURE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/crc32.h b/sys/compat/linuxkpi/common/include/linux/crc32.h index 6d43eb7b1859..e6d39fa7c5ff 100644 --- a/sys/compat/linuxkpi/common/include/linux/crc32.h +++ b/sys/compat/linuxkpi/common/include/linux/crc32.h @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_CRC32_H -#define __LKPI_LINUX_CRC32_H +#ifndef _LINUXKPI_LINUX_CRC32_H +#define _LINUXKPI_LINUX_CRC32_H #include <sys/gsb_crc32.h> @@ -42,4 +40,4 @@ crc32_le(uint32_t crc, const void *data, size_t len) return (crc32_raw(data, len, crc)); } -#endif /* __LKPI_LINUX_CRC32_H */ +#endif /* _LINUXKPI_LINUX_CRC32_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/dcache.h b/sys/compat/linuxkpi/common/include/linux/dcache.h index 1bafa3dbd1fe..992d6f7c2720 100644 --- a/sys/compat/linuxkpi/common/include/linux/dcache.h +++ b/sys/compat/linuxkpi/common/include/linux/dcache.h @@ -22,15 +22,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUX_DCACHE_H -#define __LINUX_DCACHE_H +#ifndef _LINUXKPI_LINUX_DCACHE_H +#define _LINUXKPI_LINUX_DCACHE_H + +#include <sys/vnode.h> -struct vnode; -struct pfs_node; +#include <fs/pseudofs/pseudofs.h> struct dentry { struct vnode *d_inode; @@ -43,4 +42,4 @@ d_inode(const struct dentry *dentry) return (dentry->d_inode); } -#endif /* __LINUX_DCACHE_H */ +#endif /* _LINUXKPI_LINUX_DCACHE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/debugfs.h b/sys/compat/linuxkpi/common/include/linux/debugfs.h index 406016d7e2c8..4d146e085a7b 100644 --- a/sys/compat/linuxkpi/common/include/linux/debugfs.h +++ b/sys/compat/linuxkpi/common/include/linux/debugfs.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org> * @@ -23,29 +23,102 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_DEBUGFS_H_ -#define _LINUX_DEBUGFS_H_ +#ifndef _LINUXKPI_LINUX_DEBUGFS_H_ +#define _LINUXKPI_LINUX_DEBUGFS_H_ #include <linux/fs.h> +#include <linux/module.h> #include <linux/seq_file.h> - #include <linux/types.h> -void debugfs_remove(struct dentry *dentry); +MALLOC_DECLARE(M_DFSINT); + +struct debugfs_reg32 { + char *name; + unsigned long offset; +}; + +struct debugfs_regset32 { + const struct debugfs_reg32 *regs; + int nregs; +}; + +struct debugfs_blob_wrapper { + void *data; + size_t size; +}; + +static inline bool +debugfs_initialized(void) +{ + + return (true); +} struct dentry *debugfs_create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops); + struct dentry *parent, void *data, + const struct file_operations *fops); + +/* TODO: We currently ignore the `file_size` argument. */ +struct dentry *debugfs_create_file_size(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + loff_t file_size); + +struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, +struct dentry *parent, void *data, + const struct file_operations *fops); + +struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + const struct file_operations *fops_ro, + const struct file_operations *fops_wo); struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, - const char *dest); + const char *dest); + +struct dentry *debugfs_lookup(const char *name, struct dentry *parent); + +void debugfs_remove(struct dentry *dentry); void debugfs_remove_recursive(struct dentry *dentry); -#endif +#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ + DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) +#define DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) \ + DEFINE_SIMPLE_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) + +void debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, + bool *value); +void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, + uint8_t *value); +void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, + uint16_t *value); +void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, + uint32_t *value); +void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, + uint64_t *value); +void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, + uint8_t *value); +void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, + uint16_t *value); +void debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, + uint32_t *value); +void debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, + uint64_t *value); +void debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent, + unsigned long *value); +void debugfs_create_atomic_t(const char *name, umode_t mode, struct dentry *parent, + atomic_t *value); +void debugfs_create_str(const char *name, umode_t mode, struct dentry *parent, + char **value); + +struct dentry *debugfs_create_blob(const char *name, umode_t mode, + struct dentry *parent, struct debugfs_blob_wrapper *value); + +#endif /* _LINUXKPI_LINUX_DEBUGFS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/delay.h b/sys/compat/linuxkpi/common/include/linux/delay.h index c13a1797adf9..f19d1a759c26 100644 --- a/sys/compat/linuxkpi/common/include/linux/delay.h +++ b/sys/compat/linuxkpi/common/include/linux/delay.h @@ -26,11 +26,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_DELAY_H_ -#define _LINUX_DELAY_H_ +#ifndef _LINUXKPI_LINUX_DELAY_H_ +#define _LINUXKPI_LINUX_DELAY_H_ #include <linux/jiffies.h> #include <sys/systm.h> @@ -86,4 +84,4 @@ fsleep(unsigned long us) usleep_range(us, us); } -#endif /* _LINUX_DELAY_H_ */ +#endif /* _LINUXKPI_LINUX_DELAY_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/devcoredump.h b/sys/compat/linuxkpi/common/include/linux/devcoredump.h index 4616fbb5a2ea..5fa06c6595a8 100644 --- a/sys/compat/linuxkpi/common/include/linux/devcoredump.h +++ b/sys/compat/linuxkpi/common/include/linux/devcoredump.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 The FreeBSD Foundation + * Copyright (c) 2020-2025 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_DEVCOREDUMP_H -#define __LKPI_LINUX_DEVCOREDUMP_H +#ifndef _LINUXKPI_LINUX_DEVCOREDUMP_H +#define _LINUXKPI_LINUX_DEVCOREDUMP_H #include <linux/slab.h> #include <linux/scatterlist.h> @@ -73,4 +71,11 @@ dev_coredumpsg(struct device *dev __unused, struct scatterlist *table, _lkpi_dev_coredumpsg_free(table); } -#endif /* __LKPI_LINUX_DEVCOREDUMP_H */ +static inline void +_devcd_free_sgtable(struct scatterlist *table) +{ + /* UNIMPLEMENTED */ + _lkpi_dev_coredumpsg_free(table); +} + +#endif /* _LINUXKPI_LINUX_DEVCOREDUMP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h index abafcd7ba5c4..c291133e2e0b 100644 --- a/sys/compat/linuxkpi/common/include/linux/device.h +++ b/sys/compat/linuxkpi/common/include/linux/device.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2021-2025 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,11 +29,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_DEVICE_H_ -#define _LINUX_DEVICE_H_ +#ifndef _LINUXKPI_LINUX_DEVICE_H_ +#define _LINUXKPI_LINUX_DEVICE_H_ #include <linux/err.h> #include <linux/types.h> @@ -37,22 +39,24 @@ #include <linux/sysfs.h> #include <linux/list.h> #include <linux/compiler.h> -#include <linux/types.h> #include <linux/module.h> #include <linux/workqueue.h> #include <linux/kdev_t.h> #include <linux/backlight.h> +#include <linux/pm.h> +#include <linux/idr.h> +#include <linux/overflow.h> +#include <linux/ratelimit.h> /* via linux/dev_printk.h */ +#include <linux/fwnode.h> #include <asm/atomic.h> #include <sys/bus.h> #include <sys/backlight.h> struct device; -struct fwnode_handle; struct class { const char *name; - struct module *owner; struct kobject kobj; devclass_t bsdclass; const struct dev_pm_ops *pm; @@ -64,6 +68,7 @@ struct class { struct dev_pm_ops { int (*prepare)(struct device *dev); + void (*complete)(struct device *dev); int (*suspend)(struct device *dev); int (*suspend_late)(struct device *dev); int (*resume)(struct device *dev); @@ -76,6 +81,7 @@ struct dev_pm_ops { int (*poweroff_late)(struct device *dev); int (*restore)(struct device *dev); int (*restore_early)(struct device *dev); + int (*suspend_noirq)(struct device *dev); int (*runtime_suspend)(struct device *dev); int (*runtime_resume)(struct device *dev); int (*runtime_idle)(struct device *dev); @@ -84,6 +90,9 @@ struct dev_pm_ops { struct device_driver { const char *name; const struct dev_pm_ops *pm; + + void (*shutdown) (struct device *); + void (*coredump) (struct device *); }; struct device_type { @@ -121,6 +130,8 @@ struct device { spinlock_t devres_lock; struct list_head devres_head; + + struct dev_pm_info power; }; extern struct device linux_root_device; @@ -180,14 +191,47 @@ show_class_attr_string(struct class *class, struct class_attribute_string class_attr_##_name = \ _CLASS_ATTR_STRING(_name, _mode, _str) -#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_crit(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_dbg(dev, fmt, ...) do { } while (0) #define dev_printk(lvl, dev, fmt, ...) \ - device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) + device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) + +#define dev_emerg(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_alert(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_crit(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_dbg(dev, fmt, ...) do { } while (0) + +#define dev_WARN(dev, fmt, ...) \ + device_printf((dev)->bsddev, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) + +#define dev_WARN_ONCE(dev, condition, fmt, ...) do { \ + static bool __dev_WARN_ONCE; \ + bool __ret_warn_on = (condition); \ + if (unlikely(__ret_warn_on)) { \ + if (!__dev_WARN_ONCE) { \ + __dev_WARN_ONCE = true; \ + device_printf((dev)->bsddev, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__); \ + } \ + } \ +} while (0) + +#define dev_info_once(dev, ...) do { \ + static bool __dev_info_once; \ + if (!__dev_info_once) { \ + __dev_info_once = true; \ + dev_info(dev, __VA_ARGS__); \ + } \ +} while (0) + +#define dev_warn_once(dev, ...) do { \ + static bool __dev_warn_once; \ + if (!__dev_warn_once) { \ + __dev_warn_once = 1; \ + dev_warn(dev, __VA_ARGS__); \ + } \ +} while (0) #define dev_err_once(dev, ...) do { \ static bool __dev_err_once; \ @@ -197,6 +241,14 @@ show_class_attr_string(struct class *class, } \ } while (0) +#define dev_dbg_once(dev, ...) do { \ + static bool __dev_dbg_once; \ + if (!__dev_dbg_once) { \ + __dev_dbg_once = 1; \ + dev_dbg(dev, __VA_ARGS__); \ + } \ +} while (0) + #define dev_err_ratelimited(dev, ...) do { \ static linux_ratelimit_t __ratelimited; \ if (linux_ratelimited(&__ratelimited)) \ @@ -209,6 +261,12 @@ show_class_attr_string(struct class *class, dev_warn(dev, __VA_ARGS__); \ } while (0) +#define dev_dbg_ratelimited(dev, ...) do { \ + static linux_ratelimit_t __ratelimited; \ + if (linux_ratelimited(&__ratelimited)) \ + dev_dbg(dev, __VA_ARGS__); \ +} while (0) + /* Public and LinuxKPI internal devres functions. */ void *lkpi_devres_alloc(void(*release)(struct device *, void *), size_t, gfp_t); void lkpi_devres_add(struct device *, void *); @@ -227,6 +285,23 @@ int lkpi_devres_destroy(struct device *, void(*release)(struct device *, void *) void lkpi_devres_release_free_list(struct device *); void lkpi_devres_unlink(struct device *, void *); void lkpi_devm_kmalloc_release(struct device *, void *); +void lkpi_devm_kfree(struct device *, const void *); +#define devm_kfree(_d, _p) lkpi_devm_kfree(_d, _p) + +static inline const char * +dev_driver_string(const struct device *dev) +{ + driver_t *drv; + const char *str = ""; + + if (dev->bsddev != NULL) { + drv = device_get_driver(dev->bsddev); + if (drv != NULL) + str = drv->name; + } + + return (str); +} static inline void * dev_get_drvdata(const struct device *dev) @@ -259,6 +334,13 @@ dev_name(const struct device *dev) return kobject_name(&dev->kobj); } +static inline bool +dev_is_removable(struct device *dev) +{ + + return (false); +} + #define dev_set_name(_dev, _fmt, ...) \ kobject_set_name(&(_dev)->kobj, (_fmt), ##__VA_ARGS__) @@ -270,6 +352,13 @@ put_device(struct device *dev) kobject_put(&dev->kobj); } +struct class *lkpi_class_create(const char *name); +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60400 +#define class_create(name) lkpi_class_create(name) +#else +#define class_create(owner, name) lkpi_class_create(name) +#endif + static inline int class_register(struct class *class) { @@ -294,6 +383,12 @@ static inline struct device *kobj_to_dev(struct kobject *kobj) return container_of(kobj, struct device, kobj); } +struct device *device_create(struct class *class, struct device *parent, + dev_t devt, void *drvdata, const char *fmt, ...); +struct device *device_create_groups_vargs(struct class *class, struct device *parent, + dev_t devt, void *drvdata, const struct attribute_group **groups, + const char *fmt, va_list args); + /* * Devices are registered and created for exporting to sysfs. Create * implies register and register assumes the device fields have been @@ -354,47 +449,6 @@ device_create_release(struct device *dev) } static inline struct device * -device_create_groups_vargs(struct class *class, struct device *parent, - dev_t devt, void *drvdata, const struct attribute_group **groups, - const char *fmt, va_list args) -{ - struct device *dev = NULL; - int retval = -ENODEV; - - if (class == NULL || IS_ERR(class)) - goto error; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - retval = -ENOMEM; - goto error; - } - - dev->devt = devt; - dev->class = class; - dev->parent = parent; - dev->groups = groups; - dev->release = device_create_release; - /* device_initialize() needs the class and parent to be set */ - device_initialize(dev); - dev_set_drvdata(dev, drvdata); - - retval = kobject_set_name_vargs(&dev->kobj, fmt, args); - if (retval) - goto error; - - retval = device_add(dev); - if (retval) - goto error; - - return dev; - -error: - put_device(dev); - return ERR_PTR(retval); -} - -static inline struct device * device_create_with_groups(struct class *class, struct device *parent, dev_t devt, void *drvdata, const struct attribute_group **groups, const char *fmt, ...) @@ -465,9 +519,9 @@ device_unregister(struct device *dev) dev->bsddev = NULL; if (bsddev != NULL && dev->bsddev_attached_here) { - mtx_lock(&Giant); + bus_topo_lock(); device_delete_child(device_get_parent(bsddev), bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); } put_device(dev); } @@ -481,15 +535,12 @@ device_del(struct device *dev) dev->bsddev = NULL; if (bsddev != NULL && dev->bsddev_attached_here) { - mtx_lock(&Giant); + bus_topo_lock(); device_delete_child(device_get_parent(bsddev), bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); } } -struct device *device_create(struct class *class, struct device *parent, - dev_t devt, void *drvdata, const char *fmt, ...); - static inline void device_destroy(struct class *class, dev_t devt) { @@ -514,10 +565,10 @@ device_release_driver(struct device *dev) dev_set_drvdata(dev, NULL); /* Do not call dev->release! */ - mtx_lock(&Giant); + bus_topo_lock(); if (device_is_attached(dev->bsddev)) device_detach(dev->bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); #endif } @@ -527,40 +578,45 @@ device_reprobe(struct device *dev) int error; device_release_driver(dev); - mtx_lock(&Giant); + bus_topo_lock(); error = device_probe_and_attach(dev->bsddev); - mtx_unlock(&Giant); + bus_topo_unlock(); return (-error); } -#define dev_pm_set_driver_flags(dev, flags) do { \ -} while (0) - static inline void -linux_class_kfree(struct class *class) +device_set_wakeup_enable(struct device *dev __unused, bool enable __unused) { - kfree(class); + /* + * XXX-BZ TODO This is used by wireless drivers supporting WoWLAN which + * we currently do not support. + */ } -static inline struct class * -class_create(struct module *owner, const char *name) +static inline int +device_wakeup_enable(struct device *dev) { - struct class *class; - int error; - class = kzalloc(sizeof(*class), M_WAITOK); - class->owner = owner; - class->name = name; - class->class_release = linux_class_kfree; - error = class_register(class); - if (error) { - kfree(class); - return (NULL); - } + device_set_wakeup_enable(dev, true); + return (0); +} - return (class); +static inline bool +device_iommu_mapped(struct device *dev __unused) +{ + return (false); +} + +#define dev_pm_set_driver_flags(dev, flags) do { \ +} while (0) + +static inline void +linux_class_kfree(struct class *class) +{ + + kfree(class); } static inline void @@ -629,10 +685,36 @@ devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) return (p); } +static inline void * +devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp) +{ + void *dst; + + if (len == 0) + return (NULL); + + dst = devm_kmalloc(dev, len, gfp); + if (dst != NULL) + memcpy(dst, src, len); + + return (dst); +} + #define devm_kzalloc(_dev, _size, _gfp) \ devm_kmalloc((_dev), (_size), (_gfp) | __GFP_ZERO) #define devm_kcalloc(_dev, _sizen, _size, _gfp) \ devm_kmalloc((_dev), ((_sizen) * (_size)), (_gfp) | __GFP_ZERO) -#endif /* _LINUX_DEVICE_H_ */ +int lkpi_devm_add_action(struct device *dev, void (*action)(void *), void *data); +#define devm_add_action(dev, action, data) \ + lkpi_devm_add_action(dev, action, data); +int lkpi_devm_add_action_or_reset(struct device *dev, void (*action)(void *), void *data); +#define devm_add_action_or_reset(dev, action, data) \ + lkpi_devm_add_action_or_reset(dev, action, data) + +int lkpi_devm_device_add_group(struct device *dev, const struct attribute_group *group); +#define devm_device_add_group(dev, group) \ + lkpi_devm_device_add_group(dev, group) + +#endif /* _LINUXKPI_LINUX_DEVICE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/device/driver.h b/sys/compat/linuxkpi/common/include/linux/device/driver.h new file mode 100644 index 000000000000..03b510c9c8b7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/device/driver.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Bjoern A. Zeeb + * Copyright (c) 2024 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. + */ + +#ifndef LINUXKPI_LINUX_DEVICE_DRIVER_H +#define LINUXKPI_LINUX_DEVICE_DRIVER_H + +#include <sys/cdefs.h> +#include <linux/module.h> + +#define module_driver(_drv, _regf, _unregf) \ +static inline int \ +__CONCAT(__CONCAT(_, _drv), _init)(void) \ +{ \ + return (_regf(&(_drv))); \ +} \ + \ +static inline void \ +__CONCAT(__CONCAT(_, _drv), _exit)(void) \ +{ \ + _unregf(&(_drv)); \ +} \ + \ +module_init(__CONCAT(__CONCAT(_, _drv), _init)); \ +module_exit(__CONCAT(__CONCAT(_, _drv), _exit)) + +#endif /* LINUXKPI_LINUX_DEVICE_DRIVER_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/dma-attrs.h b/sys/compat/linuxkpi/common/include/linux/dma-attrs.h index d424d16164a6..c9cfa9b621d5 100644 --- a/sys/compat/linuxkpi/common/include/linux/dma-attrs.h +++ b/sys/compat/linuxkpi/common/include/linux/dma-attrs.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_DMA_ATTR_H_ -#define _LINUX_DMA_ATTR_H_ +#ifndef _LINUXKPI_LINUX_DMA_ATTR_H_ +#define _LINUXKPI_LINUX_DMA_ATTR_H_ #define DMA_ATTR_WRITE_BARRIER (1 << 0) #define DMA_ATTR_WEAK_ORDERING (1 << 1) @@ -53,4 +51,4 @@ init_dma_attrs(struct dma_attrs *attrs) attrs->flags = 0; } -#endif /* _LINUX_DMA_ATTR_H_ */ +#endif /* _LINUXKPI_LINUX_DMA_ATTR_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/dma-buf-map.h b/sys/compat/linuxkpi/common/include/linux/dma-buf-map.h new file mode 100644 index 000000000000..567ce3b072b3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/dma-buf-map.h @@ -0,0 +1,91 @@ +/* Public domain. */ + +#ifndef _LINUX_DMA_BUF_MAP_H +#define _LINUX_DMA_BUF_MAP_H + +#include <linux/io.h> +#include <linux/string.h> + +struct dma_buf_map { + union { + void *vaddr_iomem; + void *vaddr; + }; + bool is_iomem; +}; + +static inline void +dma_buf_map_incr(struct dma_buf_map *dbm, size_t n) +{ + if (dbm->is_iomem) + dbm->vaddr_iomem += n; + else + dbm->vaddr += n; +} + +static inline void +dma_buf_map_memcpy_to(struct dma_buf_map *dbm, const void *src, size_t len) +{ + if (dbm->is_iomem) + memcpy_toio(dbm->vaddr_iomem, src, len); + else + memcpy(dbm->vaddr, src, len); +} + +static inline bool +dma_buf_map_is_null(const struct dma_buf_map *dbm) +{ + if (dbm->is_iomem) + return (dbm->vaddr_iomem == NULL); + else + return (dbm->vaddr == NULL); +} + +static inline bool +dma_buf_map_is_set(const struct dma_buf_map *dbm) +{ + if (dbm->is_iomem) + return (dbm->vaddr_iomem != NULL); + else + return (dbm->vaddr != NULL); +} + +static inline bool +dma_buf_map_is_equal( + const struct dma_buf_map *dbm_a, const struct dma_buf_map *dbm_b) +{ + if (dbm_a->is_iomem != dbm_b->is_iomem) + return (false); + + if (dbm_a->is_iomem) + return (dbm_a->vaddr_iomem == dbm_b->vaddr_iomem); + else + return (dbm_a->vaddr == dbm_b->vaddr); +} + +static inline void +dma_buf_map_clear(struct dma_buf_map *dbm) +{ + if (dbm->is_iomem) { + dbm->vaddr_iomem = NULL; + dbm->is_iomem = false; + } else { + dbm->vaddr = NULL; + } +} + +static inline void +dma_buf_map_set_vaddr_iomem(struct dma_buf_map *dbm, void *addr) +{ + dbm->vaddr_iomem = addr; + dbm->is_iomem = true; +} + +static inline void +dma_buf_map_set_vaddr(struct dma_buf_map *dbm, void *addr) +{ + dbm->vaddr = addr; + dbm->is_iomem = false; +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h index c86a24d1270a..2d8e1196d3d3 100644 --- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h +++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_DMA_MAPPING_H_ -#define _LINUX_DMA_MAPPING_H_ +#ifndef _LINUXKPI_LINUX_DMA_MAPPING_H_ +#define _LINUXKPI_LINUX_DMA_MAPPING_H_ #include <linux/types.h> #include <linux/device.h> @@ -45,6 +43,7 @@ #include <vm/vm.h> #include <vm/vm_page.h> +#include <vm/uma_align_mask.h> #include <vm/pmap.h> #include <machine/bus.h> @@ -95,14 +94,21 @@ int linux_dma_tag_init(struct device *, u64); int linux_dma_tag_init_coherent(struct device *, u64); void *linux_dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag); -dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len); -void linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t size); +void *linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); +dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len); /* backward compat */ +dma_addr_t lkpi_dma_map_phys(struct device *, vm_paddr_t, size_t, + enum dma_data_direction, unsigned long); +void linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t size); /* backward compat */ +void lkpi_dma_unmap(struct device *, dma_addr_t, size_t, + enum dma_data_direction, unsigned long); int linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction dir __unused, + int nents, enum dma_data_direction direction, unsigned long attrs __unused); void linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, - int nents __unused, enum dma_data_direction dir __unused, + int nents __unused, enum dma_data_direction direction, unsigned long attrs __unused); +void linuxkpi_dma_sync(struct device *, dma_addr_t, size_t, bus_dmasync_op_t); static inline int dma_supported(struct device *dev, u64 dma_mask) @@ -158,27 +164,30 @@ dma_zalloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, return (dma_alloc_coherent(dev, size, dma_handle, flag | __GFP_ZERO)); } +static inline void * +dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flag) +{ + + return (linuxkpi_dmam_alloc_coherent(dev, size, dma_handle, flag)); +} + static inline void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr) { - linux_dma_unmap(dev, dma_addr, size); - kmem_free((vm_offset_t)cpu_addr, size); + lkpi_dma_unmap(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0); + kmem_free(cpu_addr, size); } -#define dma_map_single_attrs(dev, ptr, size, dir, attrs) \ - linux_dma_map_phys(dev, vtophys(ptr), size) - -#define dma_unmap_single_attrs(dev, dma_addr, size, dir, attrs) \ - linux_dma_unmap(dev, dma_addr, size) - static inline dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page, size_t offset, - size_t size, enum dma_data_direction dir, unsigned long attrs) + size_t size, enum dma_data_direction direction, unsigned long attrs) { - return (linux_dma_map_phys(dev, VM_PAGE_TO_PHYS(page) + offset, size)); + return (lkpi_dma_map_phys(dev, page_to_phys(page) + offset, size, + direction, attrs)); } /* linux_dma_(un)map_sg_attrs does not support attrs yet */ @@ -193,7 +202,8 @@ dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction) { - return (linux_dma_map_phys(dev, VM_PAGE_TO_PHYS(page) + offset, size)); + return (lkpi_dma_map_phys(dev, page_to_phys(page) + offset, size, + direction, 0)); } static inline void @@ -201,13 +211,46 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction) { - linux_dma_unmap(dev, dma_address, size); + lkpi_dma_unmap(dev, dma_address, size, direction, 0); +} + +static inline dma_addr_t +dma_map_resource(struct device *dev, phys_addr_t paddr, size_t size, + enum dma_data_direction direction, unsigned long attrs) +{ + return (lkpi_dma_map_phys(dev, paddr, size, direction, attrs)); } static inline void -dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, +dma_unmap_resource(struct device *dev, dma_addr_t dma, size_t size, + enum dma_data_direction direction, unsigned long attrs) +{ + lkpi_dma_unmap(dev, dma, size, direction, attrs); +} + +static inline void +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma, size_t size, enum dma_data_direction direction) { + bus_dmasync_op_t op; + + switch (direction) { + case DMA_BIDIRECTIONAL: + op = BUS_DMASYNC_POSTREAD; + linuxkpi_dma_sync(dev, dma, size, op); + op = BUS_DMASYNC_PREREAD; + break; + case DMA_TO_DEVICE: + op = BUS_DMASYNC_POSTWRITE; + break; + case DMA_FROM_DEVICE: + op = BUS_DMASYNC_POSTREAD; + break; + default: + return; + } + + linuxkpi_dma_sync(dev, dma, size, op); } static inline void @@ -218,40 +261,66 @@ dma_sync_single(struct device *dev, dma_addr_t addr, size_t size, } static inline void -dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, +dma_sync_single_for_device(struct device *dev, dma_addr_t dma, size_t size, enum dma_data_direction direction) { + bus_dmasync_op_t op; + + switch (direction) { + case DMA_BIDIRECTIONAL: + op = BUS_DMASYNC_PREWRITE; + break; + case DMA_TO_DEVICE: + op = BUS_DMASYNC_PREREAD; + break; + case DMA_FROM_DEVICE: + op = BUS_DMASYNC_PREWRITE; + break; + default: + return; + } + + linuxkpi_dma_sync(dev, dma, size, op); } +/* (20250329) These four seem to be unused code. */ static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } static inline void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } static inline void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, int direction) + unsigned long offset, size_t size, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } static inline void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, int direction) + unsigned long offset, size_t size, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } +#define DMA_MAPPING_ERROR (~(dma_addr_t)0) + static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { - return (dma_addr == 0); + if (dma_addr == 0 || dma_addr == DMA_MAPPING_ERROR) + return (-ENOMEM); + return (0); } static inline unsigned int dma_set_max_seg_size(struct device *dev, @@ -260,6 +329,34 @@ static inline unsigned int dma_set_max_seg_size(struct device *dev, return (0); } +static inline dma_addr_t +_dma_map_single_attrs(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction, unsigned long attrs) +{ + return (lkpi_dma_map_phys(dev, vtophys(ptr), size, + direction, attrs)); +} + +static inline void +_dma_unmap_single_attrs(struct device *dev, dma_addr_t dma, size_t size, + enum dma_data_direction direction, unsigned long attrs) +{ + lkpi_dma_unmap(dev, dma, size, direction, attrs); +} + +static inline size_t +dma_max_mapping_size(struct device *dev) +{ + + return (SCATTERLIST_MAX_SEGMENT); +} + +#define dma_map_single_attrs(dev, ptr, size, dir, attrs) \ + _dma_map_single_attrs(dev, ptr, size, dir, 0) + +#define dma_unmap_single_attrs(dev, dma_addr, size, dir, attrs) \ + _dma_unmap_single_attrs(dev, dma_addr, size, dir, 0) + #define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0) #define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0) #define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0) @@ -272,7 +369,31 @@ static inline unsigned int dma_set_max_seg_size(struct device *dev, #define dma_unmap_len(p, name) ((p)->name) #define dma_unmap_len_set(p, name, v) (((p)->name) = (v)) -extern int uma_align_cache; -#define dma_get_cache_alignment() uma_align_cache +#define dma_get_cache_alignment() (uma_get_cache_align_mask() + 1) + + +static inline int +dma_map_sgtable(struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir, + unsigned long attrs) +{ + int nents; + + nents = dma_map_sg_attrs(dev, sgt->sgl, sgt->nents, dir, attrs); + if (nents < 0) + return (nents); + sgt->nents = nents; + return (0); +} + +static inline void +dma_unmap_sgtable(struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir, + unsigned long attrs) +{ + + dma_unmap_sg_attrs(dev, sgt->sgl, sgt->nents, dir, attrs); +} + -#endif /* _LINUX_DMA_MAPPING_H_ */ +#endif /* _LINUXKPI_LINUX_DMA_MAPPING_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/dmapool.h b/sys/compat/linuxkpi/common/include/linux/dmapool.h index 60353ede6a82..8501a32e30b7 100644 --- a/sys/compat/linuxkpi/common/include/linux/dmapool.h +++ b/sys/compat/linuxkpi/common/include/linux/dmapool.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_DMAPOOL_H_ -#define _LINUX_DMAPOOL_H_ +#ifndef _LINUXKPI_LINUX_DMAPOOL_H_ +#define _LINUXKPI_LINUX_DMAPOOL_H_ #include <linux/types.h> #include <linux/io.h> @@ -102,4 +100,4 @@ dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma_addr) linux_dma_pool_free(pool, vaddr, dma_addr); } -#endif /* _LINUX_DMAPOOL_H_ */ +#endif /* _LINUXKPI_LINUX_DMAPOOL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/dmi.h b/sys/compat/linuxkpi/common/include/linux/dmi.h index 6e450e156b73..d9760ee0324f 100644 --- a/sys/compat/linuxkpi/common/include/linux/dmi.h +++ b/sys/compat/linuxkpi/common/include/linux/dmi.h @@ -24,16 +24,20 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUX_DMI_H__ -#define __LINUX_DMI_H__ +#ifndef __LINUXKPI_LINUX_DMI_H__ +#define __LINUXKPI_LINUX_DMI_H__ #include <sys/types.h> #include <linux/mod_devicetable.h> +struct dmi_header { + uint8_t type; + uint8_t length; + uint16_t handle; +}; + int linux_dmi_check_system(const struct dmi_system_id *); bool linux_dmi_match(enum dmi_field, const char *); const struct dmi_system_id *linux_dmi_first_match(const struct dmi_system_id *); @@ -44,4 +48,11 @@ const char *linux_dmi_get_system_info(int); #define dmi_first_match(sysid) linux_dmi_first_match(sysid) #define dmi_get_system_info(sysid) linux_dmi_get_system_info(sysid) -#endif /* __LINUX_DMI_H__ */ +static inline int +dmi_walk(void (*callbackf)(const struct dmi_header *, void *), void *arg) +{ + + return (-ENXIO); +} + +#endif /* __LINUXKPI_LINUX_DMI_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/dynamic_debug.h b/sys/compat/linuxkpi/common/include/linux/dynamic_debug.h new file mode 100644 index 000000000000..12915eec3b68 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/dynamic_debug.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_DYNAMIC_DEBUG_H +#define _LINUXKPI_LINUX_DYNAMIC_DEBUG_H + +#define DECLARE_DYNDBG_CLASSMAP(a, b, c, ...) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/efi.h b/sys/compat/linuxkpi/common/include/linux/efi.h new file mode 100644 index 000000000000..aa33371bd0e8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/efi.h @@ -0,0 +1,68 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_EFI_H_ +#define _LINUXKPI_LINUX_EFI_H_ + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/linker.h> +#include <sys/systm.h> + +#include <machine/md_var.h> +#include <machine/metadata.h> + +#define EFI_BOOT 0 + +static inline bool +__efi_enabled(int feature) +{ + bool enabled = false; + + switch (feature) { + case EFI_BOOT: +#ifdef __amd64__ + /* Use cached value on amd64 */ + enabled = efi_boot; +#elif defined(MODINFOMD_EFI_MAP) + enabled = preload_search_info(preload_kmdp, + MODINFO_METADATA | MODINFOMD_EFI_MAP) != NULL; +#endif + break; + default: + break; + } + + return (enabled); +} + +#define efi_enabled(x) ({ \ + _Static_assert((x) == EFI_BOOT, "unsupported feature"); \ + __efi_enabled(x); \ +}) + +#endif /* _LINUXKPI_LINUX_EFI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/err.h b/sys/compat/linuxkpi/common/include/linux/err.h index 40a8ba82dfda..3d19949e641e 100644 --- a/sys/compat/linuxkpi/common/include/linux/err.h +++ b/sys/compat/linuxkpi/common/include/linux/err.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_ERR_H_ -#define _LINUX_ERR_H_ +#ifndef _LINUXKPI_LINUX_ERR_H_ +#define _LINUXKPI_LINUX_ERR_H_ #include <sys/types.h> @@ -80,4 +78,4 @@ PTR_ERR_OR_ZERO(const void *ptr) #define PTR_RET(p) PTR_ERR_OR_ZERO(p) -#endif /* _LINUX_ERR_H_ */ +#endif /* _LINUXKPI_LINUX_ERR_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/errno.h b/sys/compat/linuxkpi/common/include/linux/errno.h index efdde9a7a72a..d634675d43d0 100644 --- a/sys/compat/linuxkpi/common/include/linux/errno.h +++ b/sys/compat/linuxkpi/common/include/linux/errno.h @@ -25,15 +25,15 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_ERRNO_H_ -#define _LINUX_ERRNO_H_ +#ifndef _LINUXKPI_LINUX_ERRNO_H_ +#define _LINUXKPI_LINUX_ERRNO_H_ #include <sys/errno.h> #define EBADRQC 56 /* Bad request code */ +#define EBADSLT 57 /* Invalid slot */ +#define ENOKEY 126 /* Required key not available */ #define ECHRNG EDOM #define ETIME ETIMEDOUT @@ -44,6 +44,7 @@ #define ERESTARTSYS 512 #define ENOTSUPP EOPNOTSUPP #define ENONET EHOSTDOWN +#define EHWPOISON 133 /* Memory page hardware error */ /* * The error numbers below are arbitrary and do not resemble the numbers @@ -64,5 +65,9 @@ #define EIOCBQUEUED 529 #define ERFKILL 530 #define EBADE 531 +#define ENOMEDIUM 532 +#define ENOSR 533 +#define ELNRNG 534 +#define ENAVAIL 535 -#endif /* _LINUX_ERRNO_H_ */ +#endif /* _LINUXKPI_LINUX_ERRNO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/etherdevice.h b/sys/compat/linuxkpi/common/include/linux/etherdevice.h index 9062cd562347..b9a4951de8ac 100644 --- a/sys/compat/linuxkpi/common/include/linux/etherdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/etherdevice.h @@ -21,13 +21,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_ETHERDEVICE -#define _LINUX_ETHERDEVICE +#ifndef _LINUXKPI_LINUX_ETHERDEVICE_H_ +#define _LINUXKPI_LINUX_ETHERDEVICE_H_ #include <linux/types.h> +#include <linux/device.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> #include <sys/random.h> #include <sys/libkern.h> @@ -54,19 +55,27 @@ struct ethtool_modinfo { static inline bool is_zero_ether_addr(const u8 * addr) { - return ((addr[0] + addr[1] + addr[2] + addr[3] + addr[4] + addr[5]) == 0x00); + return ((addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == + 0x00); +} + +static inline bool +is_unicast_ether_addr(const u8 * addr) +{ + return ((addr[0] & 0x01) == 0x00); } static inline bool is_multicast_ether_addr(const u8 * addr) { - return (0x01 & addr[0]); + return ((addr[0] & 0x01) == 0x01); } static inline bool is_broadcast_ether_addr(const u8 * addr) { - return ((addr[0] + addr[1] + addr[2] + addr[3] + addr[4] + addr[5]) == (6 * 0xff)); + return ((addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == + 0xff); } static inline bool @@ -107,7 +116,7 @@ eth_zero_addr(u8 *pa) } static inline void -random_ether_addr(u8 * dst) +random_ether_addr(u8 *dst) { arc4random_buf(dst, 6); @@ -115,4 +124,40 @@ random_ether_addr(u8 * dst) dst[0] |= 0x02; } -#endif /* _LINUX_ETHERDEVICE */ +static inline void +eth_random_addr(u8 *dst) +{ + + random_ether_addr(dst); +} + +static inline int +device_get_mac_address(struct device *dev, char *dst) +{ + + /* XXX get mac address from FDT? */ + return (-ENOENT); +} + +/* Returns network byte order. */ +static inline uint16_t +eth_type_trans(struct sk_buff *skb, struct net_device *dev) +{ + pr_debug("%s: TODO\n", __func__); + return (htons(ETHERTYPE_8023)); +} + +static inline void +eth_hw_addr_set(struct net_device *dev, const u8 *addr) +{ + pr_debug("%s: TODO (if we want to)\n", __func__); +} + +static inline int +eth_platform_get_mac_address(struct device *dev __unused, u8 *addr __unused) +{ + pr_debug("%s: TODO\n", __func__); + return (-ENODEV); +} + +#endif /* _LINUXKPI_LINUX_ETHERDEVICE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ethtool.h b/sys/compat/linuxkpi/common/include/linux/ethtool.h new file mode 100644 index 000000000000..f5567cd7ea40 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ethtool.h @@ -0,0 +1,57 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_ETHTOOL_H_ +#define _LINUXKPI_LINUX_ETHTOOL_H_ + +#include <linux/types.h> + +#define ETH_GSTRING_LEN (2 * IF_NAMESIZE) /* Increase if not large enough */ + +#define ETHTOOL_FWVERS_LEN 32 + +struct ethtool_stats { + uint8_t __dummy[0]; +}; + +enum ethtool_ss { + ETH_SS_STATS, +}; + +struct ethtool_drvinfo { + char driver[32]; + char version[32]; + char fw_version[ETHTOOL_FWVERS_LEN]; + char bus_info[32]; +}; + +struct net_device; +struct ethtool_ops { + void(*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); +}; + +#endif /* _LINUXKPI_LINUX_ETHTOOL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/eventpoll.h b/sys/compat/linuxkpi/common/include/linux/eventpoll.h new file mode 100644 index 000000000000..e77e6d689f86 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/eventpoll.h @@ -0,0 +1,45 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022, Jake Freeland <jfree@freebsd.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_EVENTPOLL_H_ +#define _LINUXKPI_LINUX_EVENTPOLL_H_ + +#include <sys/poll.h> + +#define EPOLLIN POLLIN +#define EPOLLPRI POLLPRI +#define EPOLLOUT POLLOUT +#define EPOLLERR POLLERR +#define EPOLLHUP POLLHUP +#define EPOLLNVAL POLLNVAL +#define EPOLLRDNORM POLLRDNORM +#define EPOLLRDBAND POLLRDBAND +#define EPOLLWRNORM POLLWRNORM +#define EPOLLWRBAND POLLWRBAND +#define EPOLLRDHUP POLLRDHUP + +#endif /* _LINUXKPI_LINUX_EVENTPOLL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/export.h b/sys/compat/linuxkpi/common/include/linux/export.h index 00d51114f774..f48bd6af45d3 100644 --- a/sys/compat/linuxkpi/common/include/linux/export.h +++ b/sys/compat/linuxkpi/common/include/linux/export.h @@ -21,11 +21,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_EXPORT_H -#define _LINUX_EXPORT_H +#ifndef _LINUXKPI_LINUX_EXPORT_H +#define _LINUXKPI_LINUX_EXPORT_H #define EXPORT_SYMBOL(name) #define EXPORT_SYMBOL_GPL(name) diff --git a/sys/compat/linuxkpi/common/include/linux/file.h b/sys/compat/linuxkpi/common/include/linux/file.h index 21b254211cfd..f6e988c2d88e 100644 --- a/sys/compat/linuxkpi/common/include/linux/file.h +++ b/sys/compat/linuxkpi/common/include/linux/file.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_FILE_H_ -#define _LINUX_FILE_H_ +#ifndef _LINUXKPI_LINUX_FILE_H_ +#define _LINUXKPI_LINUX_FILE_H_ #include <sys/param.h> #include <sys/file.h> @@ -45,7 +43,7 @@ struct linux_file; #undef file -extern struct fileops linuxfileops; +extern const struct fileops linuxfileops; static inline struct linux_file * linux_fget(unsigned int fd) @@ -53,8 +51,7 @@ linux_fget(unsigned int fd) struct file *file; /* lookup file pointer by file descriptor index */ - if (fget_unlocked(curthread->td_proc->p_fd, fd, - &cap_no_rights, &file) != 0) + if (fget_unlocked(curthread, fd, &cap_no_rights, &file) != 0) return (NULL); /* check if file handle really belongs to us */ @@ -89,8 +86,7 @@ put_unused_fd(unsigned int fd) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, - &cap_no_rights, &file) != 0) { + if (fget_unlocked(curthread, fd, &cap_no_rights, &file) != 0) { return; } /* @@ -109,8 +105,7 @@ fd_install(unsigned int fd, struct linux_file *filp) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, - &cap_no_rights, &file) != 0) { + if (fget_unlocked(curthread, fd, &cap_no_rights, &file) != 0) { filp->_file = NULL; } else { filp->_file = file; @@ -187,4 +182,4 @@ static inline struct fd fdget(unsigned int fd) #define file linux_file #define fget(...) linux_fget(__VA_ARGS__) -#endif /* _LINUX_FILE_H_ */ +#endif /* _LINUXKPI_LINUX_FILE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/fips.h b/sys/compat/linuxkpi/common/include/linux/fips.h new file mode 100644 index 000000000000..25c0c1fc1fa0 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/fips.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_FIPS_H +#define _LINUXKPI_LINUX_FIPS_H + +#define fips_enabled 0 + +#endif /* _LINUXKPI_LINUX_FIPS_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/firmware.h b/sys/compat/linuxkpi/common/include/linux/firmware.h index ada7d0d73edf..a6330ddafb55 100644 --- a/sys/compat/linuxkpi/common/include/linux/firmware.h +++ b/sys/compat/linuxkpi/common/include/linux/firmware.h @@ -2,6 +2,7 @@ * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2022 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_FIRMWARE_H @@ -56,6 +55,8 @@ int linuxkpi_request_firmware(const struct linuxkpi_firmware **, int linuxkpi_firmware_request_nowarn(const struct linuxkpi_firmware **, const char *, struct device *); void linuxkpi_release_firmware(const struct linuxkpi_firmware *); +int linuxkpi_request_partial_firmware_into_buf(const struct linuxkpi_firmware **, + const char *, struct device *, uint8_t *, size_t, size_t); static __inline int @@ -100,6 +101,16 @@ release_firmware(const struct linuxkpi_firmware *fw) linuxkpi_release_firmware(fw); } +static inline int +request_partial_firmware_into_buf(const struct linuxkpi_firmware **fw, + const char *fw_name, struct device *dev, void *buf, size_t buflen, + size_t offset) +{ + + return (linuxkpi_request_partial_firmware_into_buf(fw, fw_name, + dev, buf, buflen, offset)); +} + #define firmware linuxkpi_firmware #endif /* _LINUXKPI_LINUX_FIRMWARE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h index f1892352d598..f1568ad6282d 100644 --- a/sys/compat/linuxkpi/common/include/linux/fs.h +++ b/sys/compat/linuxkpi/common/include/linux/fs.h @@ -25,13 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_FS_H_ -#define _LINUX_FS_H_ +#ifndef _LINUXKPI_LINUX_FS_H_ +#define _LINUXKPI_LINUX_FS_H_ -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> @@ -43,6 +40,10 @@ #include <linux/semaphore.h> #include <linux/spinlock.h> #include <linux/dcache.h> +#include <linux/capability.h> +#include <linux/wait_bit.h> +#include <linux/kernel.h> +#include <linux/mutex.h> struct module; struct kiocb; @@ -149,6 +150,11 @@ struct file_operations { * an illegal seek error */ off_t (*llseek)(struct linux_file *, off_t, int); +/* + * Not supported in FreeBSD. That's ok, we never call it and it allows some + * drivers like DRM drivers to compile without changes. + */ + void (*show_fdinfo)(struct seq_file *, struct file *); #if 0 /* We do not support these methods. Don't permit them to compile. */ loff_t (*llseek)(struct file *, loff_t, int); @@ -248,6 +254,7 @@ nonseekable_open(struct inode *inode, struct file *filp) static inline int simple_open(struct inode *inode, struct file *filp) { + filp->private_data = inode->i_private; return 0; } @@ -262,12 +269,18 @@ get_file(struct linux_file *f) return (f); } +struct linux_file * linux_get_file_rcu(struct linux_file **f); +struct linux_file * get_file_active(struct linux_file **f); +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION < 60700 static inline bool get_file_rcu(struct linux_file *f) { return (refcount_acquire_if_not_zero( f->_file == NULL ? &f->f_count : &f->_file->f_count)); } +#else +#define get_file_rcu(f) linux_get_file_rcu(f) +#endif static inline struct inode * igrab(struct inode *inode) @@ -296,6 +309,18 @@ no_llseek(struct file *file, loff_t offset, int whence) } static inline loff_t +default_llseek(struct file *file, loff_t offset, int whence) +{ + return (no_llseek(file, offset, whence)); +} + +static inline loff_t +generic_file_llseek(struct file *file, loff_t offset, int whence) +{ + return (no_llseek(file, offset, whence)); +} + +static inline loff_t noop_llseek(struct linux_file *file, loff_t offset, int whence) { @@ -316,4 +341,85 @@ call_mmap(struct linux_file *file, struct vm_area_struct *vma) return (file->f_op->mmap(file, vma)); } -#endif /* _LINUX_FS_H_ */ +static inline void +i_size_write(struct inode *inode, loff_t i_size) +{ +} + +/* + * simple_read_from_buffer: copy data from kernel-space origin + * buffer into user-space destination buffer + * + * @dest: destination buffer + * @read_size: number of bytes to be transferred + * @ppos: starting transfer position pointer + * @orig: origin buffer + * @buf_size: size of destination and origin buffers + * + * Return value: + * On success, total bytes copied with *ppos incremented accordingly. + * On failure, negative value. + */ +static inline ssize_t +simple_read_from_buffer(void __user *dest, size_t read_size, loff_t *ppos, + void *orig, size_t buf_size) +{ + void *p, *read_pos = ((char *) orig) + *ppos; + size_t buf_remain = buf_size - *ppos; + + if (buf_remain < 0 || buf_remain > buf_size) + return -EINVAL; + + if (read_size > buf_remain) + read_size = buf_remain; + + /* + * XXX At time of commit only debugfs consumers could be + * identified. If others will use this function we may + * have to revise this: normally we would call copy_to_user() + * here but lindebugfs will return the result and the + * copyout is done elsewhere for us. + */ + p = memcpy(dest, read_pos, read_size); + if (p != NULL) + *ppos += read_size; + + return (read_size); +} + +MALLOC_DECLARE(M_LSATTR); + +#define __DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt, __wrfunc)\ +static inline int \ +__fops ## _open(struct inode *inode, struct file *filp) \ +{ \ + return (simple_attr_open(inode, filp, __get, __set, __fmt)); \ +} \ +static const struct file_operations __fops = { \ + .owner = THIS_MODULE, \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = simple_attr_read, \ + .write = __wrfunc, \ + .llseek = no_llseek \ +} + +#define DEFINE_SIMPLE_ATTRIBUTE(fops, get, set, fmt) \ + __DEFINE_SIMPLE_ATTRIBUTE(fops, get, set, fmt, simple_attr_write) +#define DEFINE_SIMPLE_ATTRIBUTE_SIGNED(fops, get, set, fmt) \ + __DEFINE_SIMPLE_ATTRIBUTE(fops, get, set, fmt, simple_attr_write_signed) + +int simple_attr_open(struct inode *inode, struct file *filp, + int (*get)(void *, uint64_t *), int (*set)(void *, uint64_t), + const char *fmt); + +int simple_attr_release(struct inode *inode, struct file *filp); + +ssize_t simple_attr_read(struct file *filp, char *buf, size_t read_size, loff_t *ppos); + +ssize_t simple_attr_write(struct file *filp, const char *buf, size_t write_size, loff_t *ppos); + +ssize_t simple_attr_write_signed(struct file *filp, const char *buf, + size_t write_size, loff_t *ppos); + +#endif /* _LINUXKPI_LINUX_FS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/fwnode.h b/sys/compat/linuxkpi/common/include/linux/fwnode.h new file mode 100644 index 000000000000..a1fbc1b6d6a3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/fwnode.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_FWNODE_H_ +#define _LINUXKPI_LINUX_FWNODE_H_ + +struct fwnode_handle { + struct fwnode_handle *secondary; +}; + +#endif /* _LINUXKPI_LINUX_FWNODE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/gcd.h b/sys/compat/linuxkpi/common/include/linux/gcd.h index bff28340cfae..5ca0540e5102 100644 --- a/sys/compat/linuxkpi/common/include/linux/gcd.h +++ b/sys/compat/linuxkpi/common/include/linux/gcd.h @@ -25,12 +25,10 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_GCD_H_ -#define _LINUX_GCD_H_ +#ifndef _LINUXKPI_LINUX_GCD_H_ +#define _LINUXKPI_LINUX_GCD_H_ static inline unsigned long gcd(unsigned long a, unsigned long b) diff --git a/sys/compat/linuxkpi/common/include/linux/gfp.h b/sys/compat/linuxkpi/common/include/linux/gfp.h index 1366e75ad26a..7a32e7862338 100644 --- a/sys/compat/linuxkpi/common/include/linux/gfp.h +++ b/sys/compat/linuxkpi/common/include/linux/gfp.h @@ -25,18 +25,16 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_GFP_H_ -#define _LINUX_GFP_H_ +#ifndef _LINUXKPI_LINUX_GFP_H_ +#define _LINUXKPI_LINUX_GFP_H_ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/systm.h> #include <sys/malloc.h> #include <linux/page.h> +#include <linux/topology.h> #include <vm/vm_param.h> #include <vm/vm_object.h> @@ -46,7 +44,7 @@ #define __GFP_NOWARN 0 #define __GFP_HIGHMEM 0 #define __GFP_ZERO M_ZERO -#define __GFP_NORETRY 0 +#define __GFP_NOMEMALLOC 0 #define __GFP_RECLAIM 0 #define __GFP_RECLAIMABLE 0 #define __GFP_RETRY_MAYFAIL 0 @@ -59,7 +57,8 @@ #define __GFP_KSWAPD_RECLAIM 0 #define __GFP_WAIT M_WAITOK #define __GFP_DMA32 (1U << 24) /* LinuxKPI only */ -#define __GFP_BITS_SHIFT 25 +#define __GFP_NORETRY (1U << 25) /* LinuxKPI only */ +#define __GFP_BITS_SHIFT 26 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1) #define __GFP_NOFAIL M_WAITOK @@ -71,6 +70,7 @@ #define GFP_HIGHUSER_MOVABLE M_WAITOK #define GFP_IOFS M_NOWAIT #define GFP_NOIO M_NOWAIT +#define GFP_NOFS M_NOWAIT #define GFP_DMA32 __GFP_DMA32 #define GFP_TEMPORARY M_NOWAIT #define GFP_NATIVE_MASK (M_NOWAIT | M_WAITOK | M_USE_RESERVE | M_ZERO) @@ -80,20 +80,19 @@ CTASSERT((__GFP_DMA32 & GFP_NATIVE_MASK) == 0); CTASSERT((__GFP_BITS_MASK & GFP_NATIVE_MASK) == GFP_NATIVE_MASK); -/* - * Resolve a page into a virtual address: - * - * NOTE: This function only works for pages allocated by the kernel. - */ -extern void *linux_page_address(struct page *); - -#define page_address(page) linux_page_address(page) +struct page_frag_cache { + void *va; + int pagecnt_bias; +}; /* * Page management for unmapped pages: */ -extern vm_page_t linux_alloc_pages(gfp_t flags, unsigned int order); -extern void linux_free_pages(vm_page_t page, unsigned int order); +struct page *linux_alloc_pages(gfp_t flags, unsigned int order); +void linux_free_pages(struct page *page, unsigned int order); +void *linuxkpi_page_frag_alloc(struct page_frag_cache *, size_t, gfp_t); +void linuxkpi_page_frag_free(void *); +void linuxkpi__page_frag_cache_drain(struct page *, size_t); static inline struct page * alloc_page(gfp_t flags) @@ -130,11 +129,19 @@ __free_page(struct page *page) linux_free_pages(page, 0); } +static inline struct page * +dev_alloc_pages(unsigned int order) +{ + return (linux_alloc_pages(GFP_ATOMIC, order)); +} + +struct folio *folio_alloc(gfp_t gfp, unsigned int order); + /* * Page management for mapped pages: */ -extern vm_offset_t linux_alloc_kmem(gfp_t flags, unsigned int order); -extern void linux_free_kmem(vm_offset_t, unsigned int order); +vm_offset_t linux_alloc_kmem(gfp_t flags, unsigned int order); +void linux_free_kmem(vm_offset_t, unsigned int order); static inline vm_offset_t get_zeroed_page(gfp_t flags) @@ -175,6 +182,27 @@ free_page(uintptr_t addr) linux_free_kmem(addr, 0); } +static inline void * +page_frag_alloc(struct page_frag_cache *pfc, size_t fragsz, gfp_t gfp) +{ + + return (linuxkpi_page_frag_alloc(pfc, fragsz, gfp)); +} + +static inline void +page_frag_free(void *addr) +{ + + linuxkpi_page_frag_free(addr); +} + +static inline void +__page_frag_cache_drain(struct page *page, size_t count) +{ + + linuxkpi__page_frag_cache_drain(page, count); +} + static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) { @@ -184,4 +212,4 @@ gfpflags_allow_blocking(const gfp_t gfp_flags) #define SetPageReserved(page) do { } while (0) /* NOP */ #define ClearPageReserved(page) do { } while (0) /* NOP */ -#endif /* _LINUX_GFP_H_ */ +#endif /* _LINUXKPI_LINUX_GFP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/gpf.h b/sys/compat/linuxkpi/common/include/linux/gpf.h new file mode 100644 index 000000000000..01e883a94728 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/gpf.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_GPF_H_ +#define _LINUXKPI_LINUX_GPF_H_ + +#include <linux/mmzone.h> + +#endif /* _LINUXKPI_LINUX_GPF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/hardirq.h b/sys/compat/linuxkpi/common/include/linux/hardirq.h index d338e11c5a6f..f79451dd0d35 100644 --- a/sys/compat/linuxkpi/common/include/linux/hardirq.h +++ b/sys/compat/linuxkpi/common/include/linux/hardirq.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_HARDIRQ_H_ -#define _LINUX_HARDIRQ_H_ +#ifndef _LINUXKPI_LINUX_HARDIRQ_H_ +#define _LINUXKPI_LINUX_HARDIRQ_H_ #include <linux/types.h> #include <linux/lockdep.h> @@ -40,4 +38,14 @@ #define synchronize_irq(irq) _intr_drain((irq)) -#endif /* _LINUX_HARDIRQ_H_ */ +/* + * FIXME: In the i915 driver's `intel_engine_cs.c` file, + * `synchronize_hardirq()` was replaced by `synchronize_rcu()` with the + * following comment: + * "Is it enough to wait that all cpu have context-switched?" + * + * See commit f6d50b7af554e21c380486d6f41c8537b265c777 in drm-kmod. + */ +#define synchronize_hardirq(irq) _intr_drain((irq)) + +#endif /* _LINUXKPI_LINUX_HARDIRQ_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/hash.h b/sys/compat/linuxkpi/common/include/linux/hash.h new file mode 100644 index 000000000000..c75814c96724 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/hash.h @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 NVIDIA corporation & affiliates. + * Copyright (c) 2013 François Tigeot + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_HASH_H_ +#define _LINUXKPI_LINUX_HASH_H_ + +#include <sys/hash.h> +#include <sys/param.h> +#include <sys/systm.h> + +#include <asm/types.h> + +#include <linux/bitops.h> + +static inline u64 +hash_64(u64 val, u8 bits) +{ + u64 ret; + u8 x; + + ret = bits; + + for (x = 0; x != sizeof(ret); x++) { + u64 chunk = (val >> (8 * x)) & 0xFF; + ret = HASHSTEP(ret, chunk); + } + return (ret >> (64 - bits)); +} + +static inline u32 +hash_32(u32 val, u8 bits) +{ + u32 ret; + u8 x; + + ret = bits; + + for (x = 0; x != sizeof(ret); x++) { + u32 chunk = (val >> (8 * x)) & 0xFF; + ret = HASHSTEP(ret, chunk); + } + return (ret >> (32 - bits)); +} + +#if BITS_PER_LONG == 64 +#define hash_long(...) hash_64(__VA_ARGS__) +#else +#define hash_long(...) hash_32(__VA_ARGS__) +#endif + +#endif /* _LINUXKPI_LINUX_HASH_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/hashtable.h b/sys/compat/linuxkpi/common/include/linux/hashtable.h new file mode 100644 index 000000000000..55755c354959 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/hashtable.h @@ -0,0 +1,183 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 NVIDIA corporation & affiliates. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_HASHTABLE_H +#define _LINUXKPI_LINUX_HASHTABLE_H + +#include <sys/param.h> +#include <sys/systm.h> + +#include <linux/hash.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/log2.h> +#include <linux/rcupdate.h> +#include <linux/rculist.h> + +#include <ck_queue.h> + +struct lkpi_hash_entry { + CK_LIST_ENTRY(lkpi_hash_entry) entry; +}; + +struct lkpi_hash_head { + CK_LIST_HEAD(, lkpi_hash_entry) head; +}; + +#define DEFINE_HASHTABLE(name, bits) \ + struct lkpi_hash_head name[1UL << (bits)] + +#define DEFINE_READ_MOSTLY_HASHTABLE(name, bits) \ + struct lkpi_hash_head name[1UL << (bits)] __read_mostly + +#define DECLARE_HASHTABLE(name, bits) \ + struct lkpi_hash_head name[1UL << (bits)] + +#define HASH_SIZE(name) ARRAY_SIZE(name) +#define HASH_BITS(name) ilog2(HASH_SIZE(name)) + +#define hash_min(...) \ + hash_long(__VA_ARGS__) + +static inline void +__hash_init(struct lkpi_hash_head *ht, unsigned long size) +{ + unsigned long x; + + for (x = 0; x != size; x++) + CK_LIST_INIT(&ht[x].head); +} + +#define hash_init(ht) \ + __hash_init(ht, HASH_SIZE(ht)) + +#define hash_add(...) \ + hash_add_rcu(__VA_ARGS__) + +static inline void +__hash_node_type_assert(struct hlist_node *node) +{ + /* + * Unfortunately Linux doesn't have an own type for the hash + * table node entries. The purpose of this function is simply + * to check the type of the passed argument. + */ + CTASSERT(sizeof(struct lkpi_hash_entry) == sizeof(*node)); +} + +#define hash_add_rcu(ht, node, key) do { \ + struct lkpi_hash_head *__head = &(ht)[hash_min(key, HASH_BITS(ht))]; \ + __hash_node_type_assert(node); \ + CK_LIST_INSERT_HEAD(&__head->head, \ + (struct lkpi_hash_entry *)(node), entry); \ +} while (0) + +static inline bool +hash_hashed(struct hlist_node *node) +{ + return (((struct lkpi_hash_entry *)node)->entry.cle_prev != NULL); +} + +static inline bool +__hash_empty(struct lkpi_hash_head *ht, unsigned long size) +{ + unsigned long x; + + for (x = 0; x != size; x++) { + if (!CK_LIST_EMPTY(&ht[x].head)) + return (false); + } + return (true); +} + +#define hash_empty(ht) \ + __hash_empty(ht, HASH_SIZE(ht)) + +#define hash_del(...) \ + hash_del_rcu(__VA_ARGS__) + +static inline void +hash_del_rcu(struct hlist_node *node) +{ + CK_LIST_REMOVE((struct lkpi_hash_entry *)node, entry); + memset(node, 0, sizeof(*node)); +} + +#define __hash_first(ht, type, member) ({ \ + const struct lkpi_hash_entry *__first = CK_LIST_FIRST(&(ht)->head); \ + __hash_node_type_assert(&((type *)0)->member); \ + (__first != NULL ? container_of((const void *)__first, type, member) : NULL); \ +}) + +#define __hash_next(obj, type, member) ({ \ + const struct lkpi_hash_entry *__next = \ + CK_LIST_NEXT((struct lkpi_hash_entry *)&(obj)->member, entry); \ + __hash_node_type_assert(&(obj)->member); \ + (__next != NULL ? container_of((const void *)__next, type, member) : NULL); \ +}) + +#define hash_for_each(...) \ + hash_for_each_rcu(__VA_ARGS__) + +#define hash_for_each_rcu(name, bkt, obj, member) \ + for ((bkt) = 0, (obj) = NULL; (obj) == NULL && \ + (bkt) != HASH_SIZE(name); (bkt)++) \ + for ((obj) = __hash_first(&(name)[bkt], \ + __typeof(*(obj)), member); \ + (obj) != NULL; \ + (obj) = __hash_next(obj, \ + __typeof(*(obj)), member)) + +#define hash_for_each_safe(name, bkt, tmp, obj, member) \ + for ((bkt) = 0, (obj) = NULL; (obj) == NULL && \ + (bkt) != HASH_SIZE(name); (bkt)++) \ + for ((obj) = __hash_first(&(name)[bkt], \ + __typeof(*(obj)), member); \ + (obj) != NULL && ((tmp) = &__hash_next(obj, \ + __typeof(*(obj)), member)->member, 1); \ + (obj) = container_of(tmp, __typeof(*(obj)), member)) + +#define hash_for_each_possible(...) \ + hash_for_each_possible_rcu(__VA_ARGS__) + +#define hash_for_each_possible_rcu_notrace(...) \ + hash_for_each_possible_rcu(__VA_ARGS__) + +#define hash_for_each_possible_rcu(name, obj, member, key) \ + for ((obj) = __hash_first(&(name)[hash_min(key, HASH_BITS(name))], \ + __typeof(*(obj)), member); \ + (obj) != NULL; \ + (obj) = __hash_next(obj, __typeof(*(obj)), member)) + +#define hash_for_each_possible_safe(name, obj, tmp, member, key) \ + for ((obj) = __hash_first(&(name)[hash_min(key, HASH_BITS(name))], \ + __typeof(*(obj)), member); \ + (obj) != NULL && ((tmp) = &__hash_next(obj, \ + __typeof(*(obj)), member)->member, 1); \ + (obj) = container_of(tmp, __typeof(*(obj)), member)) + +#endif /* _LINUXKPI_LINUX_HASHTABLE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/hdmi.h b/sys/compat/linuxkpi/common/include/linux/hdmi.h new file mode 100644 index 000000000000..e07578167d69 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/hdmi.h @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LINUX_HDMI_H_ +#define __LINUX_HDMI_H_ + +#include <linux/types.h> +#include <linux/device.h> + +enum hdmi_packet_type { + HDMI_PACKET_TYPE_NULL = 0x00, + HDMI_PACKET_TYPE_AUDIO_CLOCK_REGEN = 0x01, + HDMI_PACKET_TYPE_AUDIO_SAMPLE = 0x02, + HDMI_PACKET_TYPE_GENERAL_CONTROL = 0x03, + HDMI_PACKET_TYPE_ACP = 0x04, + HDMI_PACKET_TYPE_ISRC1 = 0x05, + HDMI_PACKET_TYPE_ISRC2 = 0x06, + HDMI_PACKET_TYPE_ONE_BIT_AUDIO_SAMPLE = 0x07, + HDMI_PACKET_TYPE_DST_AUDIO = 0x08, + HDMI_PACKET_TYPE_HBR_AUDIO_STREAM = 0x09, + HDMI_PACKET_TYPE_GAMUT_METADATA = 0x0a, + /* + enum hdmi_infoframe_type */ +}; + +enum hdmi_infoframe_type { + HDMI_INFOFRAME_TYPE_VENDOR = 0x81, + HDMI_INFOFRAME_TYPE_AVI = 0x82, + HDMI_INFOFRAME_TYPE_SPD = 0x83, + HDMI_INFOFRAME_TYPE_AUDIO = 0x84, + HDMI_INFOFRAME_TYPE_DRM = 0x87, +}; + +#define HDMI_IEEE_OUI 0x000c03 +#define HDMI_FORUM_IEEE_OUI 0xc45dd8 +#define HDMI_INFOFRAME_HEADER_SIZE 4 +#define HDMI_AVI_INFOFRAME_SIZE 13 +#define HDMI_SPD_INFOFRAME_SIZE 25 +#define HDMI_AUDIO_INFOFRAME_SIZE 10 +#define HDMI_DRM_INFOFRAME_SIZE 26 +#define HDMI_VENDOR_INFOFRAME_SIZE 4 + +#define HDMI_INFOFRAME_SIZE(type) \ + (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) + +struct hdmi_any_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; +}; + +enum hdmi_colorspace { + HDMI_COLORSPACE_RGB, + HDMI_COLORSPACE_YUV422, + HDMI_COLORSPACE_YUV444, + HDMI_COLORSPACE_YUV420, + HDMI_COLORSPACE_RESERVED4, + HDMI_COLORSPACE_RESERVED5, + HDMI_COLORSPACE_RESERVED6, + HDMI_COLORSPACE_IDO_DEFINED, +}; + +enum hdmi_scan_mode { + HDMI_SCAN_MODE_NONE, + HDMI_SCAN_MODE_OVERSCAN, + HDMI_SCAN_MODE_UNDERSCAN, + HDMI_SCAN_MODE_RESERVED, +}; + +enum hdmi_colorimetry { + HDMI_COLORIMETRY_NONE, + HDMI_COLORIMETRY_ITU_601, + HDMI_COLORIMETRY_ITU_709, + HDMI_COLORIMETRY_EXTENDED, +}; + +enum hdmi_picture_aspect { + HDMI_PICTURE_ASPECT_NONE, + HDMI_PICTURE_ASPECT_4_3, + HDMI_PICTURE_ASPECT_16_9, + HDMI_PICTURE_ASPECT_64_27, + HDMI_PICTURE_ASPECT_256_135, + HDMI_PICTURE_ASPECT_RESERVED, +}; + +enum hdmi_active_aspect { + HDMI_ACTIVE_ASPECT_16_9_TOP = 2, + HDMI_ACTIVE_ASPECT_14_9_TOP = 3, + HDMI_ACTIVE_ASPECT_16_9_CENTER = 4, + HDMI_ACTIVE_ASPECT_PICTURE = 8, + HDMI_ACTIVE_ASPECT_4_3 = 9, + HDMI_ACTIVE_ASPECT_16_9 = 10, + HDMI_ACTIVE_ASPECT_14_9 = 11, + HDMI_ACTIVE_ASPECT_4_3_SP_14_9 = 13, + HDMI_ACTIVE_ASPECT_16_9_SP_14_9 = 14, + HDMI_ACTIVE_ASPECT_16_9_SP_4_3 = 15, +}; + +enum hdmi_extended_colorimetry { + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601, + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709, + HDMI_EXTENDED_COLORIMETRY_S_YCC_601, + HDMI_EXTENDED_COLORIMETRY_OPYCC_601, + HDMI_EXTENDED_COLORIMETRY_OPRGB, + + /* The following EC values are only defined in CEA-861-F. */ + HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM, + HDMI_EXTENDED_COLORIMETRY_BT2020, + HDMI_EXTENDED_COLORIMETRY_RESERVED, +}; + +enum hdmi_quantization_range { + HDMI_QUANTIZATION_RANGE_DEFAULT, + HDMI_QUANTIZATION_RANGE_LIMITED, + HDMI_QUANTIZATION_RANGE_FULL, + HDMI_QUANTIZATION_RANGE_RESERVED, +}; + +/* non-uniform picture scaling */ +enum hdmi_nups { + HDMI_NUPS_UNKNOWN, + HDMI_NUPS_HORIZONTAL, + HDMI_NUPS_VERTICAL, + HDMI_NUPS_BOTH, +}; + +enum hdmi_ycc_quantization_range { + HDMI_YCC_QUANTIZATION_RANGE_LIMITED, + HDMI_YCC_QUANTIZATION_RANGE_FULL, +}; + +enum hdmi_content_type { + HDMI_CONTENT_TYPE_GRAPHICS, + HDMI_CONTENT_TYPE_PHOTO, + HDMI_CONTENT_TYPE_CINEMA, + HDMI_CONTENT_TYPE_GAME, +}; + +enum hdmi_metadata_type { + HDMI_STATIC_METADATA_TYPE1 = 0, +}; + +enum hdmi_eotf { + HDMI_EOTF_TRADITIONAL_GAMMA_SDR, + HDMI_EOTF_TRADITIONAL_GAMMA_HDR, + HDMI_EOTF_SMPTE_ST2084, + HDMI_EOTF_BT_2100_HLG, +}; + +struct hdmi_avi_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + bool itc; + unsigned char pixel_repeat; + enum hdmi_colorspace colorspace; + enum hdmi_scan_mode scan_mode; + enum hdmi_colorimetry colorimetry; + enum hdmi_picture_aspect picture_aspect; + enum hdmi_active_aspect active_aspect; + enum hdmi_extended_colorimetry extended_colorimetry; + enum hdmi_quantization_range quantization_range; + enum hdmi_nups nups; + unsigned char video_code; + enum hdmi_ycc_quantization_range ycc_quantization_range; + enum hdmi_content_type content_type; + unsigned short top_bar; + unsigned short bottom_bar; + unsigned short left_bar; + unsigned short right_bar; +}; + +/* DRM Infoframe as per CTA 861.G spec */ +struct hdmi_drm_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + enum hdmi_eotf eotf; + enum hdmi_metadata_type metadata_type; + struct { + u16 x, y; + } display_primaries[3]; + struct { + u16 x, y; + } white_point; + u16 max_display_mastering_luminance; + u16 min_display_mastering_luminance; + u16 max_cll; + u16 max_fall; +}; + +void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame); +ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame, + void *buffer, size_t size); +int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame); +int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame); +ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame, + void *buffer, size_t size); +int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame); +int hdmi_drm_infoframe_unpack_only(struct hdmi_drm_infoframe *frame, + const void *buffer, size_t size); + +enum hdmi_spd_sdi { + HDMI_SPD_SDI_UNKNOWN, + HDMI_SPD_SDI_DSTB, + HDMI_SPD_SDI_DVDP, + HDMI_SPD_SDI_DVHS, + HDMI_SPD_SDI_HDDVR, + HDMI_SPD_SDI_DVC, + HDMI_SPD_SDI_DSC, + HDMI_SPD_SDI_VCD, + HDMI_SPD_SDI_GAME, + HDMI_SPD_SDI_PC, + HDMI_SPD_SDI_BD, + HDMI_SPD_SDI_SACD, + HDMI_SPD_SDI_HDDVD, + HDMI_SPD_SDI_PMP, +}; + +struct hdmi_spd_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + char vendor[8]; + char product[16]; + enum hdmi_spd_sdi sdi; +}; + +int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame, + const char *vendor, const char *product); +ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe *frame, + void *buffer, size_t size); +int hdmi_spd_infoframe_check(struct hdmi_spd_infoframe *frame); + +enum hdmi_audio_coding_type { + HDMI_AUDIO_CODING_TYPE_STREAM, + HDMI_AUDIO_CODING_TYPE_PCM, + HDMI_AUDIO_CODING_TYPE_AC3, + HDMI_AUDIO_CODING_TYPE_MPEG1, + HDMI_AUDIO_CODING_TYPE_MP3, + HDMI_AUDIO_CODING_TYPE_MPEG2, + HDMI_AUDIO_CODING_TYPE_AAC_LC, + HDMI_AUDIO_CODING_TYPE_DTS, + HDMI_AUDIO_CODING_TYPE_ATRAC, + HDMI_AUDIO_CODING_TYPE_DSD, + HDMI_AUDIO_CODING_TYPE_EAC3, + HDMI_AUDIO_CODING_TYPE_DTS_HD, + HDMI_AUDIO_CODING_TYPE_MLP, + HDMI_AUDIO_CODING_TYPE_DST, + HDMI_AUDIO_CODING_TYPE_WMA_PRO, + HDMI_AUDIO_CODING_TYPE_CXT, +}; + +enum hdmi_audio_sample_size { + HDMI_AUDIO_SAMPLE_SIZE_STREAM, + HDMI_AUDIO_SAMPLE_SIZE_16, + HDMI_AUDIO_SAMPLE_SIZE_20, + HDMI_AUDIO_SAMPLE_SIZE_24, +}; + +enum hdmi_audio_sample_frequency { + HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM, + HDMI_AUDIO_SAMPLE_FREQUENCY_32000, + HDMI_AUDIO_SAMPLE_FREQUENCY_44100, + HDMI_AUDIO_SAMPLE_FREQUENCY_48000, + HDMI_AUDIO_SAMPLE_FREQUENCY_88200, + HDMI_AUDIO_SAMPLE_FREQUENCY_96000, + HDMI_AUDIO_SAMPLE_FREQUENCY_176400, + HDMI_AUDIO_SAMPLE_FREQUENCY_192000, +}; + +enum hdmi_audio_coding_type_ext { + /* Refer to Audio Coding Type (CT) field in Data Byte 1 */ + HDMI_AUDIO_CODING_TYPE_EXT_CT, + + /* + * The next three CXT values are defined in CEA-861-E only. + * They do not exist in older versions, and in CEA-861-F they are + * defined as 'Not in use'. + */ + HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC, + HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND, + + /* The following CXT values are only defined in CEA-861-F. */ + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC, + HDMI_AUDIO_CODING_TYPE_EXT_DRA, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND = 10, +}; + +struct hdmi_audio_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned char channels; + enum hdmi_audio_coding_type coding_type; + enum hdmi_audio_sample_size sample_size; + enum hdmi_audio_sample_frequency sample_frequency; + enum hdmi_audio_coding_type_ext coding_type_ext; + unsigned char channel_allocation; + unsigned char level_shift_value; + bool downmix_inhibit; + +}; + +int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame); +ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, + void *buffer, size_t size); +ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, + void *buffer, size_t size); +int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame); + +#ifdef __linux__ +struct dp_sdp; +ssize_t +hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame, + struct dp_sdp *sdp, u8 dp_version); +#endif + +enum hdmi_3d_structure { + HDMI_3D_STRUCTURE_INVALID = -1, + HDMI_3D_STRUCTURE_FRAME_PACKING = 0, + HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE, + HDMI_3D_STRUCTURE_LINE_ALTERNATIVE, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL, + HDMI_3D_STRUCTURE_L_DEPTH, + HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH, + HDMI_3D_STRUCTURE_TOP_AND_BOTTOM, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF = 8, +}; + + +struct hdmi_vendor_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned int oui; + u8 vic; + enum hdmi_3d_structure s3d_struct; + unsigned int s3d_ext_data; +}; + +/* HDR Metadata as per 861.G spec */ +struct hdr_static_metadata { + __u8 eotf; + __u8 metadata_type; + __u16 max_cll; + __u16 max_fall; + __u16 min_cll; +}; + +/** + * struct hdr_sink_metadata - HDR sink metadata + * + * Metadata Information read from Sink's EDID + */ +struct hdr_sink_metadata { + /** + * @metadata_type: Static_Metadata_Descriptor_ID. + */ + __u32 metadata_type; + /** + * @hdmi_type1: HDR Metadata Infoframe. + */ + union { + struct hdr_static_metadata hdmi_type1; + }; +}; + +int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame); +ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, + void *buffer, size_t size); +ssize_t hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe *frame, + void *buffer, size_t size); +int hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe *frame); + +union hdmi_vendor_any_infoframe { + struct { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned int oui; + } any; + struct hdmi_vendor_infoframe hdmi; +}; + +/** + * union hdmi_infoframe - overall union of all abstract infoframe representations + * @any: generic infoframe + * @avi: avi infoframe + * @spd: spd infoframe + * @vendor: union of all vendor infoframes + * @audio: audio infoframe + * @drm: Dynamic Range and Mastering infoframe + * + * This is used by the generic pack function. This works since all infoframes + * have the same header which also indicates which type of infoframe should be + * packed. + */ +union hdmi_infoframe { + struct hdmi_any_infoframe any; + struct hdmi_avi_infoframe avi; + struct hdmi_spd_infoframe spd; + union hdmi_vendor_any_infoframe vendor; + struct hdmi_audio_infoframe audio; + struct hdmi_drm_infoframe drm; +}; + +ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, + void *buffer, size_t size); +int hdmi_infoframe_check(union hdmi_infoframe *frame); +int hdmi_infoframe_unpack(union hdmi_infoframe *frame, + const void *buffer, size_t size); +void hdmi_infoframe_log(const char *level, struct device *dev, + const union hdmi_infoframe *frame); + +#endif /* _DRM_HDMI_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/highmem.h b/sys/compat/linuxkpi/common/include/linux/highmem.h index 9378746ea480..58a9cdcdf60f 100644 --- a/sys/compat/linuxkpi/common/include/linux/highmem.h +++ b/sys/compat/linuxkpi/common/include/linux/highmem.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2010 Isilon Systems, Inc. * Copyright (c) 2016 Matthew Macy (mmacy@mattmacy.io) @@ -29,8 +29,8 @@ * SUCH DAMAGE. */ -#ifndef _LINUX_HIGHMEM_H_ -#define _LINUX_HIGHMEM_H_ +#ifndef _LINUXKPI_LINUX_HIGHMEM_H_ +#define _LINUXKPI_LINUX_HIGHMEM_H_ #include <sys/types.h> #include <sys/lock.h> @@ -43,23 +43,25 @@ #include <vm/vm_page.h> #include <vm/pmap.h> +#include <linux/mm.h> #include <linux/page.h> #define PageHighMem(p) (0) -static inline vm_page_t +static inline struct page * kmap_to_page(void *addr) { + return (virt_to_page(addr)); } static inline void * -kmap(vm_page_t page) +kmap(struct page *page) { struct sf_buf *sf; if (PMAP_HAS_DMAP) { - return ((void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(page))); + return ((void *)PHYS_TO_DMAP(page_to_phys(page))); } else { sched_pin(); sf = sf_buf_alloc(page, SFB_NOWAIT | SFB_CPUPRIVATE); @@ -72,27 +74,39 @@ kmap(vm_page_t page) } static inline void * -kmap_atomic_prot(vm_page_t page, pgprot_t prot) +kmap_atomic_prot(struct page *page, pgprot_t prot) { vm_memattr_t attr = pgprot2cachemode(prot); if (attr != VM_MEMATTR_DEFAULT) { - vm_page_lock(page); page->flags |= PG_FICTITIOUS; - vm_page_unlock(page); pmap_page_set_memattr(page, attr); } return (kmap(page)); } static inline void * -kmap_atomic(vm_page_t page) +kmap_atomic(struct page *page) { + return (kmap_atomic_prot(page, VM_PROT_ALL)); } +static inline void * +kmap_local_page(struct page *page) +{ + return (kmap(page)); +} + +static inline void * +kmap_local_page_prot(struct page *page, pgprot_t prot) +{ + + return (kmap_atomic_prot(page, prot)); +} + static inline void -kunmap(vm_page_t page) +kunmap(struct page *page) { struct sf_buf *sf; @@ -111,8 +125,46 @@ kunmap(vm_page_t page) static inline void kunmap_atomic(void *vaddr) { + if (!PMAP_HAS_DMAP) kunmap(virt_to_page(vaddr)); } -#endif /* _LINUX_HIGHMEM_H_ */ +static inline void +kunmap_local(void *addr) +{ + + kunmap_atomic(addr); +} + +static inline void +memcpy_from_page(char *to, struct page *page, size_t offset, size_t len) +{ + char *from; + + KASSERT(offset + len <= PAGE_SIZE, + ("%s: memcpy from page %p to address %p: " + "offset+len (%zu+%zu) would go beyond page end", + __func__, page, to, offset, len)); + + from = kmap_local_page(page); + memcpy(to, from + offset, len); + kunmap_local(from); +} + +static inline void +memcpy_to_page(struct page *page, size_t offset, const char *from, size_t len) +{ + char *to; + + KASSERT(offset + len <= PAGE_SIZE, + ("%s: memcpy from address %p to page %p: " + "offset+len (%zu+%zu) would go beyond page end", + __func__, from, page, offset, len)); + + to = kmap_local_page(page); + memcpy(to + offset, from, len); + kunmap_local(to); +} + +#endif /* _LINUXKPI_LINUX_HIGHMEM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/hrtimer.h b/sys/compat/linuxkpi/common/include/linux/hrtimer.h index a5ff7480a271..88f9487d0b85 100644 --- a/sys/compat/linuxkpi/common/include/linux/hrtimer.h +++ b/sys/compat/linuxkpi/common/include/linux/hrtimer.h @@ -21,17 +21,16 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_HRTIMER_H_ -#define _LINUX_HRTIMER_H_ +#ifndef _LINUXKPI_LINUX_HRTIMER_H_ +#define _LINUXKPI_LINUX_HRTIMER_H_ #include <sys/_callout.h> #include <sys/_mutex.h> #include <linux/ktime.h> +#include <linux/rbtree.h> #include <linux/timer.h> enum hrtimer_mode { @@ -53,6 +52,7 @@ struct hrtimer { }; #define hrtimer_active(hrtimer) linux_hrtimer_active(hrtimer) +#define hrtimer_try_to_cancel(hrtimer) linux_hrtimer_try_to_cancel(hrtimer) #define hrtimer_cancel(hrtimer) linux_hrtimer_cancel(hrtimer) #define hrtimer_init(hrtimer, clock, mode) do { \ @@ -79,6 +79,7 @@ struct hrtimer { } while (0) bool linux_hrtimer_active(struct hrtimer *); +int linux_hrtimer_try_to_cancel(struct hrtimer *); int linux_hrtimer_cancel(struct hrtimer *); void linux_hrtimer_init(struct hrtimer *); void linux_hrtimer_set_expires(struct hrtimer *, ktime_t); @@ -86,4 +87,4 @@ void linux_hrtimer_start(struct hrtimer *, ktime_t); void linux_hrtimer_start_range_ns(struct hrtimer *, ktime_t, int64_t); void linux_hrtimer_forward_now(struct hrtimer *, ktime_t); -#endif /* _LINUX_HRTIMER_H_ */ +#endif /* _LINUXKPI_LINUX_HRTIMER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/i2c-algo-bit.h b/sys/compat/linuxkpi/common/include/linux/i2c-algo-bit.h new file mode 100644 index 000000000000..4e8f00f9bebc --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/i2c-algo-bit.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUX_I2C_ALGO_BIT_H_ +#define _LINUX_I2C_ALGO_BIT_H_ + +#include <linux/i2c.h> + +struct i2c_algo_bit_data { + void *data; + void (*setsda) (void *data, int state); + void (*setscl) (void *data, int state); + int (*getsda) (void *data); + int (*getscl) (void *data); + int (*pre_xfer) (struct i2c_adapter *); + void (*post_xfer) (struct i2c_adapter *); + + int udelay; + int timeout; +}; + +int lkpi_i2c_bit_add_bus(struct i2c_adapter *adapter); + +#define i2c_bit_add_bus(adapter) lkpi_i2c_bit_add_bus(adapter) + +#endif /*_LINUX_I2C_ALGO_BIT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/i2c.h b/sys/compat/linuxkpi/common/include/linux/i2c.h new file mode 100644 index 000000000000..f24d282586f6 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/i2c.h @@ -0,0 +1,177 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUX_I2C_H_ +#define _LINUX_I2C_H_ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/systm.h> + +#include <linux/device.h> + +#define I2C_MAX_ADAPTER_NAME_LENGTH 32 + +#define I2C_M_RD 0x0001 +#define I2C_M_NOSTART 0x0002 +#define I2C_M_STOP 0x0004 + +/* No need for us */ +#define I2C_FUNC_I2C 0 +#define I2C_FUNC_SMBUS_EMUL 0 +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0 +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0 +#define I2C_FUNC_10BIT_ADDR 0 + +#define I2C_CLASS_HWMON 0x1 +#define I2C_CLASS_DDC 0x8 +#define I2C_CLASS_SPD 0x80 + +struct i2c_adapter { + struct module *owner; + unsigned int class; + + char name[I2C_MAX_ADAPTER_NAME_LENGTH]; + struct device dev; + + const struct i2c_lock_operations *lock_ops; + const struct i2c_algorithm *algo; + const struct i2c_adapter_quirks *quirks; + void *algo_data; + + int retries; + void *data; +}; + +struct i2c_msg { + uint16_t addr; + uint16_t flags; + uint16_t len; + uint8_t *buf; +}; + +struct i2c_algorithm { + int (*master_xfer)(struct i2c_adapter *, struct i2c_msg *, int); + uint32_t (*functionality)(struct i2c_adapter *); +}; + +struct i2c_lock_operations { + void (*lock_bus)(struct i2c_adapter *, unsigned int); + int (*trylock_bus)(struct i2c_adapter *, unsigned int); + void (*unlock_bus)(struct i2c_adapter *, unsigned int); +}; + +struct i2c_adapter_quirks { + uint64_t flags; + int max_num_msgs; + uint16_t max_write_len; + uint16_t max_read_len; + uint16_t max_comb_1st_msg_len; + uint16_t max_comb_2nd_msg_len; +}; + +#define I2C_AQ_COMB BIT(0) +#define I2C_AQ_COMB_WRITE_FIRST BIT(1) +#define I2C_AQ_COMB_READ_SECOND BIT(2) +#define I2C_AQ_COMB_SAME_ADDR BIT(3) +#define I2C_AQ_COMB_WRITE_THEN_READ \ + (I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \ + I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR) +#define I2C_AQ_NO_CLK_STRETCH BIT(4) +#define I2C_AQ_NO_ZERO_LEN_READ BIT(5) +#define I2C_AQ_NO_ZERO_LEN_WRITE BIT(6) +#define I2C_AQ_NO_ZERO_LEN \ + (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE) +#define I2C_AQ_NO_REP_START BIT(7) + +int lkpi_i2c_add_adapter(struct i2c_adapter *adapter); +int lkpi_i2c_del_adapter(struct i2c_adapter *adapter); + +int lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs); + +#define i2c_add_adapter(adapter) lkpi_i2c_add_adapter(adapter) +#define i2c_del_adapter(adapter) lkpi_i2c_del_adapter(adapter) + +#define i2c_get_adapter(x) NULL +#define i2c_put_adapter(x) + +static inline int +do_i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) +{ + int ret, retries; + + retries = adapter->retries == 0 ? 1 : adapter->retries; + for (; retries != 0; retries--) { + if (adapter->algo != NULL && adapter->algo->master_xfer != NULL) + ret = adapter->algo->master_xfer(adapter, msgs, nmsgs); + else + ret = lkpi_i2cbb_transfer(adapter, msgs, nmsgs); + if (ret != -EAGAIN) + break; + } + + return (ret); +} + +static inline int +i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) +{ + int ret; + + if (adapter->algo == NULL && adapter->algo_data == NULL) + return (-EOPNOTSUPP); + + if (adapter->lock_ops) + adapter->lock_ops->lock_bus(adapter, 0); + + ret = do_i2c_transfer(adapter, msgs, nmsgs); + + if (adapter->lock_ops) + adapter->lock_ops->unlock_bus(adapter, 0); + + return (ret); +} + +/* Unlocked version of i2c_transfer */ +static inline int +__i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) +{ + return (do_i2c_transfer(adapter, msgs, nmsgs)); +} + +static inline void +i2c_set_adapdata(struct i2c_adapter *adapter, void *data) +{ + adapter->data = data; +} + +static inline void * +i2c_get_adapdata(struct i2c_adapter *adapter) +{ + return (adapter->data); +} + +#endif /* _LINUX_I2C_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/idr.h b/sys/compat/linuxkpi/common/include/linux/idr.h index cba3f96c88ae..06850c94a5e9 100644 --- a/sys/compat/linuxkpi/common/include/linux/idr.h +++ b/sys/compat/linuxkpi/common/include/linux/idr.h @@ -25,16 +25,17 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IDR_H_ -#define _LINUX_IDR_H_ +#ifndef _LINUXKPI_LINUX_IDR_H_ +#define _LINUXKPI_LINUX_IDR_H_ #include <sys/param.h> #include <sys/lock.h> +#include <sys/limits.h> #include <sys/mutex.h> +#include <linux/radix-tree.h> +#include <linux/gpf.h> #include <linux/types.h> #define IDR_BITS 5 @@ -134,12 +135,25 @@ ida_get_new(struct ida *ida, int *p_id) } static inline int +ida_alloc_min(struct ida *ida, unsigned int min, gfp_t gfp) +{ + return (ida_simple_get(ida, min, UINT_MAX, gfp)); +} + +static inline int ida_alloc_max(struct ida *ida, unsigned int max, gfp_t gfp) { return (ida_simple_get(ida, 0, max, gfp)); } +static inline int +ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max, gfp_t gfp) +{ + + return (ida_simple_get(ida, min, max, gfp)); +} + static inline int ida_alloc(struct ida *ida, gfp_t gfp) { return (ida_alloc_max(ida, ~0u, gfp)); @@ -152,4 +166,4 @@ ida_is_empty(struct ida *ida) return (idr_is_empty(&ida->idr)); } -#endif /* _LINUX_IDR_H_ */ +#endif /* _LINUXKPI_LINUX_IDR_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h new file mode 100644 index 000000000000..ea8c0fc8ef5e --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h @@ -0,0 +1,1269 @@ +/*- + * Copyright (c) 2020-2025 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_IEEE80211_H +#define _LINUXKPI_LINUX_IEEE80211_H + +#include <sys/types.h> +#include <net80211/ieee80211.h> + +#include <asm/unaligned.h> +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> +#include <linux/if_ether.h> + +/* linux_80211.c */ +extern int linuxkpi_debug_80211; +#ifndef D80211_TODO +#define D80211_TODO 0x1 +#endif +#define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ + printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) + + +/* 9.4.2.55 Management MIC element (CMAC-256, GMAC-128, and GMAC-256). */ +struct ieee80211_mmie_16 { + uint8_t element_id; + uint8_t length; + uint16_t key_id; + uint8_t ipn[6]; + uint8_t mic[16]; +}; + +#define IEEE80211_CCMP_HDR_LEN 8 /* 802.11i .. net80211 comment */ +#define IEEE80211_CCMP_PN_LEN 6 +#define IEEE80211_CCMP_MIC_LEN 8 /* || 16 */ +#define IEEE80211_CCMP_256_HDR_LEN 8 +#define IEEE80211_CCMP_256_MIC_LEN 16 +#define IEEE80211_GCMP_HDR_LEN 8 +#define IEEE80211_GCMP_MIC_LEN 16 +#define IEEE80211_GCMP_PN_LEN 6 +#define IEEE80211_GMAC_PN_LEN 6 +#define IEEE80211_CMAC_PN_LEN 6 + +#define IEEE80211_MAX_PN_LEN 16 + +#define IEEE80211_INVAL_HW_QUEUE ((uint8_t)-1) + +#define IEEE80211_MAX_AMPDU_BUF_HT IEEE80211_AGGR_BAWMAX +#define IEEE80211_MAX_AMPDU_BUF_HE 256 +#define IEEE80211_MAX_AMPDU_BUF_EHT 1024 + +#define IEEE80211_MAX_FRAME_LEN 2352 +#define IEEE80211_MAX_DATA_LEN (2300 + IEEE80211_CRC_LEN) + +#define IEEE80211_MAX_MPDU_LEN_HT_BA 4095 /* 9.3.2.1 Format of Data frames; non-VHT non-DMG STA */ +#define IEEE80211_MAX_MPDU_LEN_HT_3839 3839 +#define IEEE80211_MAX_MPDU_LEN_HT_7935 7935 +#define IEEE80211_MAX_MPDU_LEN_VHT_3895 3895 +#define IEEE80211_MAX_MPDU_LEN_VHT_7991 7991 +#define IEEE80211_MAX_MPDU_LEN_VHT_11454 11454 + +#define IEEE80211_MAX_RTS_THRESHOLD 2346 /* net80211::IEEE80211_RTS_MAX */ + +#define IEEE80211_MIN_ACTION_SIZE 23 /* ? */ + +/* Wi-Fi Peer-to-Peer (P2P) Technical Specification */ +#define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7f +#define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7) + +/* 802.11-2016, 9.2.4.5.1, Table 9-6 QoS Control Field */ +#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 +#define IEEE80211_QOS_CTL_TID_MASK IEEE80211_QOS_TID +#define IEEE80211_QOS_CTL_EOSP 0x0010 +#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080 +#define IEEE80211_QOS_CTL_ACK_POLICY_MASK 0x0060 +#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020 +#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100 + +enum ieee80211_rate_flags { + IEEE80211_RATE_SHORT_PREAMBLE = BIT(0), +}; + +enum ieee80211_rate_control_changed_flags { + IEEE80211_RC_BW_CHANGED = BIT(0), + IEEE80211_RC_NSS_CHANGED = BIT(1), + IEEE80211_RC_SUPP_RATES_CHANGED = BIT(2), + IEEE80211_RC_SMPS_CHANGED = BIT(3), +}; + +#define IEEE80211_SCTL_FRAG IEEE80211_SEQ_FRAG_MASK +#define IEEE80211_SCTL_SEQ IEEE80211_SEQ_SEQ_MASK + +#define IEEE80211_TKIP_ICV_LEN 4 +#define IEEE80211_TKIP_IV_LEN 8 /* WEP + KID + EXT */ + +/* 802.11-2016, 9.4.2.158.3 Supported VHT-MCS and NSS Set field. */ +#define IEEE80211_VHT_EXT_NSS_BW_CAPABLE (1 << 13) /* part of tx_highest */ + +/* + * 802.11-2020, 9.4.2.157.2 VHT Capabilities Information field, + * Table 9-271-Subfields of the VHT Capabilities Information field (continued). + */ +enum ieee80211_vht_max_ampdu_len_exp { + IEEE80211_VHT_MAX_AMPDU_8K = 0, + IEEE80211_VHT_MAX_AMPDU_16K = 1, + IEEE80211_VHT_MAX_AMPDU_32K = 2, + IEEE80211_VHT_MAX_AMPDU_64K = 3, + IEEE80211_VHT_MAX_AMPDU_128K = 4, + IEEE80211_VHT_MAX_AMPDU_256K = 5, + IEEE80211_VHT_MAX_AMPDU_512K = 6, + IEEE80211_VHT_MAX_AMPDU_1024K = 7, +}; + +#define IEEE80211_WEP_IV_LEN 3 /* net80211: IEEE80211_WEP_IVLEN */ +#define IEEE80211_WEP_ICV_LEN 4 + +#define WLAN_AUTH_OPEN __LINE__ /* TODO FIXME brcmfmac */ +#define WLAN_CAPABILITY_IBSS __LINE__ /* TODO FIXME no longer used? */ +#define WLAN_CAPABILITY_SHORT_PREAMBLE __LINE__ /* TODO FIXME brcmfmac */ +#define WLAN_CAPABILITY_SHORT_SLOT_TIME __LINE__ /* TODO FIXME brcmfmac */ + +enum wlan_ht_cap_sm_ps { + WLAN_HT_CAP_SM_PS_STATIC = 0, + WLAN_HT_CAP_SM_PS_DYNAMIC = 1, + WLAN_HT_CAP_SM_PS_INVALID = 2, + WLAN_HT_CAP_SM_PS_DISABLED = 3 +}; + +#define WLAN_MAX_KEY_LEN 32 +#define WLAN_PMKID_LEN 16 +#define WLAN_PMK_LEN_SUITE_B_192 48 + +enum ieee80211_key_len { + WLAN_KEY_LEN_WEP40 = 5, + WLAN_KEY_LEN_WEP104 = 13, + WLAN_KEY_LEN_TKIP = 32, + WLAN_KEY_LEN_CCMP = 16, + WLAN_KEY_LEN_CCMP_256 = 32, + WLAN_KEY_LEN_GCMP = 16, + WLAN_KEY_LEN_AES_CMAC = 16, + WLAN_KEY_LEN_GCMP_256 = 32, + WLAN_KEY_LEN_BIP_CMAC_256 = 32, + WLAN_KEY_LEN_BIP_GMAC_128 = 16, + WLAN_KEY_LEN_BIP_GMAC_256 = 32, +}; + +/* 802.11-2020, 9.4.2.55.3, Table 9-185 Subfields of the A-MPDU Parameters field */ +enum ieee80211_min_mpdu_start_spacing { + IEEE80211_HT_MPDU_DENSITY_NONE = 0, +#if 0 + IEEE80211_HT_MPDU_DENSITY_XXX = 1, /* 1/4 us */ +#endif + IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 us */ + IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 us */ + IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 us */ + IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4us */ + IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8us */ + IEEE80211_HT_MPDU_DENSITY_16 = 7, /* 16us */ +}; + +/* 9.4.2.57, Table 9-168, HT Operation element fields and subfields */ +#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 /* B24.. */ + +#define IEEE80211_FCTL_FTYPE IEEE80211_FC0_TYPE_MASK +#define IEEE80211_FCTL_STYPE IEEE80211_FC0_SUBTYPE_MASK +#define IEEE80211_FCTL_ORDER (IEEE80211_FC1_ORDER << 8) +#define IEEE80211_FCTL_PROTECTED (IEEE80211_FC1_PROTECTED << 8) +#define IEEE80211_FCTL_FROMDS (IEEE80211_FC1_DIR_FROMDS << 8) +#define IEEE80211_FCTL_TODS (IEEE80211_FC1_DIR_TODS << 8) +#define IEEE80211_FCTL_MOREFRAGS (IEEE80211_FC1_MORE_FRAG << 8) +#define IEEE80211_FCTL_PM (IEEE80211_FC1_PWR_MGT << 8) + +#define IEEE80211_FTYPE_MGMT IEEE80211_FC0_TYPE_MGT +#define IEEE80211_FTYPE_CTL IEEE80211_FC0_TYPE_CTL +#define IEEE80211_FTYPE_DATA IEEE80211_FC0_TYPE_DATA + +#define IEEE80211_STYPE_ASSOC_REQ IEEE80211_FC0_SUBTYPE_ASSOC_REQ +#define IEEE80211_STYPE_REASSOC_REQ IEEE80211_FC0_SUBTYPE_REASSOC_REQ +#define IEEE80211_STYPE_PROBE_REQ IEEE80211_FC0_SUBTYPE_PROBE_REQ +#define IEEE80211_STYPE_DISASSOC IEEE80211_FC0_SUBTYPE_DISASSOC +#define IEEE80211_STYPE_AUTH IEEE80211_FC0_SUBTYPE_AUTH +#define IEEE80211_STYPE_DEAUTH IEEE80211_FC0_SUBTYPE_DEAUTH +#define IEEE80211_STYPE_CTS IEEE80211_FC0_SUBTYPE_CTS +#define IEEE80211_STYPE_RTS IEEE80211_FC0_SUBTYPE_RTS +#define IEEE80211_STYPE_ACTION IEEE80211_FC0_SUBTYPE_ACTION +#define IEEE80211_STYPE_DATA IEEE80211_FC0_SUBTYPE_DATA +#define IEEE80211_STYPE_QOS_DATA IEEE80211_FC0_SUBTYPE_QOS_DATA +#define IEEE80211_STYPE_QOS_NULLFUNC IEEE80211_FC0_SUBTYPE_QOS_NULL +#define IEEE80211_STYPE_QOS_CFACK 0xd0 /* XXX-BZ reserved? */ + +#define IEEE80211_NUM_ACS 4 /* net8021::WME_NUM_AC */ + +#define IEEE80211_MAX_SSID_LEN 32 /* 9.4.2.2 SSID element, net80211: IEEE80211_NWID_LEN */ + + +/* Figure 9-27, BAR Control field */ +#define IEEE80211_BAR_CTRL_TID_INFO_MASK 0xf000 +#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT 12 + +#define IEEE80211_PPE_THRES_INFO_PPET_SIZE 1 /* TODO FIXME ax? */ +#define IEEE80211_PPE_THRES_NSS_MASK 2 /* TODO FIXME ax? */ +#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_POS 3 /* TODO FIXME ax? */ +#define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK 8 /* TODO FIXME ax? */ +#define IEEE80211_HE_PPE_THRES_INFO_HEADER_SIZE 16 /* TODO FIXME ax? */ + +/* 802.11-2012, Table 8-130-HT Operation element fields and subfields, HT Protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION IEEE80211_HTINFO_OPMODE /* Mask. */ +#define IEEE80211_HT_OP_MODE_PROTECTION_NONE IEEE80211_HTINFO_OPMODE_PURE /* No protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER IEEE80211_HTINFO_OPMODE_PROTOPT /* Nonmember protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ IEEE80211_HTINFO_OPMODE_HT20PR /* 20 MHz protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED IEEE80211_HTINFO_OPMODE_MIXED /* Non-HT mixed */ + + +/* 9.6.13.1, Table 9-342 TDLS Action field values. */ +enum ieee80211_tdls_action_code { + WLAN_TDLS_SETUP_REQUEST = 0, + WLAN_TDLS_SETUP_RESPONSE = 1, + WLAN_TDLS_SETUP_CONFIRM = 2, + WLAN_TDLS_TEARDOWN = 3, + WLAN_TDLS_PEER_TRAFFIC_INDICATION = 4, + WLAN_TDLS_CHANNEL_SWITCH_REQUEST = 5, + WLAN_TDLS_CHANNEL_SWITCH_RESPONSE = 6, + WLAN_TDLS_PEER_PSM_REQUEST = 7, + WLAN_TDLS_PEER_PSM_RESPONSE = 8, + WLAN_TDLS_PEER_TRAFFIC_RESPONSE = 9, + WLAN_TDLS_DISCOVERY_REQUEST = 10, + /* 11-255 reserved */ +}; + +/* 802.11-2020 9.4.2.26, Table 9-153. Extended Capabilities field. */ +/* This is split up into octets CAPA1 = octet 1, ... */ +#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2 % 8) +#define WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT BIT(22 % 8) +#define WLAN_EXT_CAPA3_TIMING_MEASUREMENT_SUPPORT BIT(23 % 8) +#define WLAN_EXT_CAPA8_OPMODE_NOTIF BIT(62 % 8) +#define WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB BIT(63 % 8) +#define WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB BIT(64 % 8) +#define WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT BIT(77 % 8) +#define WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT BIT(78 % 8) +#define WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT BIT(79 % 8) + +#define WLAN_EXT_CAPA11_EMA_SUPPORT 0x00 /* XXX TODO FIXME */ + + +/* iwlwifi/mvm/utils:: for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_VI; ac++) */ +/* Would be so much easier if we'd define constants to the same. */ +enum ieee80211_ac_numbers { + IEEE80211_AC_VO = 0, /* net80211::WME_AC_VO */ + IEEE80211_AC_VI = 1, /* net80211::WME_AC_VI */ + IEEE80211_AC_BE = 2, /* net80211::WME_AC_BE */ + IEEE80211_AC_BK = 3, /* net80211::WME_AC_BK */ +}; + +#define IEEE80211_MAX_QUEUES 16 /* Assume IEEE80211_NUM_TIDS for the moment. */ + +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO 1 +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI 2 +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK 4 +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE 8 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0xf + + +/* Define the LinuxKPI names directly to the net80211 ones. */ +#define IEEE80211_HT_CAP_LDPC_CODING IEEE80211_HTCAP_LDPC +#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 IEEE80211_HTCAP_CHWIDTH40 +#define IEEE80211_HT_CAP_SM_PS IEEE80211_HTCAP_SMPS +#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 +#define IEEE80211_HT_CAP_GRN_FLD IEEE80211_HTCAP_GREENFIELD +#define IEEE80211_HT_CAP_SGI_20 IEEE80211_HTCAP_SHORTGI20 +#define IEEE80211_HT_CAP_SGI_40 IEEE80211_HTCAP_SHORTGI40 +#define IEEE80211_HT_CAP_TX_STBC IEEE80211_HTCAP_TXSTBC +#define IEEE80211_HT_CAP_RX_STBC IEEE80211_HTCAP_RXSTBC +#define IEEE80211_HT_CAP_RX_STBC_SHIFT IEEE80211_HTCAP_RXSTBC_S +#define IEEE80211_HT_CAP_MAX_AMSDU IEEE80211_HTCAP_MAXAMSDU +#define IEEE80211_HT_CAP_DSSSCCK40 IEEE80211_HTCAP_DSSSCCK40 +#define IEEE80211_HT_CAP_LSIG_TXOP_PROT IEEE80211_HTCAP_LSIGTXOPPROT + +#define IEEE80211_HT_MCS_TX_DEFINED 0x0001 +#define IEEE80211_HT_MCS_TX_RX_DIFF 0x0002 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0c +#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff +#define IEEE80211_HT_MCS_MASK_LEN 10 + +#define IEEE80211_MLD_MAX_NUM_LINKS 15 +#define IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS 0xf +#define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP 0x0060 +#define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME 1 +#define IEEE80211_MLD_CAP_OP_LINK_RECONF_SUPPORT 0x2000 + +struct ieee80211_mcs_info { + uint8_t rx_mask[IEEE80211_HT_MCS_MASK_LEN]; + uint16_t rx_highest; + uint8_t tx_params; + uint8_t __reserved[3]; +} __packed; + +/* 802.11-2020, 9.4.2.55.1 HT Capabilities element structure */ +struct ieee80211_ht_cap { + uint16_t cap_info; + uint8_t ampdu_params_info; + struct ieee80211_mcs_info mcs; + uint16_t extended_ht_cap_info; + uint32_t tx_BF_cap_info; + uint8_t antenna_selection_info; +} __packed; + +#define IEEE80211_HT_MAX_AMPDU_FACTOR 13 +#define IEEE80211_HE_HT_MAX_AMPDU_FACTOR 16 +#define IEEE80211_HE_VHT_MAX_AMPDU_FACTOR 20 +#define IEEE80211_HE_6GHZ_MAX_AMPDU_FACTOR 13 + +enum ieee80211_ht_max_ampdu_len { + IEEE80211_HT_MAX_AMPDU_64K +}; + +enum ieee80211_ampdu_mlme_action { + IEEE80211_AMPDU_RX_START, + IEEE80211_AMPDU_RX_STOP, + IEEE80211_AMPDU_TX_OPERATIONAL, + IEEE80211_AMPDU_TX_START, + IEEE80211_AMPDU_TX_STOP_CONT, + IEEE80211_AMPDU_TX_STOP_FLUSH, + IEEE80211_AMPDU_TX_STOP_FLUSH_CONT +}; + +#define IEEE80211_AMPDU_TX_START_IMMEDIATE 1 +#define IEEE80211_AMPDU_TX_START_DELAY_ADDBA 2 + +enum ieee80211_chanctx_switch_mode { + CHANCTX_SWMODE_REASSIGN_VIF, + CHANCTX_SWMODE_SWAP_CONTEXTS, +}; + +enum ieee80211_chanctx_change_flags { + IEEE80211_CHANCTX_CHANGE_MIN_WIDTH = BIT(0), + IEEE80211_CHANCTX_CHANGE_RADAR = BIT(1), + IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(2), + IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(3), + IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(4), + IEEE80211_CHANCTX_CHANGE_PUNCTURING = BIT(5), + IEEE80211_CHANCTX_CHANGE_MIN_DEF = BIT(6), + IEEE80211_CHANCTX_CHANGE_AP = BIT(7), +}; + +enum ieee80211_frame_release_type { + IEEE80211_FRAME_RELEASE_PSPOLL = 1, + IEEE80211_FRAME_RELEASE_UAPSD = 2, +}; + +enum ieee80211_p2p_attr_ids { + IEEE80211_P2P_ATTR_DEVICE_ID, + IEEE80211_P2P_ATTR_DEVICE_INFO, + IEEE80211_P2P_ATTR_GROUP_ID, + IEEE80211_P2P_ATTR_LISTEN_CHANNEL, + IEEE80211_P2P_ATTR_ABSENCE_NOTICE, +}; + +enum ieee80211_reconfig_type { + IEEE80211_RECONFIG_TYPE_RESTART, + IEEE80211_RECONFIG_TYPE_SUSPEND, +}; + +enum ieee80211_roc_type { + IEEE80211_ROC_TYPE_MGMT_TX, + IEEE80211_ROC_TYPE_NORMAL, +}; + +enum ieee80211_smps_mode { + IEEE80211_SMPS_OFF, + IEEE80211_SMPS_STATIC, + IEEE80211_SMPS_DYNAMIC, + IEEE80211_SMPS_AUTOMATIC, + IEEE80211_SMPS_NUM_MODES, +}; + +/* net80211::IEEE80211_S_* different but represents the state machine. */ +/* Note: order here is important! */ +enum ieee80211_sta_state { + IEEE80211_STA_NOTEXIST = 0, + IEEE80211_STA_NONE = 1, + IEEE80211_STA_AUTH = 2, + IEEE80211_STA_ASSOC = 3, + IEEE80211_STA_AUTHORIZED = 4, /* 802.1x */ +}; + +enum ieee80211_sta_rx_bandwidth { + IEEE80211_STA_RX_BW_20 = 0, + IEEE80211_STA_RX_BW_40, + IEEE80211_STA_RX_BW_80, + IEEE80211_STA_RX_BW_160, + IEEE80211_STA_RX_BW_320, +}; + +enum ieee80211_tx_info_flags { + /* XXX TODO .. right shift numbers - not sure where that came from? */ + IEEE80211_TX_CTL_AMPDU = BIT(0), + IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), + IEEE80211_TX_CTL_NO_ACK = BIT(2), + IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(3), + IEEE80211_TX_CTL_TX_OFFCHAN = BIT(4), + IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(5), + IEEE80211_TX_STATUS_EOSP = BIT(6), + IEEE80211_TX_STAT_ACK = BIT(7), + IEEE80211_TX_STAT_AMPDU = BIT(8), + IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(9), + IEEE80211_TX_STAT_TX_FILTERED = BIT(10), + IEEE80211_TX_STAT_NOACK_TRANSMITTED = BIT(11), + IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(12), + IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(13), + IEEE80211_TX_CTL_NO_CCK_RATE = BIT(14), + IEEE80211_TX_CTL_INJECTED = BIT(15), + IEEE80211_TX_CTL_HW_80211_ENCAP = BIT(16), + IEEE80211_TX_CTL_USE_MINRATE = BIT(17), + IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(18), + IEEE80211_TX_CTL_LDPC = BIT(19), + IEEE80211_TX_CTL_STBC = BIT(20), +} __packed; + +enum ieee80211_tx_status_flags { + IEEE80211_TX_STATUS_ACK_SIGNAL_VALID = BIT(0), +}; + +enum ieee80211_tx_control_flags { + /* XXX TODO .. right shift numbers */ + IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0), + IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1), + IEEE80211_TX_CTRL_RATE_INJECT = BIT(2), + IEEE80211_TX_CTRL_DONT_USE_RATE_MASK = BIT(3), + IEEE80211_TX_CTRL_MLO_LINK = 0xF0000000, /* This is IEEE80211_LINK_UNSPECIFIED on the high bits. */ +}; + +enum ieee80211_tx_rate_flags { + /* XXX TODO .. right shift numbers */ + IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(0), + IEEE80211_TX_RC_80_MHZ_WIDTH = BIT(1), + IEEE80211_TX_RC_160_MHZ_WIDTH = BIT(2), + IEEE80211_TX_RC_GREEN_FIELD = BIT(3), + IEEE80211_TX_RC_MCS = BIT(4), + IEEE80211_TX_RC_SHORT_GI = BIT(5), + IEEE80211_TX_RC_VHT_MCS = BIT(6), + IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(7), +}; + +#define IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED -128 + +#define IEEE80211_HT_CTL_LEN 4 + +struct ieee80211_hdr { /* net80211::ieee80211_frame_addr4 */ + __le16 frame_control; + __le16 duration_id; + uint8_t addr1[ETH_ALEN]; + uint8_t addr2[ETH_ALEN]; + uint8_t addr3[ETH_ALEN]; + __le16 seq_ctrl; + uint8_t addr4[ETH_ALEN]; +}; + +struct ieee80211_hdr_3addr { /* net80211::ieee80211_frame */ + __le16 frame_control; + __le16 duration_id; + uint8_t addr1[ETH_ALEN]; + uint8_t addr2[ETH_ALEN]; + uint8_t addr3[ETH_ALEN]; + __le16 seq_ctrl; +}; + +struct ieee80211_qos_hdr { /* net80211:ieee80211_qosframe */ + __le16 frame_control; + __le16 duration_id; + uint8_t addr1[ETH_ALEN]; + uint8_t addr2[ETH_ALEN]; + uint8_t addr3[ETH_ALEN]; + __le16 seq_ctrl; + __le16 qos_ctrl; +}; + +struct ieee80211_vendor_ie { +}; + +/* 802.11-2020, Table 9-359-Block Ack Action field values */ +enum ieee80211_back { + WLAN_ACTION_ADDBA_REQ = 0, +}; + +enum ieee80211_sa_query { + WLAN_ACTION_SA_QUERY_RESPONSE = 1, +}; + +/* 802.11-2020, Table 9-51-Category values */ +enum ieee80211_category { + WLAN_CATEGORY_BACK = 3, + WLAN_CATEGORY_SA_QUERY = 8, /* net80211::IEEE80211_ACTION_CAT_SA_QUERY */ +}; + +/* 80211-2020 9.3.3.2 Format of Management frames */ +struct ieee80211_mgmt { + __le16 frame_control; + __le16 duration_id; + uint8_t da[ETH_ALEN]; + uint8_t sa[ETH_ALEN]; + uint8_t bssid[ETH_ALEN]; + __le16 seq_ctrl; + union { + /* 9.3.3.3 Beacon frame format */ + struct { + uint64_t timestamp; + uint16_t beacon_int; + uint16_t capab_info; + uint8_t variable[0]; + } __packed beacon; + /* 9.3.3.5 Association Request frame format */ + struct { + uint16_t capab_info; + uint16_t listen_interval; + uint8_t variable[0]; + } __packed assoc_req; + /* 9.3.3.10 Probe Request frame format */ + struct { + uint8_t variable[0]; + } __packed probe_req; + /* 9.3.3.11 Probe Response frame format */ + struct { + uint64_t timestamp; + uint16_t beacon_int; + uint16_t capab_info; + uint8_t variable[0]; + } __packed probe_resp; + /* 9.3.3.14 Action frame format */ + struct { + /* 9.4.1.11 Action field */ + uint8_t category; + /* 9.6.8 Public Action details */ + union { + /* 9.6.2.5 TPC Report frame format */ + struct { + uint8_t spec_mgmt; + uint8_t dialog_token; + /* uint32_t tpc_rep_elem:: */ + uint8_t tpc_elem_id; + uint8_t tpc_elem_length; + uint8_t tpc_elem_tx_power; + uint8_t tpc_elem_link_margin; + } __packed tpc_report; + /* 9.6.8.33 Fine Timing Measurement frame format */ + struct { + uint8_t dialog_token; + uint8_t follow_up; + uint8_t tod[6]; + uint8_t toa[6]; + uint16_t tod_error; + uint16_t toa_error; + uint8_t variable[0]; + } __packed ftm; + /* 802.11-2016, 9.6.5.2 ADDBA Request frame format */ + struct { + uint8_t action_code; + uint8_t dialog_token; + uint16_t capab; + uint16_t timeout; + uint16_t start_seq_num; + /* Optional follows... */ + uint8_t variable[0]; + } __packed addba_req; + /* XXX */ + struct { + uint8_t dialog_token; + } __packed wnm_timing_msr; + } u; + } __packed action; + DECLARE_FLEX_ARRAY(uint8_t, body); + } u; +} __packed __aligned(2); + +struct ieee80211_cts { /* net80211::ieee80211_frame_cts */ + __le16 frame_control; + __le16 duration; + uint8_t ra[ETH_ALEN]; +} __packed; + +struct ieee80211_rts { /* net80211::ieee80211_frame_rts */ + __le16 frame_control; + __le16 duration; + uint8_t ra[ETH_ALEN]; + uint8_t ta[ETH_ALEN]; +} __packed; + +#define MHZ_TO_KHZ(_f) ((_f) * 1000) +#define DBI_TO_MBI(_g) ((_g) * 100) +#define MBI_TO_DBI(_x) ((_x) / 100) +#define DBM_TO_MBM(_g) ((_g) * 100) +#define MBM_TO_DBM(_x) ((_x) / 100) + +#define IEEE80211_SEQ_TO_SN(_seqn) (((_seqn) & IEEE80211_SEQ_SEQ_MASK) >> \ + IEEE80211_SEQ_SEQ_SHIFT) +#define IEEE80211_SN_TO_SEQ(_sn) (((_sn) << IEEE80211_SEQ_SEQ_SHIFT) & \ + IEEE80211_SEQ_SEQ_MASK) + +/* Time unit (TU) to .. See net80211: IEEE80211_DUR_TU */ +#define TU_TO_JIFFIES(_tu) (usecs_to_jiffies(_tu) * 1024) +#define TU_TO_EXP_TIME(_tu) (jiffies + TU_TO_JIFFIES(_tu)) + +/* 9.4.2.21.1, Table 9-82. */ +#define IEEE80211_SPCT_MSR_RPRT_TYPE_LCI 8 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC 11 + +/* 9.4.2.1, Table 9-77. Element IDs. */ +enum ieee80211_eid { + WLAN_EID_SSID = 0, + WLAN_EID_SUPP_RATES = 1, + WLAN_EID_DS_PARAMS = 3, + WLAN_EID_TIM = 5, + WLAN_EID_COUNTRY = 7, /* IEEE80211_ELEMID_COUNTRY */ + WLAN_EID_REQUEST = 10, + WLAN_EID_QBSS_LOAD = 11, /* IEEE80211_ELEMID_BSSLOAD */ + WLAN_EID_CHANNEL_SWITCH = 37, + WLAN_EID_MEASURE_REPORT = 39, + WLAN_EID_HT_CAPABILITY = 45, /* IEEE80211_ELEMID_HTCAP */ + WLAN_EID_RSN = 48, /* IEEE80211_ELEMID_RSN */ + WLAN_EID_EXT_SUPP_RATES = 50, + WLAN_EID_EXT_NON_INHERITANCE = 56, + WLAN_EID_EXT_CHANSWITCH_ANN = 60, + WLAN_EID_MULTIPLE_BSSID = 71, /* IEEE80211_ELEMID_MULTIBSSID */ + WLAN_EID_MULTI_BSSID_IDX = 85, + WLAN_EID_EXT_CAPABILITY = 127, + WLAN_EID_VHT_CAPABILITY = 191, /* IEEE80211_ELEMID_VHT_CAP */ + WLAN_EID_S1G_TWT = 216, + WLAN_EID_VENDOR_SPECIFIC = 221, /* IEEE80211_ELEMID_VENDOR */ +}; + +enum ieee80211_eid_ext { + WLAN_EID_EXT_HE_CAPABILITY = 35, +}; + +#define for_each_element(_elem, _data, _len) \ + for (_elem = (const struct element *)(_data); \ + (((const uint8_t *)(_data) + (_len) - (const uint8_t *)_elem) >= sizeof(*_elem)) && \ + (((const uint8_t *)(_data) + (_len) - (const uint8_t *)_elem) >= (sizeof(*_elem) + _elem->datalen)); \ + _elem = (const struct element *)(_elem->data + _elem->datalen)) + +#define for_each_element_id(_elem, _eid, _data, _len) \ + for_each_element(_elem, _data, _len) \ + if (_elem->id == (_eid)) + +/* 9.4.1.7, Table 9-45. Reason codes. */ +enum ieee80211_reason_code { + /* reserved = 0, */ + WLAN_REASON_UNSPECIFIED = 1, + WLAN_REASON_DEAUTH_LEAVING = 3, /* LEAVING_NETWORK_DEAUTH */ + WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE = 25, + WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED = 26, +}; + +/* 9.4.1.9, Table 9-46. Status codes. */ +enum ieee80211_status_code { + WLAN_STATUS_SUCCESS = 0, + WLAN_STATUS_AUTH_TIMEOUT = 16, /* REJECTED_SEQUENCE_TIMEOUT */ +}; + +/* 9.3.1.22 Trigger frame format; 80211ax-2021 */ +struct ieee80211_trigger { + __le16 frame_control; + __le16 duration_id; + uint8_t ra[ETH_ALEN]; + uint8_t ta[ETH_ALEN]; + __le64 common_info; /* 8+ really */ + uint8_t variable[]; +}; + +/* Table 9-29c-Trigger Type subfield encoding */ +enum { + IEEE80211_TRIGGER_TYPE_BASIC = 0x0, + IEEE80211_TRIGGER_TYPE_MU_BAR = 0x2, +#if 0 + /* Not seen yet. */ + BFRP = 0x1, + MU-RTS = 0x3, + BSRP = 0x4, + GCR MU-BAR = 0x5, + BQRP = 0x6, + NFRP = 0x7, + /* 0x8..0xf reserved */ +#endif + IEEE80211_TRIGGER_TYPE_MASK = 0xf +}; + +#define IEEE80211_TRIGGER_ULBW_MASK 0xc0000 +#define IEEE80211_TRIGGER_ULBW_20MHZ 0x0 +#define IEEE80211_TRIGGER_ULBW_40MHZ 0x1 +#define IEEE80211_TRIGGER_ULBW_80MHZ 0x2 +#define IEEE80211_TRIGGER_ULBW_160_80P80MHZ 0x3 + +/* 802.11-2020, Figure 9-687-Control field format; 802.11ax-2021 */ +#define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3) +#define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4) +#define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5) + +/* 802.11-2020, Figure 9-688-Request Type field format; 802.11ax-2021 */ +#define IEEE80211_TWT_REQTYPE_SETUP_CMD (BIT(1) | BIT(2) | BIT(3)) +#define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4) +#define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5) +#define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6) +#define IEEE80211_TWT_REQTYPE_FLOWID (BIT(7) | BIT(8) | BIT(9)) +#define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP (BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14)) +#define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15) + +struct ieee80211_twt_params { + int mantissa, min_twt_dur, twt; + uint16_t req_type; +}; + +struct ieee80211_twt_setup { + int control; + struct ieee80211_twt_params *params; +}; + +/* 802.11-2020, Table 9-297-TWT Setup Command field values */ +enum ieee80211_twt_setup_cmd { + TWT_SETUP_CMD_REQUEST = 0, + TWT_SETUP_CMD_SUGGEST = 1, + /* DEMAND = 2, */ + /* GROUPING = 3, */ + TWT_SETUP_CMD_ACCEPT = 4, + /* ALTERNATE = 5 */ + TWT_SETUP_CMD_DICTATE = 6, + TWT_SETUP_CMD_REJECT = 7, +}; + +struct ieee80211_bssid_index { + int bssid_index; +}; + +enum ieee80211_ap_reg_power { + IEEE80211_REG_UNSET_AP, + IEEE80211_REG_LPI_AP, + IEEE80211_REG_SP_AP, + IEEE80211_REG_VLP_AP, +}; + +/* + * 802.11ax-2021, Table 9-277-Meaning of Maximum Transmit Power Count subfield + * if Maximum Transmit Power Interpretation subfield is 1 or 3 + */ +#define IEEE80211_MAX_NUM_PWR_LEVEL 8 + +/* + * 802.11ax-2021, Table 9-275a-Maximum Transmit Power Interpretation subfield + * encoding (4) * Table E-12-Regulatory Info subfield encoding in the + * United States (2) + */ +#define IEEE80211_TPE_MAX_IE_NUM 8 + +/* 802.11ax-2021, 9.4.2.161 Transmit Power Envelope element */ +struct ieee80211_tx_pwr_env { + uint8_t tx_power_info; + uint8_t tx_power[IEEE80211_MAX_NUM_PWR_LEVEL]; +}; + +/* 802.11ax-2021, Figure 9-617-Transmit Power Information field format */ +/* These are field masks (3bit/3bit/2bit). */ +#define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x07 +#define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38 +#define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xc0 + +/* + * 802.11ax-2021, Table 9-275a-Maximum Transmit Power Interpretation subfield + * encoding + */ +enum ieee80211_tx_pwr_interpretation_subfield_enc { + IEEE80211_TPE_LOCAL_EIRP, + IEEE80211_TPE_LOCAL_EIRP_PSD, + IEEE80211_TPE_REG_CLIENT_EIRP, + IEEE80211_TPE_REG_CLIENT_EIRP_PSD, +}; + +enum ieee80211_tx_pwr_category_6ghz { + IEEE80211_TPE_CAT_6GHZ_DEFAULT, +}; + +/* 802.11-2020, 9.4.2.27 BSS Load element */ +struct ieee80211_bss_load_elem { + uint16_t sta_count; + uint8_t channel_util; + uint16_t avail_adm_capa; +}; + +struct ieee80211_p2p_noa_desc { + uint32_t count; /* uint8_t ? */ + uint32_t duration; + uint32_t interval; + uint32_t start_time; +}; + +struct ieee80211_p2p_noa_attr { + uint8_t index; + uint8_t oppps_ctwindow; + struct ieee80211_p2p_noa_desc desc[4]; +}; + + +/* net80211: IEEE80211_IS_CTL() */ +static __inline bool +ieee80211_is_ctl(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_TYPE_CTL); + + return (fc == v); +} + +/* net80211: IEEE80211_IS_DATA() */ +static __inline bool +ieee80211_is_data(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +/* net80211: IEEE80211_IS_QOSDATA() */ +static __inline bool +ieee80211_is_data_qos(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +/* net80211: IEEE80211_IS_MGMT() */ +static __inline bool +ieee80211_is_mgmt(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + + +/* Derived from net80211::ieee80211_anyhdrsize. */ +static __inline unsigned int +ieee80211_hdrlen(__le16 fc) +{ + unsigned int size; + + if (ieee80211_is_ctl(fc)) { + switch (fc & htole16(IEEE80211_FC0_SUBTYPE_MASK)) { + case htole16(IEEE80211_FC0_SUBTYPE_CTS): + case htole16(IEEE80211_FC0_SUBTYPE_ACK): + return sizeof(struct ieee80211_frame_ack); + case htole16(IEEE80211_FC0_SUBTYPE_BAR): + return sizeof(struct ieee80211_frame_bar); + } + return (sizeof(struct ieee80211_frame_min)); + } + + size = sizeof(struct ieee80211_frame); + if (ieee80211_is_data(fc)) { + if ((fc & htole16(IEEE80211_FC1_DIR_MASK << 8)) == + htole16(IEEE80211_FC1_DIR_DSTODS << 8)) + size += IEEE80211_ADDR_LEN; + if ((fc & htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | + IEEE80211_FC0_TYPE_MASK)) == + htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | + IEEE80211_FC0_TYPE_DATA)) + size += sizeof(uint16_t); + } + + if (ieee80211_is_mgmt(fc)) { +#ifdef __notyet__ + printf("XXX-BZ %s: TODO? fc %#04x size %u\n", + __func__, fc, size); +#endif + ; + } + + return (size); +} + +static inline bool +ieee80211_is_trigger(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_TRIGGER | IEEE80211_FC0_TYPE_CTL); + + return (fc == v); +} + +static __inline bool +ieee80211_is_action(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_ACTION | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_probe_resp(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_PROBE_RESP | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_auth(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_AUTH | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_assoc_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_ASSOC_REQ | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_assoc_resp(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_ASSOC_RESP | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_reassoc_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_REASSOC_REQ | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_reassoc_resp(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_REASSOC_RESP | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_disassoc(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_DISASSOC | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_data_present(__le16 fc) +{ + __le16 v; + + /* If it is a data frame and NODATA is not present. */ + fc &= htole16(IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_NODATA); + v = htole16(IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +static __inline bool +ieee80211_is_deauth(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_DEAUTH | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_beacon(__le16 fc) +{ + __le16 v; + + /* + * For as much as I get it this comes in LE and unlike FreeBSD + * where we get the entire frame header and u8[], here we get the + * 9.2.4.1 Frame Control field only. Mask and compare. + */ + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_BEACON | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + + +static __inline bool +ieee80211_is_probe_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_PROBE_REQ | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_has_protected(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_PROTECTED << 8)); +} + +static __inline bool +ieee80211_is_back_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_BAR | IEEE80211_FC0_TYPE_CTL); + + return (fc == v); +} + +static __inline bool +ieee80211_is_bufferable_mmpdu(struct sk_buff *skb) +{ + struct ieee80211_mgmt *mgmt; + __le16 fc; + + mgmt = (struct ieee80211_mgmt *)skb->data; + fc = mgmt->frame_control; + + /* 11.2.2 Bufferable MMPDUs, 80211-2020. */ + /* XXX we do not care about IBSS yet. */ + + if (!ieee80211_is_mgmt(fc)) + return (false); + if (ieee80211_is_action(fc)) /* XXX FTM? */ + return (true); /* XXX false? */ + if (ieee80211_is_disassoc(fc)) + return (true); + if (ieee80211_is_deauth(fc)) + return (true); + + TODO(); + + return (false); +} + +static __inline bool +ieee80211_is_nullfunc(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_NODATA | IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +static __inline bool +ieee80211_is_qos_nullfunc(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_QOS_NULL | IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +static __inline bool +ieee80211_is_any_nullfunc(__le16 fc) +{ + + return (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)); +} + +static inline bool +ieee80211_is_pspoll(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_PS_POLL | IEEE80211_FC0_TYPE_CTL); + + return (fc == v); +} + +static __inline bool +ieee80211_has_a4(__le16 fc) +{ + __le16 v; + + fc &= htole16((IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_DIR_FROMDS) << 8); + v = htole16((IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_DIR_FROMDS) << 8); + + return (fc == v); +} + +static __inline bool +ieee80211_has_order(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_ORDER << 8)); +} + +static __inline bool +ieee80211_has_retry(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_RETRY << 8)); +} + + +static __inline bool +ieee80211_has_fromds(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_DIR_FROMDS << 8)); +} + +static __inline bool +ieee80211_has_tods(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_DIR_TODS << 8)); +} + +static __inline uint8_t * +ieee80211_get_SA(struct ieee80211_hdr *hdr) +{ + + if (ieee80211_has_a4(hdr->frame_control)) + return (hdr->addr4); + if (ieee80211_has_fromds(hdr->frame_control)) + return (hdr->addr3); + return (hdr->addr2); +} + +static __inline uint8_t * +ieee80211_get_DA(struct ieee80211_hdr *hdr) +{ + + if (ieee80211_has_tods(hdr->frame_control)) + return (hdr->addr3); + return (hdr->addr1); +} + +static __inline bool +ieee80211_is_frag(struct ieee80211_hdr *hdr) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_first_frag(__le16 fc) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_ftm(struct sk_buff *skb) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_timing_measurement(struct sk_buff *skb) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_has_pm(__le16 fc) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_has_morefrags(__le16 fc) +{ + + fc &= htole16(IEEE80211_FC1_MORE_FRAG << 8); + return (fc != 0); +} + +static __inline u8 * +ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_a4(hdr->frame_control)) + return (u8 *)hdr + 30; + else + return (u8 *)hdr + 24; +} + +#endif /* _LINUXKPI_LINUX_IEEE80211_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/if_arp.h b/sys/compat/linuxkpi/common/include/linux/if_arp.h index 9235e2dff9cf..6201c3a1c284 100644 --- a/sys/compat/linuxkpi/common/include/linux/if_arp.h +++ b/sys/compat/linuxkpi/common/include/linux/if_arp.h @@ -25,13 +25,11 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IF_ARP_H_ -#define _LINUX_IF_ARP_H_ +#ifndef _LINUXKPI_LINUX_IF_ARP_H_ +#define _LINUXKPI_LINUX_IF_ARP_H_ #include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> #include <net/if_arp.h> -#endif /* _LINUX_IF_ARP_H_ */ +#endif /* _LINUXKPI_LINUX_IF_ARP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/if_ether.h b/sys/compat/linuxkpi/common/include/linux/if_ether.h index 187446c4c591..6676e8fc142f 100644 --- a/sys/compat/linuxkpi/common/include/linux/if_ether.h +++ b/sys/compat/linuxkpi/common/include/linux/if_ether.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2021-2022 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,13 +29,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IF_ETHER_H_ -#define _LINUX_IF_ETHER_H_ +#ifndef _LINUXKPI_LINUX_IF_ETHER_H_ +#define _LINUXKPI_LINUX_IF_ETHER_H_ #include <linux/types.h> +#include <linux/skbuff.h> #include <net/ethernet.h> @@ -55,6 +58,9 @@ #define ETH_P_8021AD ETHERTYPE_QINQ #define ETH_P_PAE ETHERTYPE_PAE #define ETH_P_802_2 ETHERTYPE_8023 +#define ETH_P_IPX ETHERTYPE_IPX +#define ETH_P_AARP ETHERTYPE_AARP +#define ETH_P_802_3_MIN 0x05DD /* See comment in sys/net/ethernet.h */ #define ETH_P_LINK_CTL 0x886C /* ITU-T G.989.2 */ #define ETH_P_TDLS 0x890D /* 802.11z-2010, see wpa. */ @@ -64,4 +70,13 @@ struct ethhdr { uint16_t h_proto; } __packed; -#endif /* _LINUX_IF_ETHER_H_ */ +static inline struct ethhdr * +eth_hdr(const struct sk_buff *skb) +{ + struct ethhdr *hdr; + + hdr = (struct ethhdr *)skb_mac_header(skb); + return (hdr); +} + +#endif /* _LINUXKPI_LINUX_IF_ETHER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/if_vlan.h b/sys/compat/linuxkpi/common/include/linux/if_vlan.h index 4d8b8926a032..3d1c61db1882 100644 --- a/sys/compat/linuxkpi/common/include/linux/if_vlan.h +++ b/sys/compat/linuxkpi/common/include/linux/if_vlan.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IF_VLAN_H_ -#define _LINUX_IF_VLAN_H_ +#ifndef _LINUXKPI_LINUX_IF_VLAN_H_ +#define _LINUXKPI_LINUX_IF_VLAN_H_ #include <sys/types.h> #include <sys/socket.h> @@ -44,7 +42,7 @@ static inline int is_vlan_dev(struct ifnet *ifp) { - return (ifp->if_type == IFT_L2VLAN); + return (if_gettype(ifp) == IFT_L2VLAN); } static inline uint16_t @@ -56,4 +54,4 @@ vlan_dev_vlan_id(struct ifnet *ifp) return (0); } -#endif /* _LINUX_IF_VLAN_H_ */ +#endif /* _LINUXKPI_LINUX_IF_VLAN_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/in.h b/sys/compat/linuxkpi/common/include/linux/in.h index 96d66fbae2f0..5cc92416c7da 100644 --- a/sys/compat/linuxkpi/common/include/linux/in.h +++ b/sys/compat/linuxkpi/common/include/linux/in.h @@ -25,15 +25,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IN_H_ -#define _LINUX_IN_H_ +#ifndef _LINUXKPI_LINUX_IN_H_ +#define _LINUXKPI_LINUX_IN_H_ #include "opt_inet.h" -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/systm.h> #include <netinet/in.h> @@ -44,4 +41,4 @@ #define ipv4_is_multicast(be) IN_MULTICAST(ntohl(be)) #define ipv4_is_lbcast(be) ((be) == INADDR_BROADCAST) -#endif /* _LINUX_IN_H_ */ +#endif /* _LINUXKPI_LINUX_IN_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/in6.h b/sys/compat/linuxkpi/common/include/linux/in6.h index c72bfb6f0b88..79be45b6819a 100644 --- a/sys/compat/linuxkpi/common/include/linux/in6.h +++ b/sys/compat/linuxkpi/common/include/linux/in6.h @@ -25,12 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IN6_H_ -#define _LINUX_IN6_H_ +#ifndef _LINUXKPI_LINUX_IN6_H_ +#define _LINUXKPI_LINUX_IN6_H_ #include "opt_inet6.h" -#endif /* _LINUX_IN6_H_ */ +#endif /* _LINUXKPI_LINUX_IN6_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/inetdevice.h b/sys/compat/linuxkpi/common/include/linux/inetdevice.h index 41852e8fed81..ea256cd084a8 100644 --- a/sys/compat/linuxkpi/common/include/linux/inetdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/inetdevice.h @@ -1,6 +1,6 @@ -#ifndef _LINUX_INETDEVICE_H_ -#define _LINUX_INETDEVICE_H_ +#ifndef _LINUXKPI_LINUX_INETDEVICE_H_ +#define _LINUXKPI_LINUX_INETDEVICE_H_ #include <linux/netdevice.h> -#endif /* _LINUX_INETDEVICE_H_ */ +#endif /* _LINUXKPI_LINUX_INETDEVICE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/interrupt.h b/sys/compat/linuxkpi/common/include/linux/interrupt.h index 964b95edb43f..dfd9816da8be 100644 --- a/sys/compat/linuxkpi/common/include/linux/interrupt.h +++ b/sys/compat/linuxkpi/common/include/linux/interrupt.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_INTERRUPT_H_ -#define _LINUX_INTERRUPT_H_ +#ifndef _LINUXKPI_LINUX_INTERRUPT_H_ +#define _LINUXKPI_LINUX_INTERRUPT_H_ #include <linux/cpu.h> #include <linux/device.h> @@ -42,7 +40,12 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); -#define IRQF_SHARED RF_SHAREABLE +#define IRQF_SHARED 0x0004 /* Historically */ +#define IRQF_NOBALANCING 0 + +#define IRQ_DISABLE_UNLAZY 0 + +#define IRQ_NOTCONNECTED (1U << 31) int lkpi_request_irq(struct device *, unsigned int, irq_handler_t, irq_handler_t, unsigned long, const char *, void *); @@ -71,6 +74,14 @@ request_threaded_irq(int irq, irq_handler_t handler, } static inline int +devm_request_irq(struct device *dev, int irq, + irq_handler_t handler, unsigned long flags, const char *name, void *arg) +{ + + return (lkpi_request_irq(dev, irq, handler, NULL, flags, name, arg)); +} + +static inline int devm_request_threaded_irq(struct device *dev, int irq, irq_handler_t handler, irq_handler_t thread_handler, unsigned long flags, const char *name, void *arg) @@ -92,6 +103,12 @@ disable_irq(unsigned int irq) lkpi_disable_irq(irq); } +static inline void +disable_irq_nosync(unsigned int irq) +{ + lkpi_disable_irq(irq); +} + static inline int bind_irq_to_cpu(unsigned int irq, int cpu_id) { @@ -111,7 +128,7 @@ devm_free_irq(struct device *xdev, unsigned int irq, void *p) } static inline int -irq_set_affinity_hint(int vector, cpumask_t *mask) +irq_set_affinity_hint(int vector, const cpumask_t *mask) { int error; @@ -123,10 +140,24 @@ irq_set_affinity_hint(int vector, cpumask_t *mask) return (-error); } +static inline struct msi_desc * +irq_get_msi_desc(unsigned int irq) +{ + + return (lkpi_pci_msi_desc_alloc(irq)); +} + +static inline void +irq_set_status_flags(unsigned int irq __unused, unsigned long flags __unused) +{ +} + /* * LinuxKPI tasklet support */ +struct tasklet_struct; typedef void tasklet_func_t(unsigned long); +typedef void tasklet_callback_t(struct tasklet_struct *); struct tasklet_struct { TAILQ_ENTRY(tasklet_struct) entry; @@ -135,6 +166,8 @@ struct tasklet_struct { volatile u_int tasklet_state; atomic_t count; unsigned long data; + tasklet_callback_t *callback; + bool use_callback; }; #define DECLARE_TASKLET(_name, _func, _data) \ @@ -142,6 +175,11 @@ struct tasklet_struct _name = { .func = (_func), .data = (_data) } #define tasklet_hi_schedule(t) tasklet_schedule(t) +/* Some other compat code in the tree has this defined as well. */ +#define from_tasklet(_dev, _t, _field) \ + container_of(_t, typeof(*(_dev)), _field) + +void tasklet_setup(struct tasklet_struct *, tasklet_callback_t *); extern void tasklet_schedule(struct tasklet_struct *); extern void tasklet_kill(struct tasklet_struct *); extern void tasklet_init(struct tasklet_struct *, tasklet_func_t *, @@ -152,5 +190,6 @@ extern void tasklet_disable_nosync(struct tasklet_struct *); extern int tasklet_trylock(struct tasklet_struct *); extern void tasklet_unlock(struct tasklet_struct *); extern void tasklet_unlock_wait(struct tasklet_struct *ts); +#define tasklet_unlock_spin_wait(ts) tasklet_unlock_wait(ts) -#endif /* _LINUX_INTERRUPT_H_ */ +#endif /* _LINUXKPI_LINUX_INTERRUPT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/interval_tree.h b/sys/compat/linuxkpi/common/include/linux/interval_tree.h new file mode 100644 index 000000000000..1eb8a2fb9181 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/interval_tree.h @@ -0,0 +1,55 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_INTERVAL_TREE_H +#define _LINUXKPI_LINUX_INTERVAL_TREE_H + +#include <linux/rbtree.h> + +struct interval_tree_node { + struct rb_node rb; + unsigned long start; + unsigned long last; +}; + +#define interval_tree_iter_first(...) \ + lkpi_interval_tree_iter_first(__VA_ARGS__) +#define interval_tree_iter_next(...) \ + lkpi_interval_tree_iter_next(__VA_ARGS__) +#define interval_tree_insert(...) lkpi_interval_tree_insert(__VA_ARGS__) +#define interval_tree_remove(...) lkpi_interval_tree_remove(__VA_ARGS__) + +struct interval_tree_node *lkpi_interval_tree_iter_first( + struct rb_root_cached *, unsigned long, unsigned long); +struct interval_tree_node *lkpi_interval_tree_iter_next( + struct interval_tree_node *, unsigned long, unsigned long); +void lkpi_interval_tree_insert(struct interval_tree_node *, + struct rb_root_cached *); +void lkpi_interval_tree_remove(struct interval_tree_node *, + struct rb_root_cached *); + +#endif /* _LINUXKPI_LINUX_INTERVAL_TREE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/interval_tree_generic.h b/sys/compat/linuxkpi/common/include/linux/interval_tree_generic.h new file mode 100644 index 000000000000..3ed6e105cbda --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/interval_tree_generic.h @@ -0,0 +1,99 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Mark Kettenis <kettenis@OpenBSD.org> + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/rbtree.h> + +#define INTERVAL_TREE_DEFINE(type, field, valtype, dummy, START, LAST, \ + attr, name) \ + __IT_DEFINE_ITER_FROM(type, field, valtype, START, LAST, name) \ + __IT_DEFINE_ITER_FIRST(type, valtype, attr, name) \ + __IT_DEFINE_ITER_NEXT(type, field, valtype, attr, name) \ + __IT_DEFINE_INSERT(type, field, START, attr, name) \ + __IT_DEFINE_REMOVE(type, field, attr, name) + +#define __IT_DEFINE_ITER_FROM(type, field, valtype, START, LAST, name) \ +static inline type * \ +name##_iter_from(struct rb_node *rb, valtype start, valtype last) \ +{ \ + type *node; \ + \ + while (rb != NULL) { \ + node = rb_entry(rb, type, field); \ + if (LAST(node) >= start && START(node) <= last) \ + return (node); \ + else if (START(node) > last) \ + break; \ + rb = rb_next(rb); \ + } \ + return (NULL); \ +} + +#define __IT_DEFINE_ITER_FIRST(type, valtype, attr, name) \ +attr type * \ +name##_iter_first(struct rb_root_cached *root, valtype start, valtype last) \ +{ \ + return (name##_iter_from(rb_first_cached(root), start, last)); \ +} + +#define __IT_DEFINE_ITER_NEXT(type, field, valtype, attr, name) \ +attr type * \ +name##_iter_next(type *node, valtype start, valtype last) \ +{ \ + return (name##_iter_from(rb_next(&node->field), start, last)); \ +} + +#define __IT_DEFINE_INSERT(type, field, START, attr, name) \ +attr void \ +name##_insert(type *node, struct rb_root_cached *root) \ +{ \ + struct rb_node **iter = &root->rb_root.rb_node; \ + struct rb_node *parent = NULL; \ + type *iter_node; \ + bool min_entry = true; \ + \ + while (*iter != NULL) { \ + parent = *iter; \ + iter_node = rb_entry(parent, type, field); \ + if (START(node) < START(iter_node)) \ + iter = &parent->rb_left; \ + else { \ + iter = &parent->rb_right; \ + min_entry = false; \ + } \ + } \ + \ + rb_link_node(&node->field, parent, iter); \ + rb_insert_color_cached(&node->field, root, min_entry); \ +} + +#define __IT_DEFINE_REMOVE(type, field, attr, name) \ +attr void \ +name##_remove(type *node, struct rb_root_cached *root) \ +{ \ + rb_erase_cached(&node->field, root); \ +} diff --git a/sys/compat/linuxkpi/common/include/linux/io-64-nonatomic-lo-hi.h b/sys/compat/linuxkpi/common/include/linux/io-64-nonatomic-lo-hi.h new file mode 100644 index 000000000000..844b3ef171d5 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/io-64-nonatomic-lo-hi.h @@ -0,0 +1,65 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Felix Palmen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _LINUXKPI_LINUX_IO_64_NONATOMIC_LO_HI_H_ +#define _LINUXKPI_LINUX_IO_64_NONATOMIC_LO_HI_H_ + +#include <linux/io.h> + +static inline uint64_t +lo_hi_readq(const volatile void *addr) +{ + const volatile uint32_t *p = addr; + uint32_t l, h; + + __io_br(); + l = le32toh(__raw_readl(p)); + h = le32toh(__raw_readl(p + 1)); + __io_ar(); + + return (l + ((uint64_t)h << 32)); +} + +static inline void +lo_hi_writeq(uint64_t v, volatile void *addr) +{ + volatile uint32_t *p = addr; + + __io_bw(); + __raw_writel(htole32(v), p); + __raw_writel(htole32(v >> 32), p + 1); + __io_aw(); +} + +#ifndef readq +#define readq(addr) lo_hi_readq(addr) +#endif + +#ifndef writeq +#define writeq(v, addr) lo_hi_writeq(v, addr) +#endif + +#endif /* _LINUXKPI_LINUX_IO_64_NONATOMIC_LO_HI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/io-mapping.h b/sys/compat/linuxkpi/common/include/linux/io-mapping.h index 12643be9c6e6..f5f2fbc5c2cb 100644 --- a/sys/compat/linuxkpi/common/include/linux/io-mapping.h +++ b/sys/compat/linuxkpi/common/include/linux/io-mapping.h @@ -25,18 +25,17 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IO_MAPPING_H_ -#define _LINUX_IO_MAPPING_H_ +#ifndef _LINUXKPI_LINUX_IO_MAPPING_H_ +#define _LINUXKPI_LINUX_IO_MAPPING_H_ #include <sys/types.h> #include <machine/vm.h> #include <linux/types.h> #include <linux/io.h> +#include <linux/mm.h> #include <linux/slab.h> struct io_mapping { @@ -46,6 +45,8 @@ struct io_mapping { vm_memattr_t attr; }; +struct io_mapping *io_mapping_create_wc(resource_size_t base, unsigned long size); + static inline struct io_mapping * io_mapping_init_wc(struct io_mapping *mapping, resource_size_t base, unsigned long size) @@ -63,17 +64,6 @@ io_mapping_init_wc(struct io_mapping *mapping, resource_size_t base, return (mapping); } -static inline struct io_mapping * -io_mapping_create_wc(resource_size_t base, unsigned long size) -{ - struct io_mapping *mapping; - - mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); - if (mapping == NULL) - return (NULL); - return (io_mapping_init_wc(mapping, base, size)); -} - static inline void io_mapping_fini(struct io_mapping *mapping) { @@ -102,6 +92,18 @@ io_mapping_unmap_atomic(void *vaddr) } static inline void * +io_mapping_map_local_wc(struct io_mapping *mapping, unsigned long offset) +{ + + return (io_mapping_map_atomic_wc(mapping, offset)); +} + +static inline void +io_mapping_unmap_local(void *vaddr __unused) +{ +} + +static inline void * io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset, unsigned long size) { @@ -109,9 +111,20 @@ io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset, return ((char *)mapping->mem + offset); } +int lkpi_io_mapping_map_user(struct io_mapping *iomap, + struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, + unsigned long size); + +static inline int +io_mapping_map_user(struct io_mapping *iomap, struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn, unsigned long size) +{ + return (lkpi_io_mapping_map_user(iomap, vma, addr, pfn, size)); +} + static inline void io_mapping_unmap(void *vaddr) { } -#endif /* _LINUX_IO_MAPPING_H_ */ +#endif /* _LINUXKPI_LINUX_IO_MAPPING_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/io.h b/sys/compat/linuxkpi/common/include/linux/io.h index e402ebed0665..2d6fef4e7c52 100644 --- a/sys/compat/linuxkpi/common/include/linux/io.h +++ b/sys/compat/linuxkpi/common/include/linux/io.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IO_H_ -#define _LINUX_IO_H_ +#ifndef _LINUXKPI_LINUX_IO_H_ +#define _LINUXKPI_LINUX_IO_H_ #include <sys/endian.h> #include <sys/types.h> @@ -37,7 +35,12 @@ #include <machine/vm.h> #include <linux/compiler.h> +#include <linux/err.h> +#include <asm-generic/io.h> #include <linux/types.h> +#if !defined(__arm__) +#include <asm/set_memory.h> +#endif /* * XXX This is all x86 specific. It should be bus space access. @@ -348,6 +351,16 @@ ioread32be(const volatile void *addr) } #define ioread32be(addr) ioread32be(addr) +#ifdef __LP64__ +#undef ioread64 +static inline uint64_t +ioread64(const volatile void *addr) +{ + return (readq(addr)); +} +#define ioread64(addr) ioread64(addr) +#endif + #undef iowrite8 static inline void iowrite8(uint8_t v, volatile void *addr) @@ -383,19 +396,26 @@ iowrite32be(uint32_t v, volatile void *addr) #define iowrite32be(v, addr) iowrite32be(v, addr) #if defined(__i386__) || defined(__amd64__) -static inline void -_outb(u_char data, u_int port) -{ - __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); -} +#define _outb(data, port) outb((data), (port)) #endif #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || defined(__aarch64__) || defined(__riscv) void *_ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr); #else -#define _ioremap_attr(...) NULL +static __inline void * +_ioremap_attr(vm_paddr_t _phys_addr, unsigned long _size, int _attr) +{ + return (NULL); +} #endif +struct device; +static inline void * +devm_ioremap(struct device *dev, resource_size_t offset, resource_size_t size) +{ + return (NULL); +} + #ifdef VM_MEMATTR_DEVICE #define ioremap_nocache(addr, size) \ _ioremap_attr((addr), (size), VM_MEMATTR_DEVICE) @@ -417,7 +437,7 @@ void *_ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr); #else #define ioremap_wc(addr, size) ioremap_nocache(addr, size) #endif -#define ioremap_wb(addr, size) \ +#define ioremap_cache(addr, size) \ _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_BACK) void iounmap(void *addr); @@ -426,9 +446,9 @@ void iounmap(void *addr); #define memcpy_toio(a, b, c) memcpy((a), (b), (c)) static inline void -__iowrite32_copy(void *to, void *from, size_t count) +__iowrite32_copy(void *to, const void *from, size_t count) { - uint32_t *src; + const uint32_t *src; uint32_t *dst; int i; @@ -437,10 +457,10 @@ __iowrite32_copy(void *to, void *from, size_t count) } static inline void -__iowrite64_copy(void *to, void *from, size_t count) +__iowrite64_copy(void *to, const void *from, size_t count) { #ifdef __LP64__ - uint64_t *src; + const uint64_t *src; uint64_t *dst; int i; @@ -451,6 +471,32 @@ __iowrite64_copy(void *to, void *from, size_t count) #endif } +static inline void +__ioread32_copy(void *to, const void *from, size_t count) +{ + const uint32_t *src; + uint32_t *dst; + int i; + + for (i = 0, src = from, dst = to; i < count; i++, src++, dst++) + *dst = __raw_readl(src); +} + +static inline void +__ioread64_copy(void *to, const void *from, size_t count) +{ +#ifdef __LP64__ + const uint64_t *src; + uint64_t *dst; + int i; + + for (i = 0, src = from, dst = to; i < count; i++, src++, dst++) + *dst = __raw_readq(src); +#else + __ioread32_copy(to, from, count * 2); +#endif +} + enum { MEMREMAP_WB = 1 << 0, MEMREMAP_WT = 1 << 1, @@ -463,7 +509,7 @@ memremap(resource_size_t offset, size_t size, unsigned long flags) void *addr = NULL; if ((flags & MEMREMAP_WB) && - (addr = ioremap_wb(offset, size)) != NULL) + (addr = ioremap_cache(offset, size)) != NULL) goto done; if ((flags & MEMREMAP_WT) && (addr = ioremap_wt(offset, size)) != NULL) @@ -482,4 +528,39 @@ memunmap(void *addr) iounmap(addr); } -#endif /* _LINUX_IO_H_ */ +#define IOMEM_ERR_PTR(err) (void __iomem *)ERR_PTR(err) + +#define __MTRR_ID_BASE 1 +int lkpi_arch_phys_wc_add(unsigned long, unsigned long); +void lkpi_arch_phys_wc_del(int); +#define arch_phys_wc_add(...) lkpi_arch_phys_wc_add(__VA_ARGS__) +#define arch_phys_wc_del(...) lkpi_arch_phys_wc_del(__VA_ARGS__) +#define arch_phys_wc_index(x) \ + (((x) < __MTRR_ID_BASE) ? -1 : ((x) - __MTRR_ID_BASE)) + +static inline int +arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size) +{ +#if defined(__amd64__) + vm_offset_t va; + + va = PHYS_TO_DMAP(start); + return (-pmap_change_attr(va, size, VM_MEMATTR_WRITE_COMBINING)); +#else + return (0); +#endif +} + +static inline void +arch_io_free_memtype_wc(resource_size_t start, resource_size_t size) +{ +#if defined(__amd64__) + vm_offset_t va; + + va = PHYS_TO_DMAP(start); + + pmap_change_attr(va, size, VM_MEMATTR_WRITE_BACK); +#endif +} + +#endif /* _LINUXKPI_LINUX_IO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ioctl.h b/sys/compat/linuxkpi/common/include/linux/ioctl.h index fcdb5c547e73..77c01224e6a5 100644 --- a/sys/compat/linuxkpi/common/include/linux/ioctl.h +++ b/sys/compat/linuxkpi/common/include/linux/ioctl.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IOCTL_H_ -#define _LINUX_IOCTL_H_ +#ifndef _LINUXKPI_LINUX_IOCTL_H_ +#define _LINUXKPI_LINUX_IOCTL_H_ #include <sys/ioccom.h> @@ -37,4 +35,4 @@ #define _IOC_TYPE(cmd) IOCGROUP(cmd) #define _IOC_NR(cmd) ((cmd) & 0xff) -#endif /* _LINUX_IOCTL_H_ */ +#endif /* _LINUXKPI_LINUX_IOCTL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/iommu.h b/sys/compat/linuxkpi/common/include/linux/iommu.h new file mode 100644 index 000000000000..391d9778a0c8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/iommu.h @@ -0,0 +1,29 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_IOMMU_H_ +#define _LINUXKPI_LINUX_IOMMU_H_ + +#include <linux/device.h> + +#define __IOMMU_DOMAIN_PAGING (1U << 0) +#define __IOMMU_DOMAIN_DMA_API (1U << 1) +#define __IOMMU_DOMAIN_PT (1U << 2) +#define __IOMMU_DOMAIN_DMA_FQ (1U << 3) + +#define IOMMU_DOMAIN_BLOCKED (0U) +#define IOMMU_DOMAIN_IDENTITY (__IOMMU_DOMAIN_PT) +#define IOMMU_DOMAIN_UNMANAGED (__IOMMU_DOMAIN_PAGING) +#define IOMMU_DOMAIN_DMA (__IOMMU_DOMAIN_PAGING | __IOMMU_DOMAIN_DMA_API) +#define IOMMU_DOMAIN_DMA_FQ (__IOMMU_DOMAIN_PAGING | __IOMMU_DOMAIN_DMA_API | __IOMMU_DOMAIN_DMA_FQ) + +struct iommu_domain { + unsigned int type; +}; + +static inline struct iommu_domain * +iommu_get_domain_for_dev(struct device *dev __unused) +{ + return (NULL); +} + +#endif /* _LINUXKPI_LINUX_IOMMU_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/iopoll.h b/sys/compat/linuxkpi/common/include/linux/iopoll.h index ea876042eab6..8d0498a26da1 100644 --- a/sys/compat/linuxkpi/common/include/linux/iopoll.h +++ b/sys/compat/linuxkpi/common/include/linux/iopoll.h @@ -23,12 +23,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUXKPI_LINUX_IOPOLL_H -#define __LINUXKPI_LINUX_IOPOLL_H +#ifndef _LINUXKPI_LINUX_IOPOLL_H +#define _LINUXKPI_LINUX_IOPOLL_H #include <sys/types.h> #include <sys/time.h> @@ -61,6 +59,9 @@ (_cond) ? 0 : (-ETIMEDOUT); \ }) +#define readx_poll_timeout(_pollfp, _addr, _var, _cond, _us, _to) \ + read_poll_timeout(_pollfp, _var, _cond, _us, _to, false, _addr) + #define read_poll_timeout_atomic(_pollfp, _var, _cond, _us, _to, _early_sleep, ...) \ ({ \ struct timeval __now, __end; \ @@ -88,4 +89,4 @@ (_cond) ? 0 : (-ETIMEDOUT); \ }) -#endif /* __LINUXKPI_LINUX_IOPOLL_H */ +#endif /* _LINUXKPI_LINUX_IOPOLL_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/ioport.h b/sys/compat/linuxkpi/common/include/linux/ioport.h new file mode 100644 index 000000000000..763af2de7c4f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ioport.h @@ -0,0 +1,58 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_IOPORT_H +#define _LINUXKPI_LINUX_IOPORT_H + +#include <linux/compiler.h> +#include <linux/types.h> + +#define DEFINE_RES_MEM(_start, _size) \ + (struct resource) { \ + .start = (_start), \ + .end = (_start) + (_size) - 1, \ + } + +struct resource { + resource_size_t start; + resource_size_t end; + const char *name; +}; + +static inline resource_size_t +resource_size(const struct resource *r) +{ + return (r->end - r->start + 1); +} + +static inline bool +resource_contains(struct resource *a, struct resource *b) +{ + return (a->start <= b->start && a->end >= b->end); +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/iosys-map.h b/sys/compat/linuxkpi/common/include/linux/iosys-map.h new file mode 100644 index 000000000000..66c442b8668f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/iosys-map.h @@ -0,0 +1,161 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_IOSYS_MAP_H +#define _LINUXKPI_LINUX_IOSYS_MAP_H + +#include <linux/io.h> +#include <linux/string.h> + +struct iosys_map { + union { + void *vaddr_iomem; + void *vaddr; + }; + bool is_iomem; +#ifdef __OpenBSD__ + bus_space_handle_t bsh; + bus_size_t size; +#endif +}; + +#define IOSYS_MAP_INIT_OFFSET(_ism_src_p, _off) ({ \ + struct iosys_map ism_dst = *(_ism_src_p); \ + iosys_map_incr(&ism_dst, _off); \ + ism_dst; \ +}) + +static inline void +iosys_map_incr(struct iosys_map *ism, size_t n) +{ + if (ism->is_iomem) + ism->vaddr_iomem += n; + else + ism->vaddr += n; +} + +static inline void +iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src, + size_t len) +{ + if (ism->is_iomem) + memcpy_toio(ism->vaddr_iomem + off, src, len); + else + memcpy(ism->vaddr + off, src, len); +} + +static inline bool +iosys_map_is_null(const struct iosys_map *ism) +{ + if (ism->is_iomem) + return (ism->vaddr_iomem == NULL); + else + return (ism->vaddr == NULL); +} + +static inline bool +iosys_map_is_set(const struct iosys_map *ism) +{ + if (ism->is_iomem) + return (ism->vaddr_iomem != NULL); + else + return (ism->vaddr != NULL); +} + +static inline bool +iosys_map_is_equal(const struct iosys_map *ism_a, + const struct iosys_map *ism_b) +{ + if (ism_a->is_iomem != ism_b->is_iomem) + return (false); + + if (ism_a->is_iomem) + return (ism_a->vaddr_iomem == ism_b->vaddr_iomem); + else + return (ism_a->vaddr == ism_b->vaddr); +} + +static inline void +iosys_map_clear(struct iosys_map *ism) +{ + if (ism->is_iomem) { + ism->vaddr_iomem = NULL; + ism->is_iomem = false; + } else { + ism->vaddr = NULL; + } +} + +static inline void +iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr) +{ + ism->vaddr_iomem = addr; + ism->is_iomem = true; +} + +static inline void +iosys_map_set_vaddr(struct iosys_map *ism, void *addr) +{ + ism->vaddr = addr; + ism->is_iomem = false; +} + +static inline void +iosys_map_memset(struct iosys_map *ism, size_t off, int value, size_t len) +{ + if (ism->is_iomem) + memset_io(ism->vaddr_iomem + off, value, len); + else + memset(ism->vaddr + off, value, len); +} + +#ifdef __LP64__ +#define _iosys_map_readq(_addr) readq(_addr) +#define _iosys_map_writeq(_val, _addr) writeq(_val, _addr) +#else +#define _iosys_map_readq(_addr) ({ \ + uint64_t val; \ + memcpy_fromio(&val, _addr, sizeof(uint64_t)); \ + val; \ +}) +#define _iosys_map_writeq(_val, _addr) \ + memcpy_toio(_addr, &(_val), sizeof(uint64_t)) +#endif + +#define iosys_map_rd(_ism, _off, _type) ({ \ + _type val; \ + if ((_ism)->is_iomem) { \ + void *addr = (_ism)->vaddr_iomem + (_off); \ + val = _Generic(val, \ + uint8_t : readb(addr), \ + uint16_t: readw(addr), \ + uint32_t: readl(addr), \ + uint64_t: _iosys_map_readq(addr)); \ + } else \ + val = READ_ONCE(*(_type *)((_ism)->vaddr + (_off))); \ + val; \ +}) +#define iosys_map_wr(_ism, _off, _type, _val) ({ \ + _type val = (_val); \ + if ((_ism)->is_iomem) { \ + void *addr = (_ism)->vaddr_iomem + (_off); \ + _Generic(val, \ + uint8_t : writeb(val, addr), \ + uint16_t: writew(val, addr), \ + uint32_t: writel(val, addr), \ + uint64_t: _iosys_map_writeq(val, addr)); \ + } else \ + WRITE_ONCE(*(_type *)((_ism)->vaddr + (_off)), val); \ +}) + +#define iosys_map_rd_field(_ism, _off, _type, _field) ({ \ + _type *s; \ + iosys_map_rd(_ism, (_off) + offsetof(_type, _field), \ + __typeof(s->_field)); \ +}) +#define iosys_map_wr_field(_ism, _off, _type, _field, _val) ({ \ + _type *s; \ + iosys_map_wr(_ism, (_off) + offsetof(_type, _field), \ + __typeof(s->_field), _val); \ +}) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/ip.h b/sys/compat/linuxkpi/common/include/linux/ip.h index 3507c6fe9b97..137cf89e7dcb 100644 --- a/sys/compat/linuxkpi/common/include/linux/ip.h +++ b/sys/compat/linuxkpi/common/include/linux/ip.h @@ -26,15 +26,14 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_IP_H -#define __LKPI_LINUX_IP_H +#ifndef _LINUXKPI_LINUX_IP_H +#define _LINUXKPI_LINUX_IP_H #include <sys/types.h> +#include <netinet/in.h> #include <netinet/ip.h> #include <machine/in_cksum.h> @@ -71,4 +70,4 @@ ip_send_check(struct iphdr *iph) iph->check = in_cksum_hdr((const void *)iph); } -#endif /* __LKPI_LINUX_IP_H */ +#endif /* _LINUXKPI_LINUX_IP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/irq_work.h b/sys/compat/linuxkpi/common/include/linux/irq_work.h index 1b376b829818..7c4019bc0242 100644 --- a/sys/compat/linuxkpi/common/include/linux/irq_work.h +++ b/sys/compat/linuxkpi/common/include/linux/irq_work.h @@ -24,21 +24,37 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUX_IRQ_WORK_H__ -#define __LINUX_IRQ_WORK_H__ +#ifndef _LINUXKPI_LINUX_IRQ_WORK_H_ +#define _LINUXKPI_LINUX_IRQ_WORK_H_ #include <sys/param.h> #include <sys/taskqueue.h> +#include <linux/llist.h> +#include <linux/workqueue.h> + +#define LKPI_IRQ_WORK_STD_TQ system_wq->taskqueue +#define LKPI_IRQ_WORK_FAST_TQ linux_irq_work_tq + +#ifdef LKPI_IRQ_WORK_USE_FAST_TQ +#define LKPI_IRQ_WORK_TQ LKPI_IRQ_WORK_FAST_TQ +#else +#define LKPI_IRQ_WORK_TQ LKPI_IRQ_WORK_STD_TQ +#endif + struct irq_work; typedef void (*irq_work_func_t)(struct irq_work *); struct irq_work { struct task irq_task; + union { + struct llist_node llnode; + struct { + struct llist_node llist; + } node; + }; irq_work_func_t func; }; @@ -58,16 +74,17 @@ init_irq_work(struct irq_work *irqw, irq_work_func_t func) irqw->func = func; } -static inline void +static inline bool irq_work_queue(struct irq_work *irqw) { - taskqueue_enqueue(linux_irq_work_tq, &irqw->irq_task); + return (taskqueue_enqueue_flags(LKPI_IRQ_WORK_TQ, &irqw->irq_task, + TASKQUEUE_FAIL_IF_PENDING) == 0); } static inline void irq_work_sync(struct irq_work *irqw) { - taskqueue_drain(linux_irq_work_tq, &irqw->irq_task); + taskqueue_drain(LKPI_IRQ_WORK_TQ, &irqw->irq_task); } -#endif /* __LINUX_IRQ_WORK_H__ */ +#endif /* _LINUXKPI_LINUX_IRQ_WORK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/irqdomain.h b/sys/compat/linuxkpi/common/include/linux/irqdomain.h new file mode 100644 index 000000000000..c7788e51cc89 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/irqdomain.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_IRQDOMAIN_H +#define _LINUXKPI_LINUX_IRQDOMAIN_H + +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/radix-tree.h> + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/irqreturn.h b/sys/compat/linuxkpi/common/include/linux/irqreturn.h index 780fccad017c..ff2618449d5e 100644 --- a/sys/compat/linuxkpi/common/include/linux/irqreturn.h +++ b/sys/compat/linuxkpi/common/include/linux/irqreturn.h @@ -22,12 +22,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_IRQRETURN_H -#define _LINUX_IRQRETURN_H +#ifndef _LINUXKPI_LINUX_IRQRETURN_H +#define _LINUXKPI_LINUX_IRQRETURN_H typedef enum irqreturn { IRQ_NONE = 0, @@ -37,4 +35,4 @@ typedef enum irqreturn { #define IRQ_RETVAL(x) ((x) ? IRQ_HANDLED : IRQ_NONE) -#endif /* _LINUX_IRQRETURN_H */ +#endif /* _LINUXKPI_LINUX_IRQRETURN_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/jhash.h b/sys/compat/linuxkpi/common/include/linux/jhash.h index 08300083212f..25e2c04f1965 100644 --- a/sys/compat/linuxkpi/common/include/linux/jhash.h +++ b/sys/compat/linuxkpi/common/include/linux/jhash.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_JHASH_H_ -#define _LINUX_JHASH_H_ +#ifndef _LINUXKPI_LINUX_JHASH_H_ +#define _LINUXKPI_LINUX_JHASH_H_ #include <asm/types.h> @@ -20,8 +20,6 @@ * * I've modified Bob's hash to be useful in the Linux kernel, and * any bugs present are surely my fault. -DaveM - * - * $FreeBSD$ */ /* NOTE: Arguments are modified. */ @@ -143,4 +141,4 @@ static inline u32 jhash_1word(u32 a, u32 initval) return jhash_3words(a, 0, 0, initval); } -#endif /* _LINUX_JHASH_H_ */ +#endif /* _LINUXKPI_LINUX_JHASH_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/jiffies.h b/sys/compat/linuxkpi/common/include/linux/jiffies.h index 7d547e6d66cd..c2409726e874 100644 --- a/sys/compat/linuxkpi/common/include/linux/jiffies.h +++ b/sys/compat/linuxkpi/common/include/linux/jiffies.h @@ -25,35 +25,34 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_JIFFIES_H_ -#define _LINUX_JIFFIES_H_ +#ifndef _LINUXKPI_LINUX_JIFFIES_H_ +#define _LINUXKPI_LINUX_JIFFIES_H_ #include <linux/types.h> #include <linux/time.h> -#include <sys/time.h> #include <sys/kernel.h> #include <sys/limits.h> +#include <sys/time.h> -#define jiffies ticks -#define jiffies_64 ticks -#define jiffies_to_msecs(x) (((int64_t)(int)(x)) * 1000 / hz) +extern unsigned long jiffies; /* defined in sys/kern/subr_ticks.S */ +#define jiffies_64 jiffies /* XXX-MJ wrong on 32-bit platforms */ +#define jiffies_to_msecs(x) ((unsigned int)(((int64_t)(int)(x)) * 1000 / hz)) -#define MAX_JIFFY_OFFSET ((INT_MAX >> 1) - 1) +#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1) - 1) -#define time_after(a, b) ((int)((b) - (a)) < 0) +#define time_after(a, b) ((long)((b) - (a)) < 0) #define time_after32(a, b) ((int32_t)((uint32_t)(b) - (uint32_t)(a)) < 0) #define time_before(a, b) time_after(b,a) #define time_before32(a, b) time_after32(b, a) -#define time_after_eq(a, b) ((int)((a) - (b)) >= 0) +#define time_after_eq(a, b) ((long)((a) - (b)) >= 0) #define time_before_eq(a, b) time_after_eq(b, a) #define time_in_range(a,b,c) \ (time_after_eq(a,b) && time_before_eq(a,c)) #define time_is_after_eq_jiffies(a) time_after_eq(a, jiffies) #define time_is_after_jiffies(a) time_after(a, jiffies) +#define time_is_before_jiffies(a) time_before(a, jiffies) #define HZ hz @@ -69,20 +68,7 @@ extern uint64_t lkpi_msec2hz_rem; extern uint64_t lkpi_msec2hz_div; extern uint64_t lkpi_msec2hz_max; -static inline int -timespec_to_jiffies(const struct timespec *ts) -{ - u64 result; - - result = ((u64)hz * ts->tv_sec) + - (((u64)hz * ts->tv_nsec + NSEC_PER_SEC - 1) / NSEC_PER_SEC); - if (result > MAX_JIFFY_OFFSET) - result = MAX_JIFFY_OFFSET; - - return ((int)result); -} - -static inline int +static inline unsigned long msecs_to_jiffies(uint64_t msec) { uint64_t result; @@ -93,10 +79,10 @@ msecs_to_jiffies(uint64_t msec) if (result > MAX_JIFFY_OFFSET) result = MAX_JIFFY_OFFSET; - return ((int)result); + return ((unsigned long)result); } -static inline int +static inline unsigned long usecs_to_jiffies(uint64_t usec) { uint64_t result; @@ -107,7 +93,7 @@ usecs_to_jiffies(uint64_t usec) if (result > MAX_JIFFY_OFFSET) result = MAX_JIFFY_OFFSET; - return ((int)result); + return ((unsigned long)result); } static inline uint64_t @@ -134,34 +120,24 @@ nsecs_to_jiffies(uint64_t nsec) } static inline uint64_t -jiffies_to_nsecs(int j) +jiffies_to_nsecs(unsigned long j) { - return ((1000000000ULL / hz) * (uint64_t)(unsigned int)j); + return ((1000000000ULL / hz) * (uint64_t)j); } static inline uint64_t -jiffies_to_usecs(int j) +jiffies_to_usecs(unsigned long j) { - return ((1000000ULL / hz) * (uint64_t)(unsigned int)j); + return ((1000000ULL / hz) * (uint64_t)j); } static inline uint64_t get_jiffies_64(void) { - return ((uint64_t)(unsigned int)ticks); -} - -static inline int -linux_timer_jiffies_until(int expires) -{ - int delta = expires - jiffies; - /* guard against already expired values */ - if (delta < 1) - delta = 1; - return (delta); + return ((uint64_t)jiffies); } -#endif /* _LINUX_JIFFIES_H_ */ +#endif /* _LINUXKPI_LINUX_JIFFIES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/jump_label.h b/sys/compat/linuxkpi/common/include/linux/jump_label.h new file mode 100644 index 000000000000..444754a0ff82 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/jump_label.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-2020 François Tigeot <ftigeot@wolfpond.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_JUMP_LABEL_H_ +#define _LINUXKPI_LINUX_JUMP_LABEL_H_ + +#include <linux/types.h> +#include <linux/compiler.h> +#include <linux/bug.h> + +#define DEFINE_STATIC_KEY_FALSE(key) bool key = false + +static inline void +static_branch_enable(bool *flag) +{ + *flag = true; +} + +static inline bool +static_branch_likely(bool *flag) +{ + return *flag; +} + +#endif /* _LINUXKPI_LINUX_JUMP_LABEL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kconfig.h b/sys/compat/linuxkpi/common/include/linux/kconfig.h new file mode 100644 index 000000000000..c1d186b56e1f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kconfig.h @@ -0,0 +1,76 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_KCONFIG_H_ +#define _LINUXKPI_LINUX_KCONFIG_H_ + +/* + * Checking if an option is defined would be easy if we could do CPP inside CPP. + * The defined case whether -Dxxx or -Dxxx=1 are easy to deal with. In either + * case the defined value is "1". A more general -Dxxx=<c> case will require + * more effort to deal with all possible "true" values. Hope we do not have + * to do this as well. + * The real problem is the undefined case. To avoid this problem we do the + * concat/varargs trick: "yyy" ## xxx can make two arguments if xxx is "1" + * by having a #define for yyy_1 which is "ignore,". + * Otherwise we will just get "yyy". + * Need to be careful about variable substitutions in macros though. + * This way we make a (true, false) problem a (don't care, true, false) or a + * (don't care true, false). Then we can use a variadic macro to only select + * the always well known and defined argument #2. And that seems to be + * exactly what we need. Use 1 for true and 0 for false to also allow + * #if IS_*() checks pre-compiler checks which do not like #if true. + */ +#define ___XAB_1 dontcare, +#define ___IS_XAB(_ignore, _x, ...) (_x) +#define __IS_XAB(_x) ___IS_XAB(_x 1, 0) +#define _IS_XAB(_x) __IS_XAB(__CONCAT(___XAB_, _x)) + +/* This is if CONFIG_ccc=y. */ +#define IS_BUILTIN(_x) _IS_XAB(_x) +/* This is if CONFIG_ccc=m. */ +#define IS_MODULE(_x) _IS_XAB(_x ## _MODULE) +/* This is if CONFIG_ccc is compiled in(=y) or a module(=m). */ +#define IS_ENABLED(_x) (IS_BUILTIN(_x) || IS_MODULE(_x)) +/* + * This is weird case. If the CONFIG_ccc is builtin (=y) this returns true; + * or if the CONFIG_ccc is a module (=m) and the caller is built as a module + * (-DMODULE defined) this returns true, but if the callers is not a module + * (-DMODULE not defined, which means caller is BUILTIN) then it returns + * false. In other words, a module can reach the kernel, a module can reach + * a module, but the kernel cannot reach a module, and code never compiled + * cannot be reached either. + * XXX -- I'd hope the module-to-module case would be handled by a proper + * module dependency definition (MODULE_DEPEND() in FreeBSD). + */ +#define IS_REACHABLE(_x) (IS_BUILTIN(_x) || \ + (IS_MODULE(_x) && IS_BUILTIN(MODULE))) + +#endif /* _LINUXKPI_LINUX_KCONFIG_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kdev_t.h b/sys/compat/linuxkpi/common/include/linux/kdev_t.h index 9477ba739e31..988dd771254a 100644 --- a/sys/compat/linuxkpi/common/include/linux/kdev_t.h +++ b/sys/compat/linuxkpi/common/include/linux/kdev_t.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_KDEV_T_H_ -#define _LINUX_KDEV_T_H_ +#ifndef _LINUXKPI_LINUX_KDEV_T_H_ +#define _LINUXKPI_LINUX_KDEV_T_H_ #include <sys/types.h> @@ -43,4 +41,4 @@ old_encode_dev(dev_t dev) return ((MAJOR(dev) << 8) | MINOR(dev)); } -#endif /* _LINUX_KDEV_T_H_ */ +#endif /* _LINUXKPI_LINUX_KDEV_T_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kernel.h b/sys/compat/linuxkpi/common/include/linux/kernel.h index 94af8f29c4d7..11a13cbd49b4 100644 --- a/sys/compat/linuxkpi/common/include/linux/kernel.h +++ b/sys/compat/linuxkpi/common/include/linux/kernel.h @@ -26,13 +26,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_KERNEL_H_ -#define _LINUX_KERNEL_H_ +#ifndef _LINUXKPI_LINUX_KERNEL_H_ +#define _LINUXKPI_LINUX_KERNEL_H_ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/systm.h> #include <sys/param.h> @@ -44,18 +41,27 @@ #include <sys/time.h> #include <linux/bitops.h> +#include <linux/build_bug.h> #include <linux/compiler.h> +#include <linux/container_of.h> +#include <linux/kstrtox.h> +#include <linux/limits.h> +#include <linux/math.h> +#include <linux/minmax.h> #include <linux/stringify.h> #include <linux/errno.h> -#include <linux/sched.h> #include <linux/types.h> +#include <linux/typecheck.h> #include <linux/jiffies.h> #include <linux/log2.h> +#include <linux/kconfig.h> #include <asm/byteorder.h> +#include <asm/cpufeature.h> +#include <asm/processor.h> #include <asm/uaccess.h> -#include <machine/stdarg.h> +#include <linux/stdarg.h> #define KERN_CONT "" #define KERN_EMERG "<0>" @@ -67,19 +73,6 @@ #define KERN_INFO "<6>" #define KERN_DEBUG "<7>" -#define U8_MAX ((u8)~0U) -#define S8_MAX ((s8)(U8_MAX >> 1)) -#define S8_MIN ((s8)(-S8_MAX - 1)) -#define U16_MAX ((u16)~0U) -#define S16_MAX ((s16)(U16_MAX >> 1)) -#define S16_MIN ((s16)(-S16_MAX - 1)) -#define U32_MAX ((u32)~0U) -#define S32_MAX ((s32)(U32_MAX >> 1)) -#define S32_MIN ((s32)(-S32_MAX - 1)) -#define U64_MAX ((u64)~0ULL) -#define S64_MAX ((s64)(U64_MAX >> 1)) -#define S64_MIN ((s64)(-S64_MAX - 1)) - #define S8_C(x) x #define U8_C(x) x ## U #define S16_C(x) x @@ -89,30 +82,6 @@ #define S64_C(x) x ## LL #define U64_C(x) x ## ULL -/* - * BUILD_BUG_ON() can happen inside functions where _Static_assert() does not - * seem to work. Use old-schoold-ish CTASSERT from before commit - * a3085588a88fa58eb5b1eaae471999e1995a29cf but also make sure we do not - * end up with an unused typedef or variable. The compiler should optimise - * it away entirely. - */ -#define _O_CTASSERT(x) _O__CTASSERT(x, __LINE__) -#define _O__CTASSERT(x, y) _O___CTASSERT(x, y) -#define _O___CTASSERT(x, y) while (0) { \ - typedef char __assert_line_ ## y[(x) ? 1 : -1]; \ - __assert_line_ ## y _x; \ - _x[0] = '\0'; \ -} - -#define BUILD_BUG() do { CTASSERT(0); } while (0) -#define BUILD_BUG_ON(x) do { _O_CTASSERT(!(x)) } while (0) -#define BUILD_BUG_ON_MSG(x, msg) BUILD_BUG_ON(x) -#define BUILD_BUG_ON_NOT_POWER_OF_2(x) BUILD_BUG_ON(!powerof2(x)) -#define BUILD_BUG_ON_INVALID(expr) while (0) { (void)(expr); } - -extern const volatile int lkpi_build_bug_on_zero; -#define BUILD_BUG_ON_ZERO(x) ((x) ? lkpi_build_bug_on_zero : 0) - #define BUG() panic("BUG at %s:%d", __FILE__, __LINE__) #define BUG_ON(cond) do { \ if (cond) { \ @@ -152,18 +121,18 @@ extern int linuxkpi_warn_dump_stack; #undef ALIGN #define ALIGN(x, y) roundup2((x), (y)) +#define ALIGN_DOWN(x, y) rounddown2(x, y) #undef PTR_ALIGN #define PTR_ALIGN(p, a) ((__typeof(p))ALIGN((uintptr_t)(p), (a))) #define IS_ALIGNED(x, a) (((x) & ((__typeof(x))(a) - 1)) == 0) -#define DIV_ROUND_UP(x, n) howmany(x, n) #define __KERNEL_DIV_ROUND_UP(x, n) howmany(x, n) -#define DIV_ROUND_UP_ULL(x, n) DIV_ROUND_UP((unsigned long long)(x), (n)) -#define DIV_ROUND_DOWN_ULL(x, n) (((unsigned long long)(x) / (n)) * (n)) #define FIELD_SIZEOF(t, f) sizeof(((t *)0)->f) #define printk(...) printf(__VA_ARGS__) #define vprintk(f, a) vprintf(f, a) +#define PTR_IF(x, p) ((x) ? (p) : NULL) + #define asm __asm extern void linux_dump_stack(void); @@ -294,265 +263,15 @@ extern int linuxkpi_debug; }) #endif -#define container_of(ptr, type, member) \ -({ \ - const __typeof(((type *)0)->member) *__p = (ptr); \ - (type *)((uintptr_t)__p - offsetof(type, member)); \ -}) - #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define u64_to_user_ptr(val) ((void *)(uintptr_t)(val)) #define _RET_IP_ __builtin_return_address(0) -static inline unsigned long long -simple_strtoull(const char *cp, char **endp, unsigned int base) -{ - return (strtouq(cp, endp, base)); -} - -static inline long long -simple_strtoll(const char *cp, char **endp, unsigned int base) -{ - return (strtoq(cp, endp, base)); -} - -static inline unsigned long -simple_strtoul(const char *cp, char **endp, unsigned int base) -{ - return (strtoul(cp, endp, base)); -} - -static inline long -simple_strtol(const char *cp, char **endp, unsigned int base) -{ - return (strtol(cp, endp, base)); -} - -static inline int -kstrtoul(const char *cp, unsigned int base, unsigned long *res) -{ - char *end; - - *res = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - return (0); -} - -static inline int -kstrtol(const char *cp, unsigned int base, long *res) -{ - char *end; - - *res = strtol(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - return (0); -} - -static inline int -kstrtoint(const char *cp, unsigned int base, int *res) -{ - char *end; - long temp; - - *res = temp = strtol(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (int)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtouint(const char *cp, unsigned int base, unsigned int *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (unsigned int)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou8(const char *cp, unsigned int base, u8 *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (u8)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou16(const char *cp, unsigned int base, u16 *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (u16)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou32(const char *cp, unsigned int base, u32 *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (u32)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou64(const char *cp, unsigned int base, u64 *res) -{ - char *end; - - *res = strtouq(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - return (0); -} - -static inline int -kstrtobool(const char *s, bool *res) -{ - int len; - - if (s == NULL || (len = strlen(s)) == 0 || res == NULL) - return (-EINVAL); - - /* skip newline character, if any */ - if (s[len - 1] == '\n') - len--; - - if (len == 1 && strchr("yY1", s[0]) != NULL) - *res = true; - else if (len == 1 && strchr("nN0", s[0]) != NULL) - *res = false; - else if (strncasecmp("on", s, len) == 0) - *res = true; - else if (strncasecmp("off", s, len) == 0) - *res = false; - else - return (-EINVAL); - - return (0); -} - -static inline int -kstrtobool_from_user(const char __user *s, size_t count, bool *res) -{ - char buf[8] = {}; - - if (count > (sizeof(buf) - 1)) - count = (sizeof(buf) - 1); - - if (copy_from_user(buf, s, count)) - return (-EFAULT); - - return (kstrtobool(buf, res)); -} - -static inline int -kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, - u8 *p) -{ - char buf[8] = {}; - - if (count > (sizeof(buf) - 1)) - count = (sizeof(buf) - 1); - - if (copy_from_user(buf, s, count)) - return (-EFAULT); - - return (kstrtou8(buf, base, p)); -} - -#define min(x, y) ((x) < (y) ? (x) : (y)) -#define max(x, y) ((x) > (y) ? (x) : (y)) - -#define min3(a, b, c) min(a, min(b,c)) -#define max3(a, b, c) max(a, max(b,c)) - -#define min_t(type, x, y) ({ \ - type __min1 = (x); \ - type __min2 = (y); \ - __min1 < __min2 ? __min1 : __min2; }) - -#define max_t(type, x, y) ({ \ - type __max1 = (x); \ - type __max2 = (y); \ - __max1 > __max2 ? __max1 : __max2; }) - #define offsetofend(t, m) \ (offsetof(t, m) + sizeof((((t *)0)->m))) -#define clamp_t(type, _x, min, max) min_t(type, max_t(type, _x, min), max) -#define clamp(x, lo, hi) min( max(x,lo), hi) -#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi) - -/* - * This looks more complex than it should be. But we need to - * get the type for the ~ right in round_down (it needs to be - * as wide as the result!), and we want to evaluate the macro - * arguments just once each. - */ -#define __round_mask(x, y) ((__typeof__(x))((y)-1)) -#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) -#define round_down(x, y) ((x) & ~__round_mask(x, y)) - #define smp_processor_id() PCPU_GET(cpuid) #define num_possible_cpus() mp_ncpus #define num_online_cpus() mp_ncpus @@ -562,41 +281,6 @@ extern bool linux_cpu_has_clflush; #define cpu_has_clflush linux_cpu_has_clflush #endif -typedef struct pm_message { - int event; -} pm_message_t; - -/* Swap values of a and b */ -#define swap(a, b) do { \ - typeof(a) _swap_tmp = a; \ - a = b; \ - b = _swap_tmp; \ -} while (0) - -#define DIV_ROUND_CLOSEST(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) - -#define DIV_ROUND_CLOSEST_ULL(x, divisor) ({ \ - __typeof(divisor) __d = (divisor); \ - unsigned long long __ret = (x) + (__d) / 2; \ - __ret /= __d; \ - __ret; \ -}) - -static inline uintmax_t -mult_frac(uintmax_t x, uintmax_t multiplier, uintmax_t divisor) -{ - uintmax_t q = (x / divisor); - uintmax_t r = (x % divisor); - - return ((q * multiplier) + ((r * multiplier) / divisor)); -} - -static inline int64_t -abs64(int64_t x) -{ - return (x < 0 ? -x : x); -} - typedef struct linux_ratelimit { struct timeval lasttime; int counter; @@ -608,12 +292,6 @@ linux_ratelimited(linux_ratelimit_t *rl) return (ppsratecheck(&rl->lasttime, &rl->counter, 1)); } -#define struct_size(ptr, field, num) ({ \ - const size_t __size = offsetof(__typeof(*(ptr)), field); \ - const size_t __max = (SIZE_MAX - __size) / sizeof((ptr)->field[0]); \ - ((num) > __max) ? SIZE_MAX : (__size + sizeof((ptr)->field[0]) * (num)); \ -}) - #define __is_constexpr(x) \ __builtin_constant_p(x) @@ -623,72 +301,85 @@ linux_ratelimited(linux_ratelimit_t *rl) */ #define is_signed(datatype) (((datatype)-1 / (datatype)2) == (datatype)0) -/* - * The type_max() macro below returns the maxium positive value the - * passed data type can hold. - */ -#define type_max(datatype) ( \ - (sizeof(datatype) >= 8) ? (is_signed(datatype) ? INT64_MAX : UINT64_MAX) : \ - (sizeof(datatype) >= 4) ? (is_signed(datatype) ? INT32_MAX : UINT32_MAX) : \ - (sizeof(datatype) >= 2) ? (is_signed(datatype) ? INT16_MAX : UINT16_MAX) : \ - (is_signed(datatype) ? INT8_MAX : UINT8_MAX) \ -) - -/* - * The type_min() macro below returns the minimum value the passed - * data type can hold. For unsigned types the minimum value is always - * zero. For signed types it may vary. - */ -#define type_min(datatype) ( \ - (sizeof(datatype) >= 8) ? (is_signed(datatype) ? INT64_MIN : 0) : \ - (sizeof(datatype) >= 4) ? (is_signed(datatype) ? INT32_MIN : 0) : \ - (sizeof(datatype) >= 2) ? (is_signed(datatype) ? INT16_MIN : 0) : \ - (is_signed(datatype) ? INT8_MIN : 0) \ -) - #define TAINT_WARN 0 #define test_taint(x) (0) +#define add_taint(x,y) do { \ + } while (0) -/* - * Checking if an option is defined would be easy if we could do CPP inside CPP. - * The defined case whether -Dxxx or -Dxxx=1 are easy to deal with. In either - * case the defined value is "1". A more general -Dxxx=<c> case will require - * more effort to deal with all possible "true" values. Hope we do not have - * to do this as well. - * The real problem is the undefined case. To avoid this problem we do the - * concat/varargs trick: "yyy" ## xxx can make two arguments if xxx is "1" - * by having a #define for yyy_1 which is "ignore,". - * Otherwise we will just get "yyy". - * Need to be careful about variable substitutions in macros though. - * This way we make a (true, false) problem a (don't care, true, false) or a - * (don't care true, false). Then we can use a variadic macro to only select - * the always well known and defined argument #2. And that seems to be - * exactly what we need. Use 1 for true and 0 for false to also allow - * #if IS_*() checks pre-compiler checks which do not like #if true. - */ -#define ___XAB_1 dontcare, -#define ___IS_XAB(_ignore, _x, ...) (_x) -#define __IS_XAB(_x) ___IS_XAB(_x 1, 0) -#define _IS_XAB(_x) __IS_XAB(__CONCAT(___XAB_, _x)) - -/* This is if CONFIG_ccc=y. */ -#define IS_BUILTIN(_x) _IS_XAB(_x) -/* This is if CONFIG_ccc=m. */ -#define IS_MODULE(_x) _IS_XAB(_x ## _MODULE) -/* This is if CONFIG_ccc is compiled in(=y) or a module(=m). */ -#define IS_ENABLED(_x) (IS_BUILTIN(_x) || IS_MODULE(_x)) -/* - * This is weird case. If the CONFIG_ccc is builtin (=y) this returns true; - * or if the CONFIG_ccc is a module (=m) and the caller is built as a module - * (-DMODULE defined) this returns true, but if the callers is not a module - * (-DMODULE not defined, which means caller is BUILTIN) then it returns - * false. In other words, a module can reach the kernel, a module can reach - * a module, but the kernel cannot reach a module, and code never compiled - * cannot be reached either. - * XXX -- I'd hope the module-to-module case would be handled by a proper - * module dependency definition (MODULE_DEPEND() in FreeBSD). - */ -#define IS_REACHABLE(_x) (IS_BUILTIN(_x) || \ - (IS_MODULE(_x) && IS_BUILTIN(MODULE))) +static inline int +_h2b(const char c) +{ + + if (c >= '0' && c <= '9') + return (c - '0'); + if (c >= 'a' && c <= 'f') + return (10 + c - 'a'); + if (c >= 'A' && c <= 'F') + return (10 + c - 'A'); + return (-EINVAL); +} + +static inline int +hex2bin(uint8_t *bindst, const char *hexsrc, size_t binlen) +{ + int hi4, lo4; + + while (binlen > 0) { + hi4 = _h2b(*hexsrc++); + lo4 = _h2b(*hexsrc++); + if (hi4 < 0 || lo4 < 0) + return (-EINVAL); + + *bindst++ = (hi4 << 4) | lo4; + binlen--; + } + + return (0); +} + +static inline bool +mac_pton(const char *macin, uint8_t *macout) +{ + const char *s, *d; + uint8_t mac[6], hx, lx; + int i; + + if (strlen(macin) < (3 * 6 - 1)) + return (false); + + i = 0; + s = macin; + do { + /* Should we also support '-'-delimiters? */ + d = strchrnul(s, ':'); + hx = lx = 0; + while (s < d) { + /* Fail on abc:123:xxx:... */ + if ((d - s) > 2) + return (false); + /* We do support non-well-formed strings: 3:45:6:... */ + if ((d - s) > 1) { + hx = _h2b(*s); + if (hx < 0) + return (false); + s++; + } + lx = _h2b(*s); + if (lx < 0) + return (false); + s++; + } + mac[i] = (hx << 4) | lx; + i++; + if (i >= 6) + return (false); + } while (d != NULL && *d != '\0'); + + memcpy(macout, mac, 6); + return (true); +} + +#define DECLARE_FLEX_ARRAY(_t, _n) \ + struct { struct { } __dummy_ ## _n; _t _n[0]; } -#endif /* _LINUX_KERNEL_H_ */ +#endif /* _LINUXKPI_LINUX_KERNEL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kernel_stat.h b/sys/compat/linuxkpi/common/include/linux/kernel_stat.h new file mode 100644 index 000000000000..c960b4ad2cff --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kernel_stat.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_KERNEL_STAT_H_ +#define _LINUXKPI_LINUX_KERNEL_STAT_H_ + +#include <linux/interrupt.h> + +#endif /* _LINUXKPI_LINUX_KERNEL_STAT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kfifo.h b/sys/compat/linuxkpi/common/include/linux/kfifo.h new file mode 100644 index 000000000000..d2f570781661 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kfifo.h @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_KFIFO_H_ +#define _LINUXKPI_LINUX_KFIFO_H_ + +#include <sys/types.h> + +#include <linux/slab.h> +#include <linux/gfp.h> + +#define INIT_KFIFO(x) 0 +#define DECLARE_KFIFO(x, y, z) + +#define DECLARE_KFIFO_PTR(_name, _type) \ + struct kfifo_ ## _name { \ + size_t total; \ + size_t count; \ + size_t first; \ + size_t last; \ + _type *head; \ + } _name + +#define kfifo_len(_kf) \ +({ \ + (_kf)->count; \ +}) + +#define kfifo_is_empty(_kf) \ +({ \ + ((_kf)->count == 0) ? true : false; \ +}) + +#define kfifo_is_full(_kf) \ +({ \ + ((_kf)->count == (_kf)->total) ? true : false; \ +}) + +#define kfifo_put(_kf, _e) \ +({ \ + bool _rc; \ + \ + /* Would overflow. */ \ + if (kfifo_is_full(_kf)) { \ + _rc = false; \ + } else { \ + (_kf)->head[(_kf)->last] = (_e); \ + (_kf)->count++; \ + (_kf)->last++; \ + if ((_kf)->last > (_kf)->total) \ + (_kf)->last = 0; \ + _rc = true; \ + } \ + \ + _rc; \ +}) + +#define kfifo_get(_kf, _e) \ +({ \ + bool _rc; \ + \ + if (kfifo_is_empty(_kf)) { \ + _rc = false; \ + } else { \ + *(_e) = (_kf)->head[(_kf)->first]; \ + (_kf)->count--; \ + (_kf)->first++; \ + if ((_kf)->first > (_kf)->total) \ + (_kf)->first = 0; \ + _rc = true; \ + } \ + \ + _rc; \ +}) + +#define kfifo_alloc(_kf, _s, _gfp) \ +({ \ + int _error; \ + \ + (_kf)->head = kmalloc(sizeof(__typeof(*(_kf)->head)) * (_s), _gfp); \ + if ((_kf)->head == NULL) \ + _error = ENOMEM; \ + else { \ + (_kf)->total = (_s); \ + _error = 0; \ + } \ + \ + _error; \ +}) + +#define kfifo_free(_kf) \ +({ \ + kfree((_kf)->head); \ + (_kf)->head = NULL; \ + (_kf)->total = (_kf)->count = (_kf)->first = (_kf)->last = 0; \ +}) + +#endif /* _LINUXKPI_LINUX_KFIFO_H_*/ diff --git a/sys/compat/linuxkpi/common/include/linux/kmemleak.h b/sys/compat/linuxkpi/common/include/linux/kmemleak.h new file mode 100644 index 000000000000..7007e72718c7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kmemleak.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_KMEMLEAK_H_ +#define _LINUXKPI_LINUX_KMEMLEAK_H_ + +#define kmemleak_update_trace(x) + +#endif /* _LINUXKPI_LINUX_KMEMLEAK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kmod.h b/sys/compat/linuxkpi/common/include/linux/kmod.h index b8a1a8b677ed..8f9f034aabd8 100644 --- a/sys/compat/linuxkpi/common/include/linux/kmod.h +++ b/sys/compat/linuxkpi/common/include/linux/kmod.h @@ -25,27 +25,24 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_KMOD_H_ -#define _LINUX_KMOD_H_ +#ifndef _LINUXKPI_LINUX_KMOD_H_ +#define _LINUXKPI_LINUX_KMOD_H_ #include <sys/types.h> #include <sys/syscallsubr.h> #include <sys/refcount.h> #include <sys/sbuf.h> -#include <machine/stdarg.h> +#include <sys/stdarg.h> #include <sys/proc.h> #define request_module(...) \ ({\ char modname[128]; \ - int fileid; \ snprintf(modname, sizeof(modname), __VA_ARGS__); \ - kern_kldload(curthread, modname, &fileid); \ + kern_kldload(curthread, modname, NULL); \ }) #define request_module_nowait request_module -#endif /* _LINUX_KMOD_H_ */ +#endif /* _LINUXKPI_LINUX_KMOD_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kobject.h b/sys/compat/linuxkpi/common/include/linux/kobject.h index 403ec1495c32..98f55d1234c4 100644 --- a/sys/compat/linuxkpi/common/include/linux/kobject.h +++ b/sys/compat/linuxkpi/common/include/linux/kobject.h @@ -25,20 +25,22 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_KOBJECT_H_ -#define _LINUX_KOBJECT_H_ +#ifndef _LINUXKPI_LINUX_KOBJECT_H_ +#define _LINUXKPI_LINUX_KOBJECT_H_ -#include <machine/stdarg.h> +#include <sys/stdarg.h> #include <linux/kernel.h> #include <linux/kref.h> #include <linux/list.h> #include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/wait.h> +#include <linux/workqueue.h> struct kobject; +struct kset; struct sysctl_oid; #define KOBJ_CHANGE 0x01 @@ -47,6 +49,7 @@ struct kobj_type { void (*release)(struct kobject *kobj); const struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; + const struct attribute_group **default_groups; }; extern const struct kobj_type linux_kfree_type; @@ -58,6 +61,7 @@ struct kobject { const struct kobj_type *ktype; struct list_head entry; struct sysctl_oid *oidp; + struct kset *kset; }; extern struct kobject *mm_kobj; @@ -68,6 +72,8 @@ struct attribute { mode_t mode; }; +extern const struct sysfs_ops kobj_sysfs_ops; + struct kobj_attribute { struct attribute attr; ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, @@ -76,6 +82,17 @@ struct kobj_attribute { const char *buf, size_t count); }; +struct kset_uevent_ops { + /* TODO */ +}; + +struct kset { + struct list_head list; + spinlock_t list_lock; + struct kobject kobj; + const struct kset_uevent_ops *uevent_ops; +}; + static inline void kobject_init(struct kobject *kobj, const struct kobj_type *ktype) { @@ -105,24 +122,12 @@ kobject_get(struct kobject *kobj) return kobj; } +struct kobject *kobject_create(void); int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, va_list); int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...); static inline struct kobject * -kobject_create(void) -{ - struct kobject *kobj; - - kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); - if (kobj == NULL) - return (NULL); - kobject_init(kobj, &linux_kfree_type); - - return (kobj); -} - -static inline struct kobject * kobject_create_and_add(const char *name, struct kobject *parent) { struct kobject *kobj; @@ -165,4 +170,41 @@ kobject_uevent_env(struct kobject *kobj, int action, char *envp[]) */ } -#endif /* _LINUX_KOBJECT_H_ */ +void kset_init(struct kset *kset); +int kset_register(struct kset *kset); +void kset_unregister(struct kset *kset); +struct kset * kset_create_and_add(const char *name, + const struct kset_uevent_ops *u, struct kobject *parent_kobj); + +static inline struct kset * +to_kset(struct kobject *kobj) +{ + if (kobj != NULL) + return container_of(kobj, struct kset, kobj); + else + return NULL; +} + +static inline struct kset * +kset_get(struct kset *kset) +{ + if (kset != NULL) { + struct kobject *kobj; + + kobj = kobject_get(&kset->kobj); + return to_kset(kobj); + } else { + return NULL; + } +} + +static inline void +kset_put(struct kset *kset) +{ + if (kset != NULL) + kobject_put(&kset->kobj); +} + +void linux_kobject_kfree_name(struct kobject *kobj); + +#endif /* _LINUXKPI_LINUX_KOBJECT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kref.h b/sys/compat/linuxkpi/common/include/linux/kref.h index d5b45ba59313..b2fba468f7df 100644 --- a/sys/compat/linuxkpi/common/include/linux/kref.h +++ b/sys/compat/linuxkpi/common/include/linux/kref.h @@ -26,11 +26,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_KREF_H_ -#define _LINUX_KREF_H_ +#ifndef _LINUXKPI_LINUX_KREF_H_ +#define _LINUXKPI_LINUX_KREF_H_ #include <sys/types.h> #include <sys/refcount.h> @@ -43,35 +41,35 @@ #include <asm/atomic.h> struct kref { - atomic_t refcount; + refcount_t refcount; }; static inline void kref_init(struct kref *kref) { - refcount_init(&kref->refcount.counter, 1); + refcount_init((uint32_t *)&kref->refcount, 1); } static inline unsigned int kref_read(const struct kref *kref) { - return (atomic_read(&kref->refcount)); + return (refcount_load(__DECONST(u_int32_t *, &kref->refcount))); } static inline void kref_get(struct kref *kref) { - refcount_acquire(&kref->refcount.counter); + refcount_acquire((uint32_t *)&kref->refcount); } static inline int kref_put(struct kref *kref, void (*rel)(struct kref *kref)) { - if (refcount_release(&kref->refcount.counter)) { + if (refcount_release((uint32_t *)&kref->refcount)) { rel(kref); return 1; } @@ -83,7 +81,7 @@ kref_put_lock(struct kref *kref, void (*rel)(struct kref *kref), spinlock_t *lock) { - if (refcount_release(&kref->refcount.counter)) { + if (refcount_release((uint32_t *)&kref->refcount)) { spin_lock(lock); rel(kref); return (1); @@ -97,7 +95,7 @@ kref_sub(struct kref *kref, unsigned int count, { while (count--) { - if (refcount_release(&kref->refcount.counter)) { + if (refcount_release((uint32_t *)&kref->refcount)) { rel(kref); return 1; } @@ -109,16 +107,16 @@ static inline int __must_check kref_get_unless_zero(struct kref *kref) { - return atomic_add_unless(&kref->refcount, 1, 0); + return refcount_acquire_if_not_zero((uint32_t *)&kref->refcount); } static inline int kref_put_mutex(struct kref *kref, void (*release)(struct kref *kref), struct mutex *lock) { WARN_ON(release == NULL); - if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) { + if (unlikely(!refcount_release_if_not_last((uint32_t *)&kref->refcount))) { mutex_lock(lock); - if (unlikely(!atomic_dec_and_test(&kref->refcount))) { + if (unlikely(!refcount_release((uint32_t *)&kref->refcount))) { mutex_unlock(lock); return 0; } @@ -128,4 +126,4 @@ static inline int kref_put_mutex(struct kref *kref, return 0; } -#endif /* _LINUX_KREF_H_ */ +#endif /* _LINUXKPI_LINUX_KREF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kstrtox.h b/sys/compat/linuxkpi/common/include/linux/kstrtox.h new file mode 100644 index 000000000000..5da99de24197 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kstrtox.h @@ -0,0 +1,324 @@ +/*- + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2017-2018 Mellanox Technologies, Ltd. + * All rights reserved. + * Copyright (c) 2018 Johannes Lundberg <johalun0@gmail.com> + * Copyright (c) 2020-2022 The FreeBSD Foundation + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC + * + * Portions of this software were developed by Bjoern A. Zeeb and + * Emmanuel Vadot under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_KSTRTOX_H_ +#define _LINUXKPI_LINUX_KSTRTOX_H_ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/libkern.h> + +#include <linux/compiler.h> +#include <linux/types.h> + +#include <asm/uaccess.h> + +static inline unsigned long long +simple_strtoull(const char *cp, char **endp, unsigned int base) +{ + return (strtouq(cp, endp, base)); +} + +static inline long long +simple_strtoll(const char *cp, char **endp, unsigned int base) +{ + return (strtoq(cp, endp, base)); +} + +static inline unsigned long +simple_strtoul(const char *cp, char **endp, unsigned int base) +{ + return (strtoul(cp, endp, base)); +} + +static inline long +simple_strtol(const char *cp, char **endp, unsigned int base) +{ + return (strtol(cp, endp, base)); +} + +static inline int +kstrtoul(const char *cp, unsigned int base, unsigned long *res) +{ + char *end; + + *res = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtol(const char *cp, unsigned int base, long *res) +{ + char *end; + + *res = strtol(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtoint(const char *cp, unsigned int base, int *res) +{ + char *end; + long temp; + + *res = temp = strtol(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (int)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtouint(const char *cp, unsigned int base, unsigned int *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (unsigned int)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtou8(const char *cp, unsigned int base, uint8_t *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (uint8_t)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtou16(const char *cp, unsigned int base, uint16_t *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (uint16_t)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtou32(const char *cp, unsigned int base, uint32_t *res) +{ + + return (kstrtouint(cp, base, res)); +} + +static inline int +kstrtos32(const char *cp, unsigned int base, int32_t *res) +{ + + return (kstrtoint(cp, base, res)); +} + +static inline int +kstrtos64(const char *cp, unsigned int base, int64_t *res) +{ + char *end; + + *res = strtoq(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtoll(const char *cp, unsigned int base, long long *res) +{ + return (kstrtos64(cp, base, (int64_t *)res)); +} + +static inline int +kstrtou64(const char *cp, unsigned int base, u64 *res) +{ + char *end; + + *res = strtouq(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtoull(const char *cp, unsigned int base, unsigned long long *res) +{ + return (kstrtou64(cp, base, (uint64_t *)res)); +} + +static inline int +kstrtobool(const char *s, bool *res) +{ + int len; + + if (s == NULL || (len = strlen(s)) == 0 || res == NULL) + return (-EINVAL); + + /* skip newline character, if any */ + if (s[len - 1] == '\n') + len--; + + if (len == 1 && strchr("yY1", s[0]) != NULL) + *res = true; + else if (len == 1 && strchr("nN0", s[0]) != NULL) + *res = false; + else if (strncasecmp("on", s, len) == 0) + *res = true; + else if (strncasecmp("off", s, len) == 0) + *res = false; + else + return (-EINVAL); + + return (0); +} + +static inline int +kstrtobool_from_user(const char __user *s, size_t count, bool *res) +{ + char buf[8] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtobool(buf, res)); +} + +static inline int +kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, + int *p) +{ + char buf[36] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtoint(buf, base, p)); +} + +static inline int +kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, + unsigned int *p) +{ + char buf[36] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtouint(buf, base, p)); +} + +static inline int +kstrtou32_from_user(const char __user *s, size_t count, unsigned int base, + unsigned int *p) +{ + + return (kstrtouint_from_user(s, count, base, p)); +} + +static inline int +kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, + uint8_t *p) +{ + char buf[8] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtou8(buf, base, p)); +} + +#endif /* _LINUXKPI_LINUX_KSTRTOX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kthread.h b/sys/compat/linuxkpi/common/include/linux/kthread.h index 3afd21dc9356..1fde734fd767 100644 --- a/sys/compat/linuxkpi/common/include/linux/kthread.h +++ b/sys/compat/linuxkpi/common/include/linux/kthread.h @@ -25,16 +25,35 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_KTHREAD_H_ -#define _LINUX_KTHREAD_H_ +#ifndef _LINUXKPI_LINUX_KTHREAD_H_ +#define _LINUXKPI_LINUX_KTHREAD_H_ #include <linux/sched.h> -#include <sys/unistd.h> +#include <sys/param.h> +#include <sys/kernel.h> #include <sys/kthread.h> +#include <sys/malloc.h> +#include <sys/queue.h> +#include <sys/taskqueue.h> +#include <sys/unistd.h> + +struct task_struct; +struct kthread_work; + +typedef void (*kthread_work_func_t)(struct kthread_work *work); + +struct kthread_worker { + struct task_struct *task; + struct taskqueue *tq; +}; + +struct kthread_work { + struct taskqueue *tq; + struct task task; + kthread_work_func_t func; +}; #define kthread_run(fn, data, fmt, ...) ({ \ struct task_struct *__task; \ @@ -70,4 +89,78 @@ int linux_in_atomic(void); #define in_atomic() linux_in_atomic() -#endif /* _LINUX_KTHREAD_H_ */ +/* Only kthread_(create|destroy)_worker interface is allowed */ +#define kthread_init_worker(worker) \ + _Static_assert(false, "pre-4.9 worker interface is not supported"); + +task_fn_t lkpi_kthread_work_fn; +task_fn_t lkpi_kthread_worker_init_fn; + +#define kthread_create_worker(flags, fmt, ...) ({ \ + struct kthread_worker *__w; \ + struct task __task; \ + \ + __w = malloc(sizeof(*__w), M_KMALLOC, M_WAITOK | M_ZERO); \ + __w->tq = taskqueue_create("lkpi kthread taskq", M_WAITOK, \ + taskqueue_thread_enqueue, &__w->tq); \ + taskqueue_start_threads(&__w->tq, 1, PWAIT, fmt, ##__VA_ARGS__);\ + TASK_INIT(&__task, 0, lkpi_kthread_worker_init_fn, __w); \ + taskqueue_enqueue(__w->tq, &__task); \ + taskqueue_drain(__w->tq, &__task); \ + __w; \ +}) + +static inline void +kthread_destroy_worker(struct kthread_worker *worker) +{ + taskqueue_drain_all(worker->tq); + taskqueue_free(worker->tq); + free(worker, M_KMALLOC); +} + +static inline void +kthread_init_work(struct kthread_work *work, kthread_work_func_t func) +{ + work->tq = NULL; + work->func = func; + TASK_INIT(&work->task, 0, lkpi_kthread_work_fn, work); +} + +static inline bool +kthread_queue_work(struct kthread_worker *worker, struct kthread_work *work) +{ + int error; + + error = taskqueue_enqueue_flags(worker->tq, &work->task, + TASKQUEUE_FAIL_IF_CANCELING | TASKQUEUE_FAIL_IF_PENDING); + if (error == 0) + work->tq = worker->tq; + return (error == 0); +} + +static inline bool +kthread_cancel_work_sync(struct kthread_work *work) +{ + u_int pending = 0; + + if (work->tq != NULL && + taskqueue_cancel(work->tq, &work->task, &pending) != 0) + taskqueue_drain(work->tq, &work->task); + + return (pending != 0); +} + +static inline void +kthread_flush_work(struct kthread_work *work) +{ + if (work->tq != NULL) + taskqueue_drain(work->tq, &work->task); +} + +static inline void +kthread_flush_worker(struct kthread_worker *worker) +{ + taskqueue_drain_all(worker->tq); +} + +#endif /* _LINUXKPI_LINUX_KTHREAD_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ktime.h b/sys/compat/linuxkpi/common/include/linux/ktime.h index 1475674a12e6..6a2f04f3d789 100644 --- a/sys/compat/linuxkpi/common/include/linux/ktime.h +++ b/sys/compat/linuxkpi/common/include/linux/ktime.h @@ -24,12 +24,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_KTIME_H -#define _LINUX_KTIME_H +#ifndef _LINUXKPI_LINUX_KTIME_H +#define _LINUXKPI_LINUX_KTIME_H #include <linux/types.h> #include <linux/time.h> @@ -71,6 +69,12 @@ ktime_to_ms(ktime_t kt) return (ktime_divns(kt, NSEC_PER_MSEC)); } +static inline ktime_t +ms_to_ktime(uint64_t ms) +{ + return (ms * NSEC_PER_MSEC); +} + static inline struct timeval ktime_to_timeval(ktime_t kt) { @@ -190,6 +194,7 @@ timespec64_to_ns(struct timespec64 *ts) #define ktime_get_ts(ts) getnanouptime(ts) #define ktime_get_ts64(ts) getnanouptime(ts) #define ktime_get_raw_ts64(ts) getnanouptime(ts) +#define ktime_get_real_ts64(ts) getnanotime(ts) #define getrawmonotonic64(ts) getnanouptime(ts) static inline int64_t @@ -227,6 +232,13 @@ ktime_get_boottime_ns(void) return (ktime_to_ns(ktime_get_boottime())); } +static inline uint64_t +ktime_get_boottime_seconds(void) +{ + + return (ktime_divns(ktime_get_boottime(), NSEC_PER_SEC)); +} + static inline ktime_t ktime_get_real(void) { @@ -263,4 +275,13 @@ ktime_get_raw_ns(void) return (ktime_to_ns(timespec_to_ktime(ts))); } -#endif /* _LINUX_KTIME_H */ +static inline uint64_t +ktime_get_raw_fast_ns(void) +{ + struct timespec ts; + + getnanouptime(&ts); + return (ktime_to_ns(timespec_to_ktime(ts))); +} + +#endif /* _LINUXKPI_LINUX_KTIME_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/leds.h b/sys/compat/linuxkpi/common/include/linux/leds.h new file mode 100644 index 000000000000..89f7286f6800 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/leds.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_LEDS_H +#define _LINUXKPI_LINUX_LEDS_H + +enum led_brightness { + LED_OFF, +}; + +struct led_classdev { + const char *name; + const char *default_trigger; + int (*blink_set)(struct led_classdev *, unsigned long *, unsigned long *); + void (*brightness_set)(struct led_classdev *, enum led_brightness); + void (*led_set)(struct led_classdev *, enum led_brightness); +}; + +#endif /* _LINUXKPI_LINUX_LEDS_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/limits.h b/sys/compat/linuxkpi/common/include/linux/limits.h new file mode 100644 index 000000000000..716366033bb3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/limits.h @@ -0,0 +1,47 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_LIMITS_H +#define _LINUXKPI_LINUX_LIMITS_H + +#include <sys/types.h> +#include <sys/stdint.h> + +#define U8_MAX UINT8_MAX +#define S8_MAX INT8_MAX +#define S8_MIN INT8_MIN +#define U16_MAX UINT16_MAX +#define S16_MAX INT16_MAX +#define S16_MIN INT16_MIN +#define U32_MAX UINT32_MAX +#define S32_MAX INT32_MAX +#define S32_MIN INT32_MIN +#define U64_MAX UINT64_MAX +#define S64_MAX INT64_MAX +#define S64_MIN INT64_MIN + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/list.h b/sys/compat/linuxkpi/common/include/linux/list.h index 37b5b751d21b..a6c74a324dac 100644 --- a/sys/compat/linuxkpi/common/include/linux/list.h +++ b/sys/compat/linuxkpi/common/include/linux/list.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_LIST_H_ -#define _LINUX_LIST_H_ +#ifndef _LINUXKPI_LINUX_LIST_H_ +#define _LINUXKPI_LINUX_LIST_H_ #ifndef _STANDALONE /* @@ -86,14 +84,6 @@ #define LINUX_LIST_HEAD(name) \ struct list_head name = LINUX_LIST_HEAD_INIT(name) -#ifndef LIST_HEAD_DEF -#define LIST_HEAD_DEF -struct list_head { - struct list_head *next; - struct list_head *prev; -}; -#endif - static inline void INIT_LIST_HEAD(struct list_head *list) { @@ -154,7 +144,7 @@ list_replace_init(struct list_head *old, struct list_head *new) } static inline void -linux_list_add(struct list_head *new, struct list_head *prev, +__list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { @@ -235,22 +225,32 @@ list_del_init(struct list_head *entry) #define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev) +#define list_for_each_prev_safe(p, n, h) \ + for (p = (h)->prev, n = (p)->prev; \ + p != (h); \ + p = n, n = (p)->prev) + #define list_for_each_entry_from_reverse(p, h, field) \ for (; &p->field != (h); \ p = list_prev_entry(p, field)) +#define list_for_each_rcu(p, head) \ + for (p = rcu_dereference((head)->next); \ + p != (head); \ + p = rcu_dereference((p)->next)) + static inline void list_add(struct list_head *new, struct list_head *head) { - linux_list_add(new, head, head->next); + __list_add(new, head, head->next); } static inline void list_add_tail(struct list_head *new, struct list_head *head) { - linux_list_add(new, head->prev, head); + __list_add(new, head->prev, head); } static inline void @@ -270,6 +270,13 @@ list_move_tail(struct list_head *entry, struct list_head *head) } static inline void +list_rotate_to_front(struct list_head *entry, struct list_head *head) +{ + + list_move_tail(entry, head); +} + +static inline void list_bulk_move_tail(struct list_head *head, struct list_head *first, struct list_head *last) { @@ -467,6 +474,20 @@ static inline int list_is_last(const struct list_head *list, return list->next == head; } +static inline size_t +list_count_nodes(const struct list_head *list) +{ + const struct list_head *lh; + size_t count; + + count = 0; + list_for_each(lh, list) { + count++; + } + + return (count); +} + #define hlist_entry(ptr, type, field) container_of(ptr, type, field) #define hlist_for_each(p, head) \ @@ -497,7 +518,12 @@ static inline int list_is_last(const struct list_head *list, (pos) && ({ n = (pos)->member.next; 1; }); \ pos = hlist_entry_safe(n, typeof(*(pos)), member)) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 +extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, + const struct list_head *a, const struct list_head *b)); +#else extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, struct list_head *a, struct list_head *b)); +#endif -#endif /* _LINUX_LIST_H_ */ +#endif /* _LINUXKPI_LINUX_LIST_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/llist.h b/sys/compat/linuxkpi/common/include/linux/llist.h index b3c89516e710..fd842f05e9eb 100644 --- a/sys/compat/linuxkpi/common/include/linux/llist.h +++ b/sys/compat/linuxkpi/common/include/linux/llist.h @@ -1,7 +1,7 @@ /* Public domain. */ -#ifndef _LINUX_LLIST_H -#define _LINUX_LLIST_H +#ifndef _LINUXKPI_LINUX_LLIST_H +#define _LINUXKPI_LINUX_LLIST_H #include <sys/types.h> #include <machine/atomic.h> diff --git a/sys/compat/linuxkpi/common/include/linux/lockdep.h b/sys/compat/linuxkpi/common/include/linux/lockdep.h index d12bd049b820..93fe445f7057 100644 --- a/sys/compat/linuxkpi/common/include/linux/lockdep.h +++ b/sys/compat/linuxkpi/common/include/linux/lockdep.h @@ -25,19 +25,21 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_LOCKDEP_H_ -#define _LINUX_LOCKDEP_H_ +#ifndef _LINUXKPI_LINUX_LOCKDEP_H_ +#define _LINUXKPI_LINUX_LOCKDEP_H_ +#include <sys/systm.h> +#include <sys/types.h> #include <sys/lock.h> struct lock_class_key { }; struct lockdep_map { }; +struct pin_cookie { +}; #define lockdep_set_class(lock, key) #define lockdep_set_subclass(lock, sub) @@ -45,8 +47,18 @@ struct lockdep_map { #define lockdep_set_current_reclaim_state(g) do { } while (0) #define lockdep_clear_current_reclaim_state() do { } while (0) #define lockdep_init_map(_map, _name, _key, _x) do { } while(0) +#define lockdep_register_key(key) do { } while(0) +#define lockdep_unregister_key(key) do { } while(0) #ifdef INVARIANTS +#define lockdep_assert(cond) do { WARN_ON(!(cond)); } while (0) +#define lockdep_assert_once(cond) do { WARN_ON_ONCE(!(cond)); } while (0) + +#define lockdep_assert_not_held(m) do { \ + struct lock_object *__lock = (struct lock_object *)(m); \ + LOCK_CLASS(__lock)->lc_assert(__lock, LA_UNLOCKED); \ +} while (0) + #define lockdep_assert_held(m) do { \ struct lock_object *__lock = (struct lock_object *)(m); \ LOCK_CLASS(__lock)->lc_assert(__lock, LA_LOCKED); \ @@ -57,25 +69,34 @@ struct lockdep_map { LOCK_CLASS(__lock)->lc_assert(__lock, LA_LOCKED | LA_NOTRECURSED); \ } while (0) +#define lockdep_assert_none_held_once() do { } while (0) + +#else +#define lockdep_assert(cond) do { } while (0) +#define lockdep_assert_once(cond) do { } while (0) + +#define lockdep_assert_not_held(m) do { (void)(m); } while (0) +#define lockdep_assert_held(m) do { (void)(m); } while (0) +#define lockdep_assert_none_held_once() do { } while (0) + +#define lockdep_assert_held_once(m) do { (void)(m); } while (0) + +#endif + static __inline bool -lockdep_is_held(void *__m) +lockdep_is_held(void *__m __diagused) { +#ifdef INVARIANTS struct lock_object *__lock; struct thread *__td; __lock = __m; return (LOCK_CLASS(__lock)->lc_owner(__lock, &__td) != 0); -} -#define lockdep_is_held_type(_m, _t) lockdep_is_held(_m) - #else -#define lockdep_assert_held(m) do { } while (0) - -#define lockdep_assert_held_once(m) do { } while (0) - -#define lockdep_is_held(m) 1 -#define lockdep_is_held_type(_m, _t) 1 + return (true); #endif +} +#define lockdep_is_held_type(_m, _t) lockdep_is_held(_m) #define might_lock(m) do { } while (0) #define might_lock_read(m) do { } while (0) @@ -92,8 +113,8 @@ lockdep_is_held(void *__m) #define lock_map_acquire_read(_map) do { } while (0) #define lock_map_release(_map) do { } while (0) -#define lockdep_pin_lock(l) do { } while (0) -#define lockdep_repin_lock(l,c) do { } while (0) -#define lockdep_unpin_lock(l,c) do { } while (0) +#define lockdep_pin_lock(l) ({ struct pin_cookie __pc = { }; __pc; }) +#define lockdep_repin_lock(l,c) do { (void)(l); (void)(c); } while (0) +#define lockdep_unpin_lock(l,c) do { (void)(l); (void)(c); } while (0) -#endif /* _LINUX_LOCKDEP_H_ */ +#endif /* _LINUXKPI_LINUX_LOCKDEP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/log2.h b/sys/compat/linuxkpi/common/include/linux/log2.h index d79eedf38176..660e9adb6fa9 100644 --- a/sys/compat/linuxkpi/common/include/linux/log2.h +++ b/sys/compat/linuxkpi/common/include/linux/log2.h @@ -25,107 +25,17 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_LOG2_H_ -#define _LINUX_LOG2_H_ +#ifndef _LINUXKPI_LINUX_LOG2_H_ +#define _LINUXKPI_LINUX_LOG2_H_ #include <linux/types.h> #include <sys/libkern.h> -static inline unsigned long -roundup_pow_of_two(unsigned long x) -{ - return (1UL << flsl(x - 1)); -} - -static inline int -is_power_of_2(unsigned long n) -{ - return (n == roundup_pow_of_two(n)); -} - -static inline unsigned long -rounddown_pow_of_two(unsigned long x) -{ - return (1UL << (flsl(x) - 1)); -} - -#define ilog2(n) \ -( \ - __builtin_constant_p(n) ? ( \ - (n) < 1 ? -1 : \ - (n) & (1ULL << 63) ? 63 : \ - (n) & (1ULL << 62) ? 62 : \ - (n) & (1ULL << 61) ? 61 : \ - (n) & (1ULL << 60) ? 60 : \ - (n) & (1ULL << 59) ? 59 : \ - (n) & (1ULL << 58) ? 58 : \ - (n) & (1ULL << 57) ? 57 : \ - (n) & (1ULL << 56) ? 56 : \ - (n) & (1ULL << 55) ? 55 : \ - (n) & (1ULL << 54) ? 54 : \ - (n) & (1ULL << 53) ? 53 : \ - (n) & (1ULL << 52) ? 52 : \ - (n) & (1ULL << 51) ? 51 : \ - (n) & (1ULL << 50) ? 50 : \ - (n) & (1ULL << 49) ? 49 : \ - (n) & (1ULL << 48) ? 48 : \ - (n) & (1ULL << 47) ? 47 : \ - (n) & (1ULL << 46) ? 46 : \ - (n) & (1ULL << 45) ? 45 : \ - (n) & (1ULL << 44) ? 44 : \ - (n) & (1ULL << 43) ? 43 : \ - (n) & (1ULL << 42) ? 42 : \ - (n) & (1ULL << 41) ? 41 : \ - (n) & (1ULL << 40) ? 40 : \ - (n) & (1ULL << 39) ? 39 : \ - (n) & (1ULL << 38) ? 38 : \ - (n) & (1ULL << 37) ? 37 : \ - (n) & (1ULL << 36) ? 36 : \ - (n) & (1ULL << 35) ? 35 : \ - (n) & (1ULL << 34) ? 34 : \ - (n) & (1ULL << 33) ? 33 : \ - (n) & (1ULL << 32) ? 32 : \ - (n) & (1ULL << 31) ? 31 : \ - (n) & (1ULL << 30) ? 30 : \ - (n) & (1ULL << 29) ? 29 : \ - (n) & (1ULL << 28) ? 28 : \ - (n) & (1ULL << 27) ? 27 : \ - (n) & (1ULL << 26) ? 26 : \ - (n) & (1ULL << 25) ? 25 : \ - (n) & (1ULL << 24) ? 24 : \ - (n) & (1ULL << 23) ? 23 : \ - (n) & (1ULL << 22) ? 22 : \ - (n) & (1ULL << 21) ? 21 : \ - (n) & (1ULL << 20) ? 20 : \ - (n) & (1ULL << 19) ? 19 : \ - (n) & (1ULL << 18) ? 18 : \ - (n) & (1ULL << 17) ? 17 : \ - (n) & (1ULL << 16) ? 16 : \ - (n) & (1ULL << 15) ? 15 : \ - (n) & (1ULL << 14) ? 14 : \ - (n) & (1ULL << 13) ? 13 : \ - (n) & (1ULL << 12) ? 12 : \ - (n) & (1ULL << 11) ? 11 : \ - (n) & (1ULL << 10) ? 10 : \ - (n) & (1ULL << 9) ? 9 : \ - (n) & (1ULL << 8) ? 8 : \ - (n) & (1ULL << 7) ? 7 : \ - (n) & (1ULL << 6) ? 6 : \ - (n) & (1ULL << 5) ? 5 : \ - (n) & (1ULL << 4) ? 4 : \ - (n) & (1ULL << 3) ? 3 : \ - (n) & (1ULL << 2) ? 2 : \ - (n) & (1ULL << 1) ? 1 : \ - (n) & (1ULL << 0) ? 0 : \ - -1) : \ - (sizeof(n) <= 4) ? \ - fls((u32)(n)) - 1 : flsll((u64)(n)) - 1 \ -) - -#define order_base_2(x) ilog2(roundup_pow_of_two(x)) +#define is_power_of_2(n) ({ \ + __typeof(n) _n = (n); \ + _n != 0 && (_n & (_n - 1)) == 0; \ +}) -#endif /* _LINUX_LOG2_H_ */ +#endif /* _LINUXKPI_LINUX_LOG2_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/math.h b/sys/compat/linuxkpi/common/include/linux/math.h new file mode 100644 index 000000000000..1d50e011f66d --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/math.h @@ -0,0 +1,76 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2013-2015 Mellanox Technologies, Ltd. + * Copyright (c) 2014-2015 François Tigeot + * Copyright (c) 2016 Matt Macy <mmacy@FreeBSD.org> + * Copyright (c) 2019 Johannes Lundberg <johalun@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MATH_H_ +#define _LINUXKPI_LINUX_MATH_H_ + +#include <linux/types.h> + +/* + * This looks more complex than it should be. But we need to + * get the type for the ~ right in round_down (it needs to be + * as wide as the result!), and we want to evaluate the macro + * arguments just once each. + */ +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + +#define DIV_ROUND_UP(x, n) howmany(x, n) +#define DIV_ROUND_UP_ULL(x, n) DIV_ROUND_UP((unsigned long long)(x), (n)) +#define DIV_ROUND_DOWN_ULL(x, n) ((unsigned long long)(x) / (n)) + +#define DIV_ROUND_CLOSEST(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) +#define DIV_ROUND_CLOSEST_ULL(x, divisor) ({ \ + __typeof(divisor) __d = (divisor); \ + unsigned long long __ret = (x) + (__d) / 2; \ + __ret /= __d; \ + __ret; \ +}) + +#if !defined(LINUXKPI_VERSION) || (LINUXKPI_VERSION >= 60600) +#define abs_diff(x, y) ({ \ + __typeof(x) _x = (x); \ + __typeof(y) _y = (y); \ + _x > _y ? _x - _y : _y - _x; \ +}) +#endif + +static inline uintmax_t +mult_frac(uintmax_t x, uintmax_t multiplier, uintmax_t divisor) +{ + uintmax_t q = (x / divisor); + uintmax_t r = (x % divisor); + + return ((q * multiplier) + ((r * multiplier) / divisor)); +} + +#endif /* _LINUXKPI_LINUX_MATH_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/math64.h b/sys/compat/linuxkpi/common/include/linux/math64.h index a3af81c92c9e..25ca9da1b622 100644 --- a/sys/compat/linuxkpi/common/include/linux/math64.h +++ b/sys/compat/linuxkpi/common/include/linux/math64.h @@ -23,14 +23,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_MATH64_H -#define _LINUX_MATH64_H +#ifndef _LINUXKPI_LINUX_MATH64_H +#define _LINUXKPI_LINUX_MATH64_H #include <sys/stdint.h> +#include <sys/systm.h> #define do_div(n, base) ({ \ uint32_t __base = (base); \ @@ -62,6 +61,8 @@ div64_u64(uint64_t dividend, uint64_t divisor) return (dividend / divisor); } +#define div64_ul(x, y) div64_u64((x), (y)) + static inline uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder) { @@ -97,7 +98,80 @@ div64_u64_round_up(uint64_t dividend, uint64_t divisor) return ((dividend + divisor - 1) / divisor); } +static inline uint64_t +roundup_u64(uint64_t x1, uint32_t x2) +{ + return (div_u64(x1 + x2 - 1, x2) * x2); +} + #define DIV64_U64_ROUND_UP(...) \ div64_u64_round_up(__VA_ARGS__) -#endif /* _LINUX_MATH64_H */ +static inline uint64_t +mul_u64_u32_div(uint64_t x, uint32_t y, uint32_t div) +{ + const uint64_t rem = x % div; + + return ((x / div) * y + (rem * y) / div); +} + +static inline uint64_t +mul_u64_u64_div_u64(uint64_t x, uint64_t y, uint64_t z) +{ + uint64_t res, rem; + uint64_t x1, y1, y1z; + + res = rem = 0; + x1 = x; + y1z = y / z; + y1 = y - y1z * z; + + /* + * INVARIANT: x * y = res * z + rem + (y1 + y1z * z) * x1 + * INVARIANT: y1 < z + * INVARIANT: rem < z + */ + while (x1 > 0) { + /* Handle low bit. */ + if (x1 & 1) { + x1 &= ~1; + res += y1z; + rem += y1; + if ((rem < y1) || (rem >= z)) { + res += 1; + rem -= z; + } + } + + /* Shift x1 right and (y1 + y1z * z) left */ + x1 >>= 1; + if ((y1 * 2 < y1) || (y1 * 2 >= z)) { + y1z = y1z * 2 + 1; + y1 = y1 * 2 - z; + } else { + y1z *= 2; + y1 *= 2; + } + } + + KASSERT(res * z + rem == x * y, ("%s: res %ju * z %ju + rem %ju != " + "x %ju * y %ju", __func__, (uintmax_t)res, (uintmax_t)z, + (uintmax_t)rem, (uintmax_t)x, (uintmax_t)y)); + KASSERT(rem < z, ("%s: rem %ju >= z %ju\n", __func__, + (uintmax_t)rem, (uintmax_t)z)); + + return (res); +} + +static inline uint64_t +mul_u64_u32_shr(uint64_t x, uint32_t y, unsigned int shift) +{ + uint32_t hi, lo; + hi = x >> 32; + lo = x & 0xffffffff; + + return (mul_u32_u32(lo, y) >> shift) + + (mul_u32_u32(hi, y) << (32 - shift)); +} + +#endif /* _LINUXKPI_LINUX_MATH64_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/media-bus-format.h b/sys/compat/linuxkpi/common/include/linux/media-bus-format.h new file mode 100644 index 000000000000..1e1954d45409 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/media-bus-format.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_MEDIA_BUS_FORMAT_H_ +#define _LINUXKPI_LINUX_MEDIA_BUS_FORMAT_H_ + +#define MEDIA_BUS_FMT_FIXED 1 + +#endif /* _LINUXKPI_LINUX_MEDIA_BUS_FORMAT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mhi.h b/sys/compat/linuxkpi/common/include/linux/mhi.h new file mode 100644 index 000000000000..24b3205d6f5a --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mhi.h @@ -0,0 +1,222 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MHI_H +#define _LINUXKPI_LINUX_MHI_H + +#include <linux/types.h> + +/* Modem Host Interface (MHI) */ + +/* XXX FIXME */ +#define MHI_DB_BRST_DISABLE 0 +#define MHI_ER_CTRL 0 + +enum mhi_callback { + MHI_CB_SYS_ERROR, + MHI_CB_BW_REQ, + MHI_CB_EE_MISSION_MODE, + MHI_CB_EE_RDDM, + MHI_CB_FATAL_ERROR, + MHI_CB_IDLE, + MHI_CB_LPM_ENTER, + MHI_CB_LPM_EXIT, + MHI_CB_PENDING_DATA, +}; + +struct mhi_channel_config { + const char *name; + int auto_queue, dir, doorbell, doorbell_mode_switch, ee_mask, event_ring, lpm_notify, num, num_elements, offload_channel, pollcfg; +}; + +struct mhi_event_config { + int client_managed, data_type, hardware_event, irq, irq_moderation_ms, mode, num_elements, offload_channel, priority; +}; + +struct mhi_device { +}; + +struct mhi_controller_config { + const struct mhi_channel_config *ch_cfg; + struct mhi_event_config *event_cfg; + + int buf_len, max_channels, num_channels, num_events, use_bounce_buf; + + uint32_t timeout_ms; +}; + +struct mhi_controller { + struct device *cntrl_dev; + struct mhi_device *mhi_dev; + void *regs; + int *irq; + const char *fw_image; + const u8 *fw_data; + size_t fw_sz; + + bool fbc_download; + size_t rddm_size; + size_t sbl_size; + size_t seg_len; + size_t reg_len; + int nr_irqs; + unsigned long irq_flags; + uint32_t timeout_ms; + + dma_addr_t iova_start; + dma_addr_t iova_stop; + + int (*runtime_get)(struct mhi_controller *); + void (*runtime_put)(struct mhi_controller *); + void (*status_cb)(struct mhi_controller *, enum mhi_callback); + int (*read_reg)(struct mhi_controller *, void __iomem *, uint32_t *); + void (*write_reg)(struct mhi_controller *, void __iomem *, uint32_t); +}; + +/* -------------------------------------------------------------------------- */ + +struct mhi_controller *linuxkpi_mhi_alloc_controller(void); +void linuxkpi_mhi_free_controller(struct mhi_controller *); +int linuxkpi_mhi_register_controller(struct mhi_controller *, + const struct mhi_controller_config *); +void linuxkpi_mhi_unregister_controller(struct mhi_controller *); + +/* -------------------------------------------------------------------------- */ + +static inline struct mhi_controller * +mhi_alloc_controller(void) +{ + + /* Keep allocations internal to our implementation. */ + return (linuxkpi_mhi_alloc_controller()); +} + +static inline void +mhi_free_controller(struct mhi_controller *mhi_ctrl) +{ + + linuxkpi_mhi_free_controller(mhi_ctrl); +} + +static inline int +mhi_register_controller(struct mhi_controller *mhi_ctrl, + const struct mhi_controller_config *cfg) +{ + + return (linuxkpi_mhi_register_controller(mhi_ctrl, cfg)); +} + +static inline void +mhi_unregister_controller(struct mhi_controller *mhi_ctrl) +{ + + linuxkpi_mhi_unregister_controller(mhi_ctrl); +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_device_get_sync(struct mhi_device *mhi_dev) +{ + /* XXX TODO */ + return (-1); +} + +static __inline void +mhi_device_put(struct mhi_device *mhi_dev) +{ + /* XXX TODO */ +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_prepare_for_power_up(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_sync_power_up(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_async_power_up(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline void +mhi_power_down(struct mhi_controller *mhi_ctrl, bool x) +{ + /* XXX TODO */ +} + +static __inline void +mhi_unprepare_after_power_down(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_pm_suspend(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_pm_resume(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_pm_resume_force(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_force_rddm_mode(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +#endif /* _LINUXKPI_LINUX_MHI_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/minmax.h b/sys/compat/linuxkpi/common/include/linux/minmax.h new file mode 100644 index 000000000000..d48958f0899f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/minmax.h @@ -0,0 +1,74 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2013-2015 Mellanox Technologies, Ltd. + * Copyright (c) 2014-2015 François Tigeot + * Copyright (c) 2015 Hans Petter Selasky <hselasky@FreeBSD.org> + * Copyright (c) 2016 Matt Macy <mmacy@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MINMAX_H_ +#define _LINUXKPI_LINUX_MINMAX_H_ + +#include <linux/build_bug.h> +#include <linux/compiler.h> +#include <linux/types.h> + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +#define min3(a, b, c) min(a, min(b, c)) +#define max3(a, b, c) max(a, max(b, c)) + +#define min_not_zero(x, y) ({ \ + __typeof(x) __min1 = (x); \ + __typeof(y) __min2 = (y); \ + __min1 == 0 ? __min2 : ((__min2 == 0) ? __min1 : min(__min1, __min2));\ +}) + +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1 : __min2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1 : __max2; }) + +#define clamp_t(type, _x, min, max) min_t(type, max_t(type, _x, min), max) +#define clamp(x, lo, hi) min(max(x, lo), hi) +#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi) + +/* Swap values of a and b */ +#define swap(a, b) do { \ + __typeof(a) _swap_tmp = a; \ + a = b; \ + b = _swap_tmp; \ +} while (0) + +#endif /* _LINUXKPI_LINUX_MINMAX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/miscdevice.h b/sys/compat/linuxkpi/common/include/linux/miscdevice.h index 26a4a2c049c1..c66006a6b78e 100644 --- a/sys/compat/linuxkpi/common/include/linux/miscdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/miscdevice.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_MISCDEVICE_H_ -#define _LINUX_MISCDEVICE_H_ +#ifndef _LINUXKPI_LINUX_MISCDEVICE_H_ +#define _LINUXKPI_LINUX_MISCDEVICE_H_ #define MISC_DYNAMIC_MINOR -1 @@ -73,4 +71,4 @@ misc_deregister(struct miscdevice *misc) return (0); } -#endif /* _LINUX_MISCDEVICE_H_ */ +#endif /* _LINUXKPI_LINUX_MISCDEVICE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mm.h b/sys/compat/linuxkpi/common/include/linux/mm.h index 00583937318b..156b00a0c0f0 100644 --- a/sys/compat/linuxkpi/common/include/linux/mm.h +++ b/sys/compat/linuxkpi/common/include/linux/mm.h @@ -27,18 +27,21 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_MM_H_ -#define _LINUX_MM_H_ +#ifndef _LINUXKPI_LINUX_MM_H_ +#define _LINUXKPI_LINUX_MM_H_ #include <linux/spinlock.h> #include <linux/gfp.h> #include <linux/kernel.h> #include <linux/mm_types.h> +#include <linux/mmzone.h> #include <linux/pfn.h> #include <linux/list.h> +#include <linux/mmap_lock.h> +#include <linux/overflow.h> +#include <linux/shrinker.h> +#include <linux/page.h> #include <asm/pgtable.h> @@ -54,6 +57,8 @@ CTASSERT((VM_PROT_ALL & -(1 << 8)) == 0); #define VM_WRITE VM_PROT_WRITE #define VM_EXEC VM_PROT_EXECUTE +#define VM_ACCESS_FLAGS (VM_READ | VM_WRITE | VM_EXEC) + #define VM_PFNINTERNAL (1 << 8) /* FreeBSD private flag to vm_insert_pfn() */ #define VM_MIXEDMAP (1 << 9) #define VM_NORESERVE (1 << 10) @@ -142,11 +147,28 @@ struct vm_operations_struct { }; struct sysinfo { - uint64_t totalram; - uint64_t totalhigh; - uint32_t mem_unit; + uint64_t totalram; /* Total usable main memory size */ + uint64_t freeram; /* Available memory size */ + uint64_t totalhigh; /* Total high memory size */ + uint64_t freehigh; /* Available high memory size */ + uint32_t mem_unit; /* Memory unit size in bytes */ }; +static inline struct page * +virt_to_head_page(const void *p) +{ + + return (virt_to_page(p)); +} + +static inline struct folio * +virt_to_folio(const void *p) +{ + struct page *page = virt_to_page(p); + + return (page_folio(page)); +} + /* * Compute log2 of the power of two rounded up count of pages * needed for size bytes. @@ -165,6 +187,14 @@ get_order(unsigned long size) return (order); } +/* + * Resolve a page into a virtual address: + * + * NOTE: This function only works for pages allocated by the kernel. + */ +void *linux_page_address(const struct page *); +#define page_address(page) linux_page_address(page) + static inline void * lowmem_page_address(struct page *page) { @@ -216,11 +246,15 @@ apply_to_page_range(struct mm_struct *mm, unsigned long address, int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address, unsigned long size); +int lkpi_remap_pfn_range(struct vm_area_struct *vma, + unsigned long start_addr, unsigned long start_pfn, unsigned long size, + pgprot_t prot); + static inline int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot) { - return (-ENOTSUP); + return (lkpi_remap_pfn_range(vma, addr, pfn, size, prot)); } static inline unsigned long @@ -232,44 +266,114 @@ vma_pages(struct vm_area_struct *vma) #define offset_in_page(off) ((unsigned long)(off) & (PAGE_SIZE - 1)) static inline void -set_page_dirty(struct vm_page *page) +set_page_dirty(struct page *page) { vm_page_dirty(page); } static inline void -mark_page_accessed(struct vm_page *page) +mark_page_accessed(struct page *page) { vm_page_reference(page); } static inline void -get_page(struct vm_page *page) +get_page(struct page *page) { vm_page_wire(page); } +static inline void +put_page(struct page *page) +{ + /* `__free_page()` takes care of the refcounting (unwire). */ + __free_page(page); +} + +static inline void +folio_get(struct folio *folio) +{ + get_page(&folio->page); +} + +static inline void +folio_put(struct folio *folio) +{ + put_page(&folio->page); +} + +/* + * Linux uses the following "transparent" union so that `release_pages()` + * accepts both a list of `struct page` or a list of `struct folio`. This + * relies on the fact that a `struct folio` can be cast to a `struct page`. + */ +typedef union { + struct page **pages; + struct folio **folios; +} release_pages_arg __attribute__ ((__transparent_union__)); + +void linux_release_pages(release_pages_arg arg, int nr); +#define release_pages(arg, nr) linux_release_pages((arg), (nr)) + extern long -get_user_pages(unsigned long start, unsigned long nr_pages, - int gup_flags, struct page **, - struct vm_area_struct **); +lkpi_get_user_pages(unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **); +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60500 +#define get_user_pages(start, nr_pages, gup_flags, pages) \ + lkpi_get_user_pages(start, nr_pages, gup_flags, pages) +#else +#define get_user_pages(start, nr_pages, gup_flags, pages, vmas) \ + lkpi_get_user_pages(start, nr_pages, gup_flags, pages) +#endif + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60500 +static inline long +pin_user_pages(unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **pages) +{ + return (get_user_pages(start, nr_pages, gup_flags, pages)); +} +#else +static inline long +pin_user_pages(unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **pages, + struct vm_area_struct **vmas) +{ + return (get_user_pages(start, nr_pages, gup_flags, pages, vmas)); +} +#endif extern int __get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **); +static inline int +pin_user_pages_fast(unsigned long start, int nr_pages, + unsigned int gup_flags, struct page **pages) +{ + return __get_user_pages_fast( + start, nr_pages, !!(gup_flags & FOLL_WRITE), pages); +} + extern long get_user_pages_remote(struct task_struct *, struct mm_struct *, unsigned long start, unsigned long nr_pages, - int gup_flags, struct page **, + unsigned int gup_flags, struct page **, struct vm_area_struct **); -static inline void -put_page(struct vm_page *page) +static inline long +pin_user_pages_remote(struct task_struct *task, struct mm_struct *mm, + unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **pages, + struct vm_area_struct **vmas) { - vm_page_unwire(page, PQ_ACTIVE); + return get_user_pages_remote( + task, mm, start, nr_pages, gup_flags, pages, vmas); } +#define unpin_user_page(page) put_page(page) +#define unpin_user_pages(pages, npages) release_pages(pages, npages) + #define copy_highpage(to, from) pmap_copy_page(from, to) static inline pgprot_t @@ -278,7 +382,19 @@ vm_get_page_prot(unsigned long vm_flags) return (vm_flags & VM_PROT_ALL); } -static inline vm_page_t +static inline void +vm_flags_set(struct vm_area_struct *vma, unsigned long flags) +{ + vma->vm_flags |= flags; +} + +static inline void +vm_flags_clear(struct vm_area_struct *vma, unsigned long flags) +{ + vma->vm_flags &= ~flags; +} + +static inline struct page * vmalloc_to_page(const void *addr) { vm_paddr_t paddr; @@ -287,13 +403,77 @@ vmalloc_to_page(const void *addr) return (PHYS_TO_VM_PAGE(paddr)); } +static inline int +trylock_page(struct page *page) +{ + return (vm_page_tryxbusy(page)); +} + +static inline void +unlock_page(struct page *page) +{ + + vm_page_xunbusy(page); +} + extern int is_vmalloc_addr(const void *addr); void si_meminfo(struct sysinfo *si); +static inline unsigned long +totalram_pages(void) +{ + return ((unsigned long)physmem); +} + #define unmap_mapping_range(...) lkpi_unmap_mapping_range(__VA_ARGS__) void lkpi_unmap_mapping_range(void *obj, loff_t const holebegin __unused, loff_t const holelen, int even_cows __unused); #define PAGE_ALIGNED(p) __is_aligned(p, PAGE_SIZE) -#endif /* _LINUX_MM_H_ */ +void vma_set_file(struct vm_area_struct *vma, struct linux_file *file); + +static inline void +might_alloc(gfp_t gfp_mask __unused) +{ +} + +#define is_cow_mapping(flags) (false) + +static inline bool +want_init_on_free(void) +{ + return (false); +} + +static inline unsigned long +folio_pfn(struct folio *folio) +{ + return (page_to_pfn(&folio->page)); +} + +static inline long +folio_nr_pages(struct folio *folio) +{ + return (1); +} + +static inline size_t +folio_size(struct folio *folio) +{ + return (PAGE_SIZE); +} + +static inline void +folio_mark_dirty(struct folio *folio) +{ + set_page_dirty(&folio->page); +} + +static inline void * +folio_address(const struct folio *folio) +{ + return (page_address(&folio->page)); +} + +#endif /* _LINUXKPI_LINUX_MM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mm_types.h b/sys/compat/linuxkpi/common/include/linux/mm_types.h index 4c9eddf500d6..3ea68e97004c 100644 --- a/sys/compat/linuxkpi/common/include/linux/mm_types.h +++ b/sys/compat/linuxkpi/common/include/linux/mm_types.h @@ -22,15 +22,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_MM_TYPES_H_ -#define _LINUX_MM_TYPES_H_ +#ifndef _LINUXKPI_LINUX_MM_TYPES_H_ +#define _LINUXKPI_LINUX_MM_TYPES_H_ #include <linux/types.h> #include <linux/page.h> +#include <linux/rbtree.h> #include <linux/rwsem.h> #include <asm/atomic.h> @@ -45,6 +44,7 @@ struct mm_struct { atomic_t mm_count; atomic_t mm_users; size_t pinned_vm; + /* Renamed to mmap_lock in v5.8 */ struct rw_semaphore mmap_sem; }; @@ -79,4 +79,15 @@ mmgrab(struct mm_struct *mm) extern struct mm_struct *linux_get_task_mm(struct task_struct *); #define get_task_mm(task) linux_get_task_mm(task) -#endif /* _LINUX_MM_TYPES_H_ */ +struct folio { + /* + * The page member must be at the beginning because `page_folio(p)` + * casts from a `struct page` to a `struct folio`. + * + * `release_pages()` also relies on this to be able to accept either a + * list of `struct page` or a list of `struct folio`. + */ + struct page page; +}; + +#endif /* _LINUXKPI_LINUX_MM_TYPES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mman.h b/sys/compat/linuxkpi/common/include/linux/mman.h new file mode 100644 index 000000000000..eff80759b4cd --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mman.h @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUX_MMAN_H +#define _LINUX_MMAN_H + +/* + * In Linux, <linux/mman.h> includes <linux/percpu_counter.h>, which includes + * <linux/smp.h>. + */ +#include <linux/smp.h> + +#endif /* _LINUX_MMAN_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/mmap_lock.h b/sys/compat/linuxkpi/common/include/linux/mmap_lock.h new file mode 100644 index 000000000000..de6b2a029b1f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mmap_lock.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_MMAP_LOCK_H_ +#define _LINUXKPI_LINUX_MMAP_LOCK_H_ + +#include <linux/mm_types.h> +#include <linux/rwsem.h> + +static inline void +mmap_read_lock(struct mm_struct *mm) +{ + + down_read(&mm->mmap_sem); +} + +static inline void +mmap_read_unlock(struct mm_struct *mm) +{ + + up_read(&mm->mmap_sem); +} + +static inline void +mmap_write_lock_killable(struct mm_struct *mm) +{ + + down_write_killable(&mm->mmap_sem); +} + +#endif /* _LINUXKPI_LINUX_MMAP_LOCK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mmu_context.h b/sys/compat/linuxkpi/common/include/linux/mmu_context.h new file mode 100644 index 000000000000..4c1bc61b3edb --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mmu_context.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2018 Johannes Lundberg <johalun0@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MMU_CONTEXT_H_ +#define _LINUXKPI_LINUX_MMU_CONTEXT_H_ + +struct mm_struct; + +static inline void +use_mm(struct mm_struct *mm) +{ + /* NOP is deliberate */ +} + +static inline void +unuse_mm(struct mm_struct *mm) +{ + /* NOP is deliberate */ +} + +#endif /* _LINUXKPI_LINUX_MMU_CONTEXT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mmu_notifier.h b/sys/compat/linuxkpi/common/include/linux/mmu_notifier.h new file mode 100644 index 000000000000..2492a6a3bd4f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mmu_notifier.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MMU_NOTIFIER_H_ +#define _LINUXKPI_LINUX_MMU_NOTIFIER_H_ + +struct mmu_notifier { +}; + +#endif /* _LINUXKPI_LINUX_MMU_NOTIFIER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mmzone.h b/sys/compat/linuxkpi/common/include/linux/mmzone.h new file mode 100644 index 000000000000..57d3dcac9597 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mmzone.h @@ -0,0 +1,15 @@ +/* Public domain. */ + +#ifndef _LINUX_MMZONE_H +#define _LINUX_MMZONE_H + +#include <linux/mm_types.h> +#include <linux/numa.h> +#include <linux/page-flags.h> + +#define MAX_ORDER 11 + +#define MAX_PAGE_ORDER 10 +#define NR_PAGE_ORDERS (MAX_PAGE_ORDER + 1) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h index f2a913bc6346..87bd6ec24bce 100644 --- a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h +++ b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h @@ -24,23 +24,27 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUX_MOD_DEVICETABLE_H__ -#define __LINUX_MOD_DEVICETABLE_H__ +#ifndef __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ +#define __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ + +#include <linux/types.h> enum dmi_field { DMI_NONE, DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_BIOS_DATE, + DMI_BIOS_RELEASE, + DMI_EC_FIRMWARE_RELEASE, DMI_SYS_VENDOR, DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_PRODUCT_SERIAL, DMI_PRODUCT_UUID, + DMI_PRODUCT_SKU, + DMI_PRODUCT_FAMILY, DMI_BOARD_VENDOR, DMI_BOARD_NAME, DMI_BOARD_VERSION, @@ -52,10 +56,12 @@ enum dmi_field { DMI_CHASSIS_SERIAL, DMI_CHASSIS_ASSET_TAG, DMI_STRING_MAX, + DMI_OEM_STRING, }; struct dmi_strmatch { - unsigned char slot; + unsigned char slot : 7; + unsigned char exact_match : 1; char substr[79]; }; @@ -67,6 +73,11 @@ struct dmi_system_id { }; #define DMI_MATCH(a, b) { .slot = a, .substr = b } -#define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, } +#define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, .exact_match = 1 } + +#define I2C_NAME_SIZE 20 +#define I2C_MODULE_PREFIX "i2c:" + +#define ACPI_ID_LEN 16 -#endif /* __LINUX_MOD_DEVICETABLE_H__ */ +#endif /* __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/module.h b/sys/compat/linuxkpi/common/include/linux/module.h index 2a4fdc5a11a9..079dacf8df6c 100644 --- a/sys/compat/linuxkpi/common/include/linux/module.h +++ b/sys/compat/linuxkpi/common/include/linux/module.h @@ -25,15 +25,15 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_MODULE_H_ -#define _LINUX_MODULE_H_ +#ifndef _LINUXKPI_LINUX_MODULE_H_ +#define _LINUXKPI_LINUX_MODULE_H_ -#include <sys/cdefs.h> #include <sys/types.h> +#include <sys/param.h> #include <sys/module.h> +#include <sys/queue.h> +#include <sys/linker.h> #include <linux/list.h> #include <linux/compiler.h> @@ -51,8 +51,28 @@ #define MODULE_INFO(tag, info) #define MODULE_FIRMWARE(firmware) #define MODULE_SUPPORTED_DEVICE(name) +#define MODULE_IMPORT_NS(_name) +/* + * THIS_MODULE is used to differentiate modules on Linux. We currently + * completely stub out any Linux struct module usage, but THIS_MODULE is still + * used to populate the "owner" fields of various drivers. Even though we + * don't actually dereference these "owner" fields they are still used by + * drivers to check if devices/dmabufs/etc come from different modules. For + * example, during DRM GEM import some drivers check if the dmabuf's owner + * matches the dev's owner. If they match because they are both NULL drivers + * may incorrectly think two resources come from the same module. + * + * To handle this we specify an undefined symbol __this_linker_file, which + * will get special treatment from the linker when resolving. This will + * populate the usages of __this_linker_file with the linker_file_t of the + * module. + */ +#ifdef KLD_MODULE +#define THIS_MODULE ((struct module *)&__this_linker_file) +#else #define THIS_MODULE ((struct module *)0) +#endif #define __MODULE_STRING(x) __stringify(x) @@ -104,4 +124,4 @@ _module_run(void *arg) #define postcore_initcall(fn) module_init(fn) -#endif /* _LINUX_MODULE_H_ */ +#endif /* _LINUXKPI_LINUX_MODULE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/moduleparam.h b/sys/compat/linuxkpi/common/include/linux/moduleparam.h index 2b48ec1809b7..b61bbce495ea 100644 --- a/sys/compat/linuxkpi/common/include/linux/moduleparam.h +++ b/sys/compat/linuxkpi/common/include/linux/moduleparam.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_MODULEPARAM_H_ -#define _LINUX_MODULEPARAM_H_ +#ifndef _LINUXKPI_LINUX_MODULEPARAM_H_ +#define _LINUXKPI_LINUX_MODULEPARAM_H_ #include <sys/types.h> #include <sys/sysctl.h> @@ -90,6 +88,15 @@ LINUXKPI_PARAM_NAME(name), LINUXKPI_PARAM_PERM(perm), &(var), 0, \ LINUXKPI_PARAM_DESC(name))) +#define LINUXKPI_PARAM_bint(name, var, perm) \ + LINUXKPI_PARAM_int(name, var, perm) + +#define LINUXKPI_PARAM_hexint(name, var, perm) \ + extern const char LINUXKPI_PARAM_DESC(name)[]; \ + LINUXKPI_PARAM_PASS(SYSCTL_UINT(LINUXKPI_PARAM_PARENT, OID_AUTO, \ + LINUXKPI_PARAM_NAME(name), LINUXKPI_PARAM_PERM(perm), &(var), 0, \ + LINUXKPI_PARAM_DESC(name))) + #define LINUXKPI_PARAM_long(name, var, perm) \ extern const char LINUXKPI_PARAM_DESC(name)[]; \ LINUXKPI_PARAM_PASS(SYSCTL_LONG(LINUXKPI_PARAM_PARENT, OID_AUTO, \ @@ -136,4 +143,4 @@ SYSCTL_DECL(_compat_linuxkpi); -#endif /* _LINUX_MODULEPARAM_H_ */ +#endif /* _LINUXKPI_LINUX_MODULEPARAM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mutex.h b/sys/compat/linuxkpi/common/include/linux/mutex.h index bdf0b4dbdb2d..6fb6a7744a89 100644 --- a/sys/compat/linuxkpi/common/include/linux/mutex.h +++ b/sys/compat/linuxkpi/common/include/linux/mutex.h @@ -25,17 +25,18 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_MUTEX_H_ -#define _LINUX_MUTEX_H_ +#ifndef _LINUXKPI_LINUX_MUTEX_H_ +#define _LINUXKPI_LINUX_MUTEX_H_ #include <sys/param.h> #include <sys/proc.h> #include <sys/lock.h> #include <sys/sx.h> +#include <linux/kernel.h> +#include <linux/cleanup.h> +#include <linux/list.h> #include <linux/spinlock.h> #include <asm/atomic.h> @@ -173,4 +174,4 @@ linux_mutex_destroy(mutex_t *m) extern int linux_mutex_lock_interruptible(mutex_t *m); -#endif /* _LINUX_MUTEX_H_ */ +#endif /* _LINUXKPI_LINUX_MUTEX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/net.h b/sys/compat/linuxkpi/common/include/linux/net.h index 5365cd0e9552..a5172f3f31eb 100644 --- a/sys/compat/linuxkpi/common/include/linux/net.h +++ b/sys/compat/linuxkpi/common/include/linux/net.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NET_H_ -#define _LINUX_NET_H_ +#ifndef _LINUXKPI_LINUX_NET_H_ +#define _LINUXKPI_LINUX_NET_H_ #include <sys/types.h> #include <sys/malloc.h> @@ -47,26 +45,27 @@ sock_create_kern(int family, int type, int proto, struct socket **res) } static inline int -sock_getname(struct socket *so, struct sockaddr *addr, int *sockaddr_len, +sock_getname(struct socket *so, struct sockaddr *sa, int *sockaddr_len, int peer) { - struct sockaddr *nam; int error; - nam = NULL; + /* + * XXXGL: we can't use sopeeraddr()/sosockaddr() here since with + * INVARIANTS they would check if supplied sockaddr has enough + * length. Such notion doesn't even exist in Linux KPI. + */ if (peer) { - if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) + if ((so->so_state & SS_ISCONNECTED) == 0) return (-ENOTCONN); - error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &nam); + error = so->so_proto->pr_peeraddr(so, sa); } else - error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &nam); + error = so->so_proto->pr_sockaddr(so, sa); if (error) return (-error); - *addr = *nam; - *sockaddr_len = addr->sa_len; + *sockaddr_len = sa->sa_len; - free(nam, M_SONAME); return (0); } @@ -86,4 +85,4 @@ net_ratelimit(void) return (linuxkpi_net_ratelimit()); } -#endif /* _LINUX_NET_H_ */ +#endif /* _LINUXKPI_LINUX_NET_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/net_dim.h b/sys/compat/linuxkpi/common/include/linux/net_dim.h index f1b7e06b820e..4fe3e39210e7 100644 --- a/sys/compat/linuxkpi/common/include/linux/net_dim.h +++ b/sys/compat/linuxkpi/common/include/linux/net_dim.h @@ -31,14 +31,12 @@ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. - * - * $FreeBSD$ */ /* This file implements Dynamic Interrupt Moderation, DIM */ -#ifndef NET_DIM_H -#define NET_DIM_H +#ifndef _LINUXKPI_LINUX_NET_DIM_H +#define _LINUXKPI_LINUX_NET_DIM_H #include <asm/types.h> @@ -407,4 +405,4 @@ net_dim(struct net_dim *dim, } } -#endif /* NET_DIM_H */ +#endif /* _LINUXKPI_LINUX_NET_DIM_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/netdev_features.h b/sys/compat/linuxkpi/common/include/linux/netdev_features.h index a4901f4d48c3..fae82776b071 100644 --- a/sys/compat/linuxkpi/common/include/linux/netdev_features.h +++ b/sys/compat/linuxkpi/common/include/linux/netdev_features.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2020-2025 The FreeBSD Foundation * * Portions of this software were developed by Björn Zeeb * under sponsorship from the FreeBSD Foundation. @@ -24,25 +24,29 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_NETDEV_FEATURES_H_ -#define __LKPI_LINUX_NETDEV_FEATURES_H_ +#ifndef _LINUXKPI_LINUX_NETDEV_FEATURES_H_ +#define _LINUXKPI_LINUX_NETDEV_FEATURES_H_ #include <linux/types.h> #include <linux/bitops.h> typedef uint32_t netdev_features_t; -#define NETIF_F_HIGHDMA BIT(0) -#define NETIF_F_SG BIT(1) -#define NETIF_F_IP_CSUM BIT(2) -#define NETIF_F_IPV6_CSUM BIT(3) -#define NETIF_F_TSO BIT(4) -#define NETIF_F_TSO6 BIT(5) -#define NETIF_F_RXCSUM BIT(6) +#define NETIF_F_HIGHDMA BIT(0) /* Can DMA to high memory. */ +#define NETIF_F_SG BIT(1) /* Can do scatter/gather I/O. */ +#define NETIF_F_IP_CSUM BIT(2) /* Can csum TCP/UDP on IPv4. */ +#define NETIF_F_IPV6_CSUM BIT(3) /* Can csum TCP/UDP on IPv6. */ +#define NETIF_F_TSO BIT(4) /* Can do TCP over IPv4 segmentation. */ +#define NETIF_F_TSO6 BIT(5) /* Can do TCP over IPv6 segmentation. */ +#define NETIF_F_RXCSUM BIT(6) /* Can do receive csum offload. */ +#define NETIF_F_HW_CSUM BIT(7) /* Can csum packets (which?). */ +#define NETIF_F_HW_TC BIT(8) /* Can offload TC. */ + +#define NETIF_F_CSUM_MASK (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) -#define NETIF_F_CSUM_MASK (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) +#define NETIF_F_BITS \ + "\20\1HIGHDMA\2SG\3IP_CSUM\4IPV6_CSUM\5TSO\6TSO6\7RXCSUM" \ + "\10HW_CSUM\11HW_TC" -#endif /* __LKPI_LINUX_NETDEV_FEATURES_H_ */ +#endif /* _LINUXKPI_LINUX_NETDEV_FEATURES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/netdevice.h b/sys/compat/linuxkpi/common/include/linux/netdevice.h index 1de31b3fa156..cf27753bcb80 100644 --- a/sys/compat/linuxkpi/common/include/linux/netdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/netdevice.h @@ -4,6 +4,11 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2019 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2020-2025 The FreeBSD Foundation + * Copyright (c) 2020-2022 Bjoern A. Zeeb + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,23 +30,36 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NETDEVICE_H_ -#define _LINUX_NETDEVICE_H_ +#ifndef _LINUXKPI_LINUX_NETDEVICE_H +#define _LINUXKPI_LINUX_NETDEVICE_H #include <linux/types.h> +#include <linux/netdev_features.h> +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/malloc.h> +#include <sys/queue.h> #include <sys/socket.h> +#include <sys/taskqueue.h> #include <net/if_types.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_dl.h> +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/list.h> +#include <linux/device.h> #include <linux/net.h> +#include <linux/if_ether.h> #include <linux/notifier.h> +#include <linux/random.h> +#include <linux/rcupdate.h> #ifdef VIMAGE #define init_net *vnet0 @@ -49,13 +67,100 @@ #define init_net *((struct vnet *)0) #endif +struct sk_buff; +struct net_device; +struct wireless_dev; /* net/cfg80211.h */ + #define MAX_ADDR_LEN 20 -#define net_device ifnet +#define NET_NAME_UNKNOWN 0 + +enum net_addr_assign_type { + NET_ADDR_RANDOM, +}; + +enum netdev_tx { + NETDEV_TX_OK = 0, +}; +typedef enum netdev_tx netdev_tx_t; + +struct netdev_hw_addr { + struct list_head addr_list; + uint8_t addr[MAX_ADDR_LEN]; +}; + +struct netdev_hw_addr_list { + struct list_head addr_list; + int count; +}; + +enum net_device_reg_state { + NETREG_DUMMY = 1, + NETREG_REGISTERED, +}; + +enum tc_setup_type { + TC_SETUP_MAX_DUMMY, +}; + +struct net_device_ops { + int (*ndo_open)(struct net_device *); + int (*ndo_stop)(struct net_device *); + int (*ndo_set_mac_address)(struct net_device *, void *); + netdev_tx_t (*ndo_start_xmit)(struct sk_buff *, struct net_device *); + void (*ndo_set_rx_mode)(struct net_device *); +}; + +struct net_device { + /* net_device fields seen publicly. */ + /* XXX can we later make some aliases to ifnet? */ + char name[IFNAMSIZ]; + struct wireless_dev *ieee80211_ptr; + uint8_t dev_addr[ETH_ALEN]; + struct netdev_hw_addr_list mc; + netdev_features_t features; + struct { + unsigned long multicast; + + unsigned long rx_bytes; + unsigned long rx_errors; + unsigned long rx_packets; + unsigned long tx_bytes; + unsigned long tx_dropped; + unsigned long tx_errors; + unsigned long tx_packets; + } stats; + enum net_addr_assign_type addr_assign_type; + enum net_device_reg_state reg_state; + const struct ethtool_ops *ethtool_ops; + const struct net_device_ops *netdev_ops; -#define rtnl_lock() -#define rtnl_unlock() + bool needs_free_netdev; + /* Not properly typed as-of now. */ + int flags, type; + int name_assign_type, needed_headroom; + int threaded; + void (*priv_destructor)(struct net_device *); + + /* net_device internal. */ + struct device dev; + + /* + * In case we delete the net_device we need to be able to clear all + * NAPI consumers. + */ + struct mtx napi_mtx; + TAILQ_HEAD(, napi_struct) napi_head; + struct taskqueue *napi_tq; + + /* Must stay last. */ + uint8_t drv_priv[0] __aligned(CACHE_LINE_SIZE); +}; + +#define SET_NETDEV_DEV(_ndev, _dev) (_ndev)->dev.parent = _dev; + +/* -------------------------------------------------------------------------- */ /* According to linux::ipoib_main.c. */ struct netdev_notifier_info { struct net_device *dev; @@ -79,4 +184,327 @@ int register_inetaddr_notifier(struct notifier_block *); int unregister_netdevice_notifier(struct notifier_block *); int unregister_inetaddr_notifier(struct notifier_block *); -#endif /* _LINUX_NETDEVICE_H_ */ +/* -------------------------------------------------------------------------- */ + +#define NAPI_POLL_WEIGHT 64 /* budget */ + +/* + * There are drivers directly testing napi state bits, so we need to publicly + * expose them. If you ask me, those accesses should be hid behind an + * inline function and the bit flags not be directly exposed. + */ +enum napi_state_bits { + /* + * Official Linux flags encountered. + */ + NAPI_STATE_SCHED = 1, + + /* + * Our internal versions (for now). + */ + /* Do not schedule new things while we are waiting to clear things. */ + LKPI_NAPI_FLAG_DISABLE_PENDING = 0, + /* To synchronise that only one poll is ever running. */ + LKPI_NAPI_FLAG_IS_SCHEDULED = 1, + /* If trying to schedule while poll is running. Need to re-schedule. */ + LKPI_NAPI_FLAG_LOST_RACE_TRY_AGAIN = 2, + /* When shutting down forcefully prevent anything from running task/poll. */ + LKPI_NAPI_FLAG_SHUTDOWN = 3, +}; + +struct napi_struct { + TAILQ_ENTRY(napi_struct) entry; + + struct list_head rx_list; + struct net_device *dev; + int (*poll)(struct napi_struct *, int); + int budget; + int rx_count; + + + /* + * These flags mostly need to be checked/changed atomically + * (multiple together in some cases). + */ + volatile unsigned long state; + + /* FreeBSD internal. */ + /* Use task for now, so we can easily switch between direct and task. */ + struct task napi_task; +}; + +void linuxkpi_init_dummy_netdev(struct net_device *); +void linuxkpi_netif_napi_add(struct net_device *, struct napi_struct *, + int(*napi_poll)(struct napi_struct *, int)); +void linuxkpi_netif_napi_del(struct napi_struct *); +bool linuxkpi_napi_schedule_prep(struct napi_struct *); +void linuxkpi___napi_schedule(struct napi_struct *); +bool linuxkpi_napi_schedule(struct napi_struct *); +void linuxkpi_napi_reschedule(struct napi_struct *); +bool linuxkpi_napi_complete_done(struct napi_struct *, int); +bool linuxkpi_napi_complete(struct napi_struct *); +void linuxkpi_napi_disable(struct napi_struct *); +void linuxkpi_napi_enable(struct napi_struct *); +void linuxkpi_napi_synchronize(struct napi_struct *); + +#define init_dummy_netdev(_n) \ + linuxkpi_init_dummy_netdev(_n) +#define netif_napi_add(_nd, _ns, _p) \ + linuxkpi_netif_napi_add(_nd, _ns, _p) +#define netif_napi_del(_n) \ + linuxkpi_netif_napi_del(_n) +#define napi_schedule_prep(_n) \ + linuxkpi_napi_schedule_prep(_n) +#define __napi_schedule(_n) \ + linuxkpi___napi_schedule(_n) +#define napi_schedule(_n) \ + linuxkpi_napi_schedule(_n) +#define napi_reschedule(_n) \ + linuxkpi_napi_reschedule(_n) +#define napi_complete_done(_n, _r) \ + linuxkpi_napi_complete_done(_n, _r) +#define napi_complete(_n) \ + linuxkpi_napi_complete(_n) +#define napi_disable(_n) \ + linuxkpi_napi_disable(_n) +#define napi_enable(_n) \ + linuxkpi_napi_enable(_n) +#define napi_synchronize(_n) \ + linuxkpi_napi_synchronize(_n) + + +static inline void +netif_napi_add_tx(struct net_device *dev, struct napi_struct *napi, + int(*napi_poll)(struct napi_struct *, int)) +{ + + netif_napi_add(dev, napi, napi_poll); +} + +static inline bool +napi_is_scheduled(struct napi_struct *napi) +{ + + return (test_bit(LKPI_NAPI_FLAG_IS_SCHEDULED, &napi->state)); +} + +/* -------------------------------------------------------------------------- */ + +static inline void +netdev_rss_key_fill(uint32_t *buf, size_t len) +{ + + /* + * Remembering from a previous life there was discussions on what is + * a good RSS hash key. See end of rss_init() in net/rss_config.c. + * iwlwifi is looking for a 10byte "secret" so stay with random for now. + */ + get_random_bytes(buf, len); +} + +static inline void +__hw_addr_init(struct netdev_hw_addr_list *list) +{ + list->count = 0; + INIT_LIST_HEAD(&list->addr_list); +} + +static inline int +netdev_hw_addr_list_count(struct netdev_hw_addr_list *list) +{ + + return (list->count); +} + +static inline int +netdev_mc_count(struct net_device *ndev) +{ + + return (netdev_hw_addr_list_count(&ndev->mc)); +} + +#define netdev_hw_addr_list_for_each(_addr, _list) \ + list_for_each_entry((_addr), &(_list)->addr_list, addr_list) + +#define netdev_for_each_mc_addr(na, ndev) \ + netdev_hw_addr_list_for_each(na, &(ndev)->mc) + +static __inline void +synchronize_net(void) +{ + + /* We probably cannot do that unconditionally at some point anymore. */ + synchronize_rcu(); +} + +static __inline void +netif_receive_skb_list(struct list_head *head) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static __inline int +napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) +{ + + pr_debug("%s: TODO\n", __func__); + return (-1); +} + +static __inline void +ether_setup(struct net_device *ndev) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +dev_net_set(struct net_device *ndev, void *p) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static __inline int +dev_set_threaded(struct net_device *ndev, bool threaded) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENODEV); +} + +/* -------------------------------------------------------------------------- */ + +static __inline bool +netif_carrier_ok(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); + return (false); +} + +static __inline void +netif_carrier_off(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +netif_carrier_on(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +/* -------------------------------------------------------------------------- */ + +static __inline bool +netif_queue_stopped(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); + return (false); +} + +static __inline void +netif_stop_queue(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +netif_wake_queue(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +register_netdevice(struct net_device *ndev) +{ + + /* assert rtnl_locked? */ + pr_debug("%s: TODO\n", __func__); + return (0); +} + +static __inline int +register_netdev(struct net_device *ndev) +{ + int error; + + /* lock */ + error = register_netdevice(ndev); + /* unlock */ + pr_debug("%s: TODO\n", __func__); + return (error); +} + +static __inline void +unregister_netdev(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +unregister_netdevice(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +/* -------------------------------------------------------------------------- */ + +static __inline void +netif_rx(struct sk_buff *skb) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +netif_rx_ni(struct sk_buff *skb) +{ + pr_debug("%s: TODO\n", __func__); +} + +/* -------------------------------------------------------------------------- */ + +struct net_device *linuxkpi_alloc_netdev(size_t, const char *, uint32_t, + void(*)(struct net_device *)); +void linuxkpi_free_netdev(struct net_device *); + +#define alloc_netdev(_l, _n, _f, _func) \ + linuxkpi_alloc_netdev(_l, _n, _f, _func) +#define alloc_netdev_dummy(_l) \ + linuxkpi_alloc_netdev(_l, "dummy", NET_NAME_UNKNOWN, NULL) +#define free_netdev(_n) \ + linuxkpi_free_netdev(_n) + +static inline void * +netdev_priv(const struct net_device *ndev) +{ + + return (__DECONST(void *, ndev->drv_priv)); +} + +/* -------------------------------------------------------------------------- */ + +static __inline void +netif_device_attach(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +netif_device_detach(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + + +/* -------------------------------------------------------------------------- */ +/* This is really rtnetlink and probably belongs elsewhere. */ + +#define rtnl_lock() do { } while(0) +#define rtnl_unlock() do { } while(0) +#define rcu_dereference_rtnl(x) READ_ONCE(x) + +#endif /* _LINUXKPI_LINUX_NETDEVICE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/nl80211.h b/sys/compat/linuxkpi/common/include/linux/nl80211.h new file mode 100644 index 000000000000..845ffec4bcba --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/nl80211.h @@ -0,0 +1,455 @@ +/*- + * Copyright (c) 2020-2024 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_NL80211_H +#define _LINUXKPI_LINUX_NL80211_H + +#include <linux/bitops.h> + +enum nl80211_feature_flags { + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE = BIT(0), + NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES = BIT(1), + NL80211_FEATURE_HT_IBSS = BIT(2), + NL80211_FEATURE_LOW_PRIORITY_SCAN = BIT(3), + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = BIT(4), + NL80211_FEATURE_P2P_GO_CTWIN = BIT(5), + NL80211_FEATURE_P2P_GO_OPPPS = BIT(6), + NL80211_FEATURE_QUIET = BIT(7), + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = BIT(8), + NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = BIT(9), + NL80211_FEATURE_DYNAMIC_SMPS = BIT(10), + NL80211_FEATURE_STATIC_SMPS = BIT(11), + NL80211_FEATURE_SUPPORTS_WMM_ADMISSION = BIT(12), + NL80211_FEATURE_TDLS_CHANNEL_SWITCH = BIT(13), + NL80211_FEATURE_TX_POWER_INSERTION = BIT(14), + NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = BIT(15), + NL80211_FEATURE_AP_SCAN = BIT(16), + NL80211_FEATURE_ACTIVE_MONITOR = BIT(17), + NL80211_FEATURE_SAE = BIT(18), +}; + +enum nl80211_pmsr_ftm_failure_flags { + NL80211_PMSR_FTM_FAILURE_NO_RESPONSE = BIT(0), + NL80211_PMSR_FTM_FAILURE_PEER_BUSY = BIT(1), + NL80211_PMSR_FTM_FAILURE_UNSPECIFIED = BIT(2), +}; + +enum nl80211_pmsr_status_flags { + NL80211_PMSR_STATUS_FAILURE = BIT(0), + NL80211_PMSR_STATUS_SUCCESS = BIT(1), + NL80211_PMSR_STATUS_TIMEOUT = BIT(2), +}; + +#define NL80211_PMSR_TYPE_FTM 1 + +enum nl80211_reg_rule_flags { + NL80211_RRF_AUTO_BW = BIT(0), + NL80211_RRF_DFS = BIT(1), + NL80211_RRF_GO_CONCURRENT = BIT(2), + NL80211_RRF_NO_IR = BIT(3), + NL80211_RRF_NO_OUTDOOR = BIT(4), + NL80211_RRF_NO_HT40MINUS = BIT(5), + NL80211_RRF_NO_HT40PLUS = BIT(6), + NL80211_RRF_NO_80MHZ = BIT(7), + NL80211_RRF_NO_160MHZ = BIT(8), + NL80211_RRF_NO_HE = BIT(9), + NL80211_RRF_NO_OFDM = BIT(10), + NL80211_RRF_NO_320MHZ = BIT(11), + NL80211_RRF_NO_EHT = BIT(12), + NL80211_RRF_DFS_CONCURRENT = BIT(13), + NL80211_RRF_NO_6GHZ_VLP_CLIENT = BIT(14), + NL80211_RRF_NO_6GHZ_AFC_CLIENT = BIT(15), + NL80211_RRF_PSD = BIT(16), + NL80211_RRF_ALLOW_6GHZ_VLP_AP = BIT(17), + NL80211_RRF_ALLOW_20MHZ_ACTIVITY = BIT(18), +}; +#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS|NL80211_RRF_NO_HT40PLUS) + +enum nl80211_scan_flags { + NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME = BIT(0), + NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = BIT(1), + NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE = BIT(2), + NL80211_SCAN_FLAG_RANDOM_ADDR = BIT(3), + NL80211_SCAN_FLAG_COLOCATED_6GHZ = BIT(4), + NL80211_SCAN_FLAG_RANDOM_SN = BIT(5), + NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP = BIT(6), +}; + +#define NL80211_MAX_SUPP_REG_RULES 512 /* TODO FIXME, random */ + +#define NL80211_BSS_CHAN_WIDTH_20 __LINE__ /* TODO FIXME, brcmfmac */ + +enum nl80211_wpa_versions { + NL80211_WPA_VERSION_1 = 1, + NL80211_WPA_VERSION_2, + NL80211_WPA_VERSION_3, +}; + +enum nl80211_bss_select_attr { + __NL80211_BSS_SELECT_ATTR_INVALID = 0, + NL80211_BSS_SELECT_ATTR_BAND_PREF, + NL80211_BSS_SELECT_ATTR_RSSI, + NL80211_BSS_SELECT_ATTR_RSSI_ADJUST, +}; + +enum nl80211_sta_flag { + /* XXX TODO */ + NL80211_STA_FLAG_ASSOCIATED, + NL80211_STA_FLAG_AUTHENTICATED, + NL80211_STA_FLAG_AUTHORIZED, + NL80211_STA_FLAG_TDLS_PEER, + NL80211_STA_FLAG_WME, +}; + +enum nl80211_band { + /* XXX TODO */ + NL80211_BAND_2GHZ = 0, + NL80211_BAND_5GHZ, + NL80211_BAND_60GHZ, + NL80211_BAND_6GHZ, + + /* Keep this last. */ + NUM_NL80211_BANDS +} __packed; + +enum nl80211_channel_type { + NL80211_CHAN_NO_HT, + NL80211_CHAN_HT20, + NL80211_CHAN_HT40PLUS, + NL80211_CHAN_HT40MINUS, +}; + +enum nl80211_chan_width { + /* XXX TODO */ + NL80211_CHAN_WIDTH_20_NOHT, + NL80211_CHAN_WIDTH_20, + NL80211_CHAN_WIDTH_40, + NL80211_CHAN_WIDTH_80, + NL80211_CHAN_WIDTH_80P80, + NL80211_CHAN_WIDTH_160, + NL80211_CHAN_WIDTH_5, + NL80211_CHAN_WIDTH_10, + NL80211_CHAN_WIDTH_320, +}; + +enum nl80211_iftype { + /* XXX TODO */ + NL80211_IFTYPE_UNSPECIFIED, + NL80211_IFTYPE_ADHOC, + NL80211_IFTYPE_STATION, + NL80211_IFTYPE_AP, + NL80211_IFTYPE_AP_VLAN, + NL80211_IFTYPE_MONITOR, + NL80211_IFTYPE_P2P_CLIENT, + NL80211_IFTYPE_P2P_DEVICE, + NL80211_IFTYPE_P2P_GO, + NL80211_IFTYPE_MESH_POINT, + NL80211_IFTYPE_WDS, + NL80211_IFTYPE_OCB, + NL80211_IFTYPE_NAN, + + /* Keep this last. */ + NUM_NL80211_IFTYPES +}; + +enum nl80211_preamble { + /* XXX TODO */ + NL80211_PREAMBLE_LEGACY, + NL80211_PREAMBLE_HT, + NL80211_PREAMBLE_VHT, + NL80211_PREAMBLE_HE, +}; + +enum nl80211_tdls_operation { + /* XXX TODO */ + NL80211_TDLS_SETUP, + NL80211_TDLS_TEARDOWN, + NL80211_TDLS_ENABLE_LINK, + NL80211_TDLS_DISABLE_LINK, + NL80211_TDLS_DISCOVERY_REQ, +}; + +enum nl80211_cqm_rssi_threshold_event { + /* XXX TODO */ + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, +}; + +enum nl80211_ext_feature { + /* XXX TODO */ + NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP, + NL80211_EXT_FEATURE_BSS_PARENT_TSF, + NL80211_EXT_FEATURE_CAN_REPLACE_PTK0, + NL80211_EXT_FEATURE_DFS_OFFLOAD, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER, + NL80211_EXT_FEATURE_EXT_KEY_ID, + NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME, + NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER, + NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION, + NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE, + NL80211_EXT_FEATURE_PROTECTED_TWT, + NL80211_EXT_FEATURE_SAE_OFFLOAD, + NL80211_EXT_FEATURE_SCAN_START_TIME, + NL80211_EXT_FEATURE_SET_SCAN_DWELL, + NL80211_EXT_FEATURE_VHT_IBSS, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK, + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT, + NL80211_EXT_FEATURE_SCAN_RANDOM_SN, + NL80211_EXT_FEATURE_STA_TX_PWR, + NL80211_EXT_FEATURE_CQM_RSSI_LIST, + NL80211_EXT_FEATURE_AQL, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS, + NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT, + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, + NL80211_EXT_FEATURE_BEACON_RATE_HT, + NL80211_EXT_FEATURE_BEACON_RATE_VHT, + NL80211_EXT_FEATURE_BEACON_RATE_HE, + NL80211_EXT_FEATURE_BSS_COLOR, + NL80211_EXT_FEATURE_FILS_DISCOVERY, + NL80211_EXT_FEATURE_RADAR_BACKGROUND, + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP, + NL80211_EXT_FEATURE_BEACON_PROTECTION, + NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT, + NL80211_EXT_FEATURE_PUNCT, + NL80211_EXT_FEATURE_DFS_CONCURRENT, + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS, + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT, + NL80211_EXT_FEATURE_SECURE_LTF, + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK, + NL80211_EXT_FEATURE_SAE_OFFLOAD_AP, + + /* Keep this last. */ + NUM_NL80211_EXT_FEATURES +}; + +/* Keep in order with lkpi_nl80211_sta_info_to_str() */ +enum nl80211_sta_info { + /* XXX TODO */ + NL80211_STA_INFO_BEACON_RX, + NL80211_STA_INFO_BEACON_SIGNAL_AVG, + NL80211_STA_INFO_BSS_PARAM, + NL80211_STA_INFO_CHAIN_SIGNAL, + NL80211_STA_INFO_CHAIN_SIGNAL_AVG, + NL80211_STA_INFO_CONNECTED_TIME, + NL80211_STA_INFO_INACTIVE_TIME, + NL80211_STA_INFO_SIGNAL, + NL80211_STA_INFO_SIGNAL_AVG, + NL80211_STA_INFO_STA_FLAGS, + NL80211_STA_INFO_RX_BITRATE, + NL80211_STA_INFO_RX_PACKETS, + NL80211_STA_INFO_RX_BYTES, + NL80211_STA_INFO_RX_DROP_MISC, + NL80211_STA_INFO_TX_BITRATE, + NL80211_STA_INFO_TX_PACKETS, + NL80211_STA_INFO_TX_BYTES, + NL80211_STA_INFO_TX_BYTES64, + NL80211_STA_INFO_RX_BYTES64, + NL80211_STA_INFO_TX_FAILED, + NL80211_STA_INFO_TX_RETRIES, + NL80211_STA_INFO_RX_DURATION, + NL80211_STA_INFO_TX_DURATION, + NL80211_STA_INFO_ACK_SIGNAL, + NL80211_STA_INFO_ACK_SIGNAL_AVG, +}; + +enum nl80211_ftm_stats { + /* XXX TODO */ + NL80211_FTM_STATS_ASAP_NUM, + NL80211_FTM_STATS_FAILED_NUM, + NL80211_FTM_STATS_NON_ASAP_NUM, + NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM, + NL80211_FTM_STATS_PARTIAL_NUM, + NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM, + NL80211_FTM_STATS_SUCCESS_NUM, + NL80211_FTM_STATS_TOTAL_DURATION_MSEC, + NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM, +}; + +enum nl80211_reg_initiator { + /* XXX TODO */ + NL80211_REGDOM_SET_BY_USER, + NL80211_REGDOM_SET_BY_DRIVER, + NL80211_REGDOM_SET_BY_CORE, + NL80211_REGDOM_SET_BY_COUNTRY_IE, +}; + +struct nl80211_sta_flag_update { + /* XXX TODO */ + int mask, set; + +}; + +enum nl80211_tx_power_setting { + /* XXX TODO */ + NL80211_TX_POWER_AUTOMATIC, + NL80211_TX_POWER_FIXED, + NL80211_TX_POWER_LIMITED, +}; + +enum nl80211_crit_proto_id { + /* XXX TODO */ + NL80211_CRIT_PROTO_DHCP, +}; + +enum nl80211_auth_type { + NL80211_AUTHTYPE_AUTOMATIC, + NL80211_AUTHTYPE_OPEN_SYSTEM, + NL80211_AUTHTYPE_SHARED_KEY, + NL80211_AUTHTYPE_SAE, +}; + +enum nl80211_key_type { + NL80211_KEYTYPE_GROUP, + NL80211_KEYTYPE_PAIRWISE, +}; + +enum nl80211_he_ru_alloc { + NL80211_RATE_INFO_HE_RU_ALLOC_26, + NL80211_RATE_INFO_HE_RU_ALLOC_52, + NL80211_RATE_INFO_HE_RU_ALLOC_106, + NL80211_RATE_INFO_HE_RU_ALLOC_242, + NL80211_RATE_INFO_HE_RU_ALLOC_484, + NL80211_RATE_INFO_HE_RU_ALLOC_996, + NL80211_RATE_INFO_HE_RU_ALLOC_2x996, +}; + +enum nl80211_he_gi { + NL80211_RATE_INFO_HE_GI_0_8, + NL80211_RATE_INFO_HE_GI_1_6, + NL80211_RATE_INFO_HE_GI_3_2, +}; + +enum nl80211_he_ltf { + NL80211_RATE_INFO_HE_1XLTF, + NL80211_RATE_INFO_HE_2XLTF, + NL80211_RATE_INFO_HE_4XLTF, +}; + +enum nl80211_eht_gi { + NL80211_RATE_INFO_EHT_GI_0_8, + NL80211_RATE_INFO_EHT_GI_1_6, + NL80211_RATE_INFO_EHT_GI_3_2, +}; + +enum nl80211_eht_ru_alloc { + NL80211_RATE_INFO_EHT_RU_ALLOC_26, + NL80211_RATE_INFO_EHT_RU_ALLOC_52, + NL80211_RATE_INFO_EHT_RU_ALLOC_52P26, + NL80211_RATE_INFO_EHT_RU_ALLOC_106, + NL80211_RATE_INFO_EHT_RU_ALLOC_106P26, + NL80211_RATE_INFO_EHT_RU_ALLOC_242, + NL80211_RATE_INFO_EHT_RU_ALLOC_484, + NL80211_RATE_INFO_EHT_RU_ALLOC_484P242, + NL80211_RATE_INFO_EHT_RU_ALLOC_996, + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242, + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996, + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996, + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_4x996, +}; + +enum nl80211_dfs_regions { + NL80211_DFS_UNSET, + NL80211_DFS_FCC, + NL80211_DFS_ETSI, + NL80211_DFS_JP, +}; + +enum nl80211_dfs_state { + NL80211_DFS_USABLE, +}; + +enum nl80211_sar_type { + NL80211_SAR_TYPE_POWER, +}; + +#define NL80211_VHT_NSS_MAX 8 +#define NL80211_HE_NSS_MAX 8 + +enum nl80211_tid_cfg_attr { + NL80211_TID_CONFIG_ATTR_NOACK, + NL80211_TID_CONFIG_ATTR_RETRY_SHORT, + NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, + NL80211_TID_CONFIG_ATTR_TX_RATE, + NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL, + NL80211_TID_CONFIG_ATTR_RETRY_LONG, + NL80211_TID_CONFIG_ATTR_AMPDU_CTRL, + NL80211_TID_CONFIG_ATTR_AMSDU_CTRL, +}; + +enum nl80211_tid_config { + NL80211_TID_CONFIG_ENABLE, +}; + +enum nl80211_tx_rate_setting { + NL80211_TX_RATE_AUTOMATIC, + NL80211_TX_RATE_FIXED, + NL80211_TX_RATE_LIMITED, +}; + +enum nl80211_txrate_gi { + NL80211_TXRATE_DEFAULT_GI, + NL80211_TXRATE_FORCE_SGI, + NL80211_TXRATE_FORCE_LGI, +}; + +enum nl80211_probe_resp_offload_support { + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P, +}; + +enum nl80211_user_reg_hint_type { + NL80211_USER_REG_HINT_USER, +}; + +enum nl80211_hidden_ssid { + NL80211_HIDDEN_SSID_NOT_IN_USE, +}; + +enum nl80211_external_auth_action { + NL80211_EXTERNAL_AUTH_START, +}; + +enum nl80211_rxmgmt_flags { + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = BIT(1), +}; + +#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 +#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 + +#define NL80211_KCK_LEN 16 +#define NL80211_KCK_EXT_LEN 24 +#define NL80211_KEK_LEN 16 +#define NL80211_KEK_EXT_LEN 32 +#define NL80211_REPLAY_CTR_LEN 8 +#endif /* _LINUXKPI_LINUX_NL80211_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/nodemask.h b/sys/compat/linuxkpi/common/include/linux/nodemask.h new file mode 100644 index 000000000000..7a245cc6f256 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/nodemask.h @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_NODEMASK_H_ +#define _LINUXKPI_LINUX_NODEMASK_H_ + +#include <linux/kernel.h> /* pr_debug */ + +static inline int +num_online_nodes(void) +{ + return (1); +} + +static inline int +num_possible_nodes(void) +{ + pr_debug("%s: TODO\n", __func__); + return (1); +} + +#endif /* _LINUXKPI_LINUX_NODEMASK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/nospec.h b/sys/compat/linuxkpi/common/include/linux/nospec.h new file mode 100644 index 000000000000..e8458ae8b371 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/nospec.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_NOSPEC_H_ +#define _LINUXKPI_LINUX_NOSPEC_H_ + +#define array_index_nospec(a, b) (a) + +#endif /* _LINUXKPILINUX_NOSPEC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/notifier.h b/sys/compat/linuxkpi/common/include/linux/notifier.h index ae292439bf54..9302a1ce4606 100644 --- a/sys/compat/linuxkpi/common/include/linux/notifier.h +++ b/sys/compat/linuxkpi/common/include/linux/notifier.h @@ -25,16 +25,17 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NOTIFIER_H_ -#define _LINUX_NOTIFIER_H_ +#ifndef _LINUXKPI_LINUX_NOTIFIER_H_ +#define _LINUXKPI_LINUX_NOTIFIER_H_ #include <sys/types.h> #include <sys/eventhandler.h> -#define NOTIFY_DONE 0 +#define NOTIFY_DONE 0 +#define NOTIFY_OK 0x0001 +#define NOTIFY_STOP_MASK 0x8000 +#define NOTIFY_BAD (NOTIFY_STOP_MASK | 0x0002) enum { NETDEV_CHANGE, @@ -54,4 +55,4 @@ struct notifier_block { eventhandler_tag tags[LINUX_NOTIFY_TAGS]; }; -#endif /* _LINUX_NOTIFIER_H_ */ +#endif /* _LINUXKPI_LINUX_NOTIFIER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/numa.h b/sys/compat/linuxkpi/common/include/linux/numa.h index 19455349a7a6..6b227e177a64 100644 --- a/sys/compat/linuxkpi/common/include/linux/numa.h +++ b/sys/compat/linuxkpi/common/include/linux/numa.h @@ -24,13 +24,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NUMA_H_ -#define _LINUX_NUMA_H_ +#ifndef _LINUXKPI_LINUX_NUMA_H_ +#define _LINUXKPI_LINUX_NUMA_H_ #define NUMA_NO_NODE -1 -#endif /* _LINUX_NUMA_H_ */ +#endif /* _LINUXKPI_LINUX_NUMA_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/of.h b/sys/compat/linuxkpi/common/include/linux/of.h new file mode 100644 index 000000000000..fb4554a8ddbc --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/of.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_OF_H +#define _LINUXKPI_LINUX_OF_H + +#include <linux/kobject.h> + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/overflow.h b/sys/compat/linuxkpi/common/include/linux/overflow.h index 2d540796cd43..e811037b8ecc 100644 --- a/sys/compat/linuxkpi/common/include/linux/overflow.h +++ b/sys/compat/linuxkpi/common/include/linux/overflow.h @@ -1,53 +1,475 @@ -/*- - * Copyright (c) 2020 The FreeBSD Foundation - * - * This software was developed by Emmanuel Vadot under sponsorship - * from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef __LINUX_OVERFLOW_H__ -#define __LINUX_OVERFLOW_H__ - -#include <sys/stdint.h> -#include <sys/types.h> - -#define check_add_overflow(a, b, c) \ - __builtin_add_overflow(a, b, c) - -#define check_mul_overflow(a, b, c) \ - __builtin_mul_overflow(a, b, c) - -static inline size_t -array_size(size_t x, size_t y) +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +#ifndef _LINUXKPI_LINUX_OVERFLOW_H +#define _LINUXKPI_LINUX_OVERFLOW_H + +#include <linux/compiler.h> +#include <linux/limits.h> +#ifdef __linux__ +#include <linux/const.h> +#endif + +/* + * We need to compute the minimum and maximum values representable in a given + * type. These macros may also be useful elsewhere. It would seem more obvious + * to do something like: + * + * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0) + * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0) + * + * Unfortunately, the middle expressions, strictly speaking, have + * undefined behaviour, and at least some versions of gcc warn about + * the type_max expression (but not if -fsanitize=undefined is in + * effect; in that case, the warning is deferred to runtime...). + * + * The slightly excessive casting in type_min is to make sure the + * macros also produce sensible values for the exotic type _Bool. [The + * overflow checkers only almost work for _Bool, but that's + * a-feature-not-a-bug, since people shouldn't be doing arithmetic on + * _Bools. Besides, the gcc builtins don't allow _Bool* as third + * argument.] + * + * Idea stolen from + * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html - + * credit to Christian Biere. + */ +#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) +#define __type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) +#define type_max(t) __type_max(typeof(t)) +#define __type_min(T) ((T)((T)-type_max(T)-(T)1)) +#define type_min(t) __type_min(typeof(t)) + +/* + * Avoids triggering -Wtype-limits compilation warning, + * while using unsigned data types to check a < 0. + */ +#define is_non_negative(a) ((a) > 0 || (a) == 0) +#define is_negative(a) (!(is_non_negative(a))) + +/* + * Allows for effectively applying __must_check to a macro so we can have + * both the type-agnostic benefits of the macros while also being able to + * enforce that the return value is, in fact, checked. + */ +static inline bool __must_check __must_check_overflow(bool overflow) +{ + return unlikely(overflow); +} + +/** + * check_add_overflow() - Calculate addition with overflow checking + * @a: first addend + * @b: second addend + * @d: pointer to store sum + * + * Returns true on wrap-around, false otherwise. + * + * *@d holds the results of the attempted addition, regardless of whether + * wrap-around occurred. + */ +#define check_add_overflow(a, b, d) \ + __must_check_overflow(__builtin_add_overflow(a, b, d)) + +/** + * wrapping_add() - Intentionally perform a wrapping addition + * @type: type for result of calculation + * @a: first addend + * @b: second addend + * + * Return the potentially wrapped-around addition without + * tripping any wrap-around sanitizers that may be enabled. + */ +#define wrapping_add(type, a, b) \ + ({ \ + type __val; \ + __builtin_add_overflow(a, b, &__val); \ + __val; \ + }) + +/** + * wrapping_assign_add() - Intentionally perform a wrapping increment assignment + * @var: variable to be incremented + * @offset: amount to add + * + * Increments @var by @offset with wrap-around. Returns the resulting + * value of @var. Will not trip any wrap-around sanitizers. + * + * Returns the new value of @var. + */ +#define wrapping_assign_add(var, offset) \ + ({ \ + typeof(var) *__ptr = &(var); \ + *__ptr = wrapping_add(typeof(var), *__ptr, offset); \ + }) + +/** + * check_sub_overflow() - Calculate subtraction with overflow checking + * @a: minuend; value to subtract from + * @b: subtrahend; value to subtract from @a + * @d: pointer to store difference + * + * Returns true on wrap-around, false otherwise. + * + * *@d holds the results of the attempted subtraction, regardless of whether + * wrap-around occurred. + */ +#define check_sub_overflow(a, b, d) \ + __must_check_overflow(__builtin_sub_overflow(a, b, d)) + +/** + * wrapping_sub() - Intentionally perform a wrapping subtraction + * @type: type for result of calculation + * @a: minuend; value to subtract from + * @b: subtrahend; value to subtract from @a + * + * Return the potentially wrapped-around subtraction without + * tripping any wrap-around sanitizers that may be enabled. + */ +#define wrapping_sub(type, a, b) \ + ({ \ + type __val; \ + __builtin_sub_overflow(a, b, &__val); \ + __val; \ + }) + +/** + * wrapping_assign_sub() - Intentionally perform a wrapping decrement assign + * @var: variable to be decremented + * @offset: amount to subtract + * + * Decrements @var by @offset with wrap-around. Returns the resulting + * value of @var. Will not trip any wrap-around sanitizers. + * + * Returns the new value of @var. + */ +#define wrapping_assign_sub(var, offset) \ + ({ \ + typeof(var) *__ptr = &(var); \ + *__ptr = wrapping_sub(typeof(var), *__ptr, offset); \ + }) + +/** + * check_mul_overflow() - Calculate multiplication with overflow checking + * @a: first factor + * @b: second factor + * @d: pointer to store product + * + * Returns true on wrap-around, false otherwise. + * + * *@d holds the results of the attempted multiplication, regardless of whether + * wrap-around occurred. + */ +#define check_mul_overflow(a, b, d) \ + __must_check_overflow(__builtin_mul_overflow(a, b, d)) + +/** + * wrapping_mul() - Intentionally perform a wrapping multiplication + * @type: type for result of calculation + * @a: first factor + * @b: second factor + * + * Return the potentially wrapped-around multiplication without + * tripping any wrap-around sanitizers that may be enabled. + */ +#define wrapping_mul(type, a, b) \ + ({ \ + type __val; \ + __builtin_mul_overflow(a, b, &__val); \ + __val; \ + }) + +/** + * check_shl_overflow() - Calculate a left-shifted value and check overflow + * @a: Value to be shifted + * @s: How many bits left to shift + * @d: Pointer to where to store the result + * + * Computes *@d = (@a << @s) + * + * Returns true if '*@d' cannot hold the result or when '@a << @s' doesn't + * make sense. Example conditions: + * + * - '@a << @s' causes bits to be lost when stored in *@d. + * - '@s' is garbage (e.g. negative) or so large that the result of + * '@a << @s' is guaranteed to be 0. + * - '@a' is negative. + * - '@a << @s' sets the sign bit, if any, in '*@d'. + * + * '*@d' will hold the results of the attempted shift, but is not + * considered "safe for use" if true is returned. + */ +#define check_shl_overflow(a, s, d) __must_check_overflow(({ \ + typeof(a) _a = a; \ + typeof(s) _s = s; \ + typeof(d) _d = d; \ + unsigned long long _a_full = _a; \ + unsigned int _to_shift = \ + is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \ + *_d = (_a_full << _to_shift); \ + (_to_shift != _s || is_negative(*_d) || is_negative(_a) || \ + (*_d >> _to_shift) != _a); \ +})) + +#define __overflows_type_constexpr(x, T) ( \ + is_unsigned_type(typeof(x)) ? \ + (x) > type_max(T) : \ + is_unsigned_type(typeof(T)) ? \ + (x) < 0 || (x) > type_max(T) : \ + (x) < type_min(T) || (x) > type_max(T)) + +#define __overflows_type(x, T) ({ \ + typeof(T) v = 0; \ + check_add_overflow((x), v, &v); \ +}) + +/** + * overflows_type - helper for checking the overflows between value, variables, + * or data type + * + * @n: source constant value or variable to be checked + * @T: destination variable or data type proposed to store @x + * + * Compares the @x expression for whether or not it can safely fit in + * the storage of the type in @T. @x and @T can have different types. + * If @x is a constant expression, this will also resolve to a constant + * expression. + * + * Returns: true if overflow can occur, false otherwise. + */ +#define overflows_type(n, T) \ + __builtin_choose_expr(__is_constexpr(n), \ + __overflows_type_constexpr(n, T), \ + __overflows_type(n, T)) + +/** + * castable_to_type - like __same_type(), but also allows for casted literals + * + * @n: variable or constant value + * @T: variable or data type + * + * Unlike the __same_type() macro, this allows a constant value as the + * first argument. If this value would not overflow into an assignment + * of the second argument's type, it returns true. Otherwise, this falls + * back to __same_type(). + */ +#define castable_to_type(n, T) \ + __builtin_choose_expr(__is_constexpr(n), \ + !__overflows_type_constexpr(n, T), \ + __same_type(n, T)) + +/** + * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX + * @factor1: first factor + * @factor2: second factor + * + * Returns: calculate @factor1 * @factor2, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. The + * lvalue must be size_t to avoid implicit type conversion. + */ +static inline size_t __must_check size_mul(size_t factor1, size_t factor2) { - size_t retval; + size_t bytes; + + if (check_mul_overflow(factor1, factor2, &bytes)) + return SIZE_MAX; - if (__builtin_mul_overflow(x, y, &retval)) - retval = SIZE_MAX; - return (retval); + return bytes; } -#endif /* __LINUX_OVERFLOW_H__ */ +/** + * size_add() - Calculate size_t addition with saturation at SIZE_MAX + * @addend1: first addend + * @addend2: second addend + * + * Returns: calculate @addend1 + @addend2, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. The + * lvalue must be size_t to avoid implicit type conversion. + */ +static inline size_t __must_check size_add(size_t addend1, size_t addend2) +{ + size_t bytes; + + if (check_add_overflow(addend1, addend2, &bytes)) + return SIZE_MAX; + + return bytes; +} + +/** + * size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX + * @minuend: value to subtract from + * @subtrahend: value to subtract from @minuend + * + * Returns: calculate @minuend - @subtrahend, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. For + * composition with the size_add() and size_mul() helpers, neither + * argument may be SIZE_MAX (or the result with be forced to SIZE_MAX). + * The lvalue must be size_t to avoid implicit type conversion. + */ +static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) +{ + size_t bytes; + + if (minuend == SIZE_MAX || subtrahend == SIZE_MAX || + check_sub_overflow(minuend, subtrahend, &bytes)) + return SIZE_MAX; + + return bytes; +} + +/** + * array_size() - Calculate size of 2-dimensional array. + * @a: dimension one + * @b: dimension two + * + * Calculates size of 2-dimensional array: @a * @b. + * + * Returns: number of bytes needed to represent the array or SIZE_MAX on + * overflow. + */ +#define array_size(a, b) size_mul(a, b) + +/** + * array3_size() - Calculate size of 3-dimensional array. + * @a: dimension one + * @b: dimension two + * @c: dimension three + * + * Calculates size of 3-dimensional array: @a * @b * @c. + * + * Returns: number of bytes needed to represent the array or SIZE_MAX on + * overflow. + */ +#define array3_size(a, b, c) size_mul(size_mul(a, b), c) + +/** + * flex_array_size() - Calculate size of a flexible array member + * within an enclosing structure. + * @p: Pointer to the structure. + * @member: Name of the flexible array member. + * @count: Number of elements in the array. + * + * Calculates size of a flexible array of @count number of @member + * elements, at the end of structure @p. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define flex_array_size(p, member, count) \ + __builtin_choose_expr(__is_constexpr(count), \ + (count) * sizeof(*(p)->member) + __must_be_array((p)->member), \ + size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member))) + +/** + * struct_size() - Calculate size of structure with trailing flexible array. + * @p: Pointer to the structure. + * @member: Name of the array member. + * @count: Number of elements in the array. + * + * Calculates size of memory needed for structure of @p followed by an + * array of @count number of @member elements. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define struct_size(p, member, count) \ + __builtin_choose_expr(__is_constexpr(count), \ + sizeof(*(p)) + flex_array_size(p, member, count), \ + size_add(sizeof(*(p)), flex_array_size(p, member, count))) + +/** + * struct_size_t() - Calculate size of structure with trailing flexible array + * @type: structure type name. + * @member: Name of the array member. + * @count: Number of elements in the array. + * + * Calculates size of memory needed for structure @type followed by an + * array of @count number of @member elements. Prefer using struct_size() + * when possible instead, to keep calculations associated with a specific + * instance variable of type @type. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define struct_size_t(type, member, count) \ + struct_size((type *)NULL, member, count) + +/** + * __DEFINE_FLEX() - helper macro for DEFINE_FLEX() family. + * Enables caller macro to pass arbitrary trailing expressions + * + * @type: structure type name, including "struct" keyword. + * @name: Name for a variable to define. + * @member: Name of the array member. + * @count: Number of elements in the array; must be compile-time const. + * @trailer: Trailing expressions for attributes and/or initializers. + */ +#define __DEFINE_FLEX(type, name, member, count, trailer...) \ + _Static_assert(__builtin_constant_p(count), \ + "onstack flex array members require compile-time const count"); \ + union { \ + u8 bytes[struct_size_t(type, member, count)]; \ + type obj; \ + } name##_u trailer; \ + type *name = (type *)&name##_u + +/** + * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family. + * Enables caller macro to pass (different) initializer. + * + * @type: structure type name, including "struct" keyword. + * @name: Name for a variable to define. + * @member: Name of the array member. + * @count: Number of elements in the array; must be compile-time const. + * @initializer: Initializer expression (e.g., pass `= { }` at minimum). + */ +#define _DEFINE_FLEX(type, name, member, count, initializer...) \ + __DEFINE_FLEX(type, name, member, count, = { .obj initializer }) + +/** + * DEFINE_RAW_FLEX() - Define an on-stack instance of structure with a trailing + * flexible array member, when it does not have a __counted_by annotation. + * + * @type: structure type name, including "struct" keyword. + * @name: Name for a variable to define. + * @member: Name of the array member. + * @count: Number of elements in the array; must be compile-time const. + * + * Define a zeroed, on-stack, instance of @type structure with a trailing + * flexible array member. + * Use __struct_size(@name) to get compile-time size of it afterwards. + * Use __member_size(@name->member) to get compile-time size of @name members. + * Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of + * elements in array @member. + */ +#define DEFINE_RAW_FLEX(type, name, member, count) \ + __DEFINE_FLEX(type, name, member, count, = { }) + +/** + * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing + * flexible array member. + * + * @TYPE: structure type name, including "struct" keyword. + * @NAME: Name for a variable to define. + * @MEMBER: Name of the array member. + * @COUNTER: Name of the __counted_by member. + * @COUNT: Number of elements in the array; must be compile-time const. + * + * Define a zeroed, on-stack, instance of @TYPE structure with a trailing + * flexible array member. + * Use __struct_size(@NAME) to get compile-time size of it afterwards. + * Use __member_size(@NAME->member) to get compile-time size of @NAME members. + * Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of + * elements in array @member. + */ +#define DEFINE_FLEX(TYPE, NAME, MEMBER, COUNTER, COUNT) \ + _DEFINE_FLEX(TYPE, NAME, MEMBER, COUNT, = { .COUNTER = COUNT, }) + +/** + * STACK_FLEX_ARRAY_SIZE() - helper macro for DEFINE_FLEX() family. + * Returns the number of elements in @array. + * + * @name: Name for a variable defined in DEFINE_RAW_FLEX()/DEFINE_FLEX(). + * @array: Name of the array member. + */ +#define STACK_FLEX_ARRAY_SIZE(name, array) \ + (__member_size((name)->array) / sizeof(*(name)->array) + \ + __must_be_array((name)->array)) + +#endif /* _LINUXKPI_LINUX_OVERFLOW_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/page-flags.h b/sys/compat/linuxkpi/common/include/linux/page-flags.h new file mode 100644 index 000000000000..a22b3a24c330 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/page-flags.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PAGEFLAGS_H_ +#define _LINUXKPI_LINUX_PAGEFLAGS_H_ + +#include <linux/mm_types.h> + +#define PageHighMem(p) (0) + +#define page_folio(p) \ + (_Generic((p), \ + const struct page *: (const struct folio *)(p), \ + struct page *: (struct folio *)(p))) + +#endif /* _LINUXKPI_LINUX_PAGEFLAGS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/page.h b/sys/compat/linuxkpi/common/include/linux/page.h index 0c3d456d6ec0..37ab593a64e9 100644 --- a/sys/compat/linuxkpi/common/include/linux/page.h +++ b/sys/compat/linuxkpi/common/include/linux/page.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PAGE_H_ -#define _LINUX_PAGE_H_ +#ifndef _LINUXKPI_LINUX_PAGE_H_ +#define _LINUXKPI_LINUX_PAGE_H_ #include <linux/types.h> @@ -74,6 +72,7 @@ pgprot2cachemode(pgprot_t prot) return (VM_MEMATTR_DEFAULT); } +#define page_to_virt(page) linux_page_address(page) #define virt_to_page(x) PHYS_TO_VM_PAGE(vtophys(x)) #define page_to_pfn(pp) (VM_PAGE_TO_PHYS(pp) >> PAGE_SHIFT) #define pfn_to_page(pfn) (PHYS_TO_VM_PAGE((pfn) << PAGE_SHIFT)) @@ -105,6 +104,7 @@ pgprot2cachemode(pgprot_t prot) #define trunc_page(x) ((uintptr_t)(x) & ~(PAGE_SIZE - 1)) #if defined(__i386__) || defined(__amd64__) +#undef clflush #undef clflushopt static inline void lkpi_clflushopt(unsigned long addr) @@ -116,7 +116,15 @@ lkpi_clflushopt(unsigned long addr) else pmap_invalidate_cache(); } +#define clflush(x) clflush((unsigned long)(x)) #define clflushopt(x) lkpi_clflushopt((unsigned long)(x)) + +static inline void +clflush_cache_range(void *addr, unsigned int size) +{ + pmap_force_invalidate_cache_range((vm_offset_t)addr, + (vm_offset_t)addr + size); +} #endif -#endif /* _LINUX_PAGE_H_ */ +#endif /* _LINUXKPI_LINUX_PAGE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pagemap.h b/sys/compat/linuxkpi/common/include/linux/pagemap.h index 100bcfaeb433..cb6a1820ea8b 100644 --- a/sys/compat/linuxkpi/common/include/linux/pagemap.h +++ b/sys/compat/linuxkpi/common/include/linux/pagemap.h @@ -24,22 +24,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PAGEMAP_H_ -#define _LINUX_PAGEMAP_H_ +#ifndef _LINUXKPI_LINUX_PAGEMAP_H_ +#define _LINUXKPI_LINUX_PAGEMAP_H_ #include <linux/mm.h> +#include <linux/highmem.h> +#include <linux/vmalloc.h> + +struct folio_batch; + +#define invalidate_mapping_pages(...) \ + linux_invalidate_mapping_pages(__VA_ARGS__) + +unsigned long linux_invalidate_mapping_pages(vm_object_t obj, pgoff_t start, + pgoff_t end); static inline void -release_pages(struct page **pages, int nr) +mapping_clear_unevictable(vm_object_t mapping) { - int i; - - for (i = 0; i < nr; i++) - put_page(pages[i]); } #endif diff --git a/sys/compat/linuxkpi/common/include/linux/pagevec.h b/sys/compat/linuxkpi/common/include/linux/pagevec.h new file mode 100644 index 000000000000..0a952e965b5a --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/pagevec.h @@ -0,0 +1,137 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_PAGEVEC_H_ +#define _LINUXKPI_LINUX_PAGEVEC_H_ + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/errno.h> + +#include <linux/pagemap.h> + +#define PAGEVEC_SIZE 15 + +struct pagevec { + uint8_t nr; + struct page *pages[PAGEVEC_SIZE]; +}; + +static inline unsigned int +pagevec_space(struct pagevec *pvec) +{ + return PAGEVEC_SIZE - pvec->nr; +} + +static inline void +pagevec_init(struct pagevec *pvec) +{ + pvec->nr = 0; +} + +static inline void +pagevec_reinit(struct pagevec *pvec) +{ + pvec->nr = 0; +} + +static inline unsigned int +pagevec_count(struct pagevec *pvec) +{ + return pvec->nr; +} + +static inline unsigned int +pagevec_add(struct pagevec *pvec, struct page *page) +{ + pvec->pages[pvec->nr++] = page; + return PAGEVEC_SIZE - pvec->nr; +} + +static inline void +__pagevec_release(struct pagevec *pvec) +{ + release_pages(pvec->pages, pagevec_count(pvec)); + pagevec_reinit(pvec); +} + +static inline void +pagevec_release(struct pagevec *pvec) +{ + if (pagevec_count(pvec)) + __pagevec_release(pvec); +} + +static inline void +check_move_unevictable_pages(struct pagevec *pvec) +{ +} + +/* + * struct folio + * + * On Linux, `struct folio` replaces `struct page`. To manage a list of folios, + * there is `struct folio_batch` on top of this, which replaces `struct + * pagevec` above. + * + * Here is the original description when `struct folio` was added to the Linux + * kernel: + * "A struct folio is a new abstraction to replace the venerable struct page. + * A function which takes a struct folio argument declares that it will + * operate on the entire (possibly compound) page, not just PAGE_SIZE bytes. + * In return, the caller guarantees that the pointer it is passing does not + * point to a tail page. No change to generated code." + */ + +struct folio; + +struct folio_batch { + uint8_t nr; + struct folio *folios[PAGEVEC_SIZE]; +}; + +static inline void +folio_batch_init(struct folio_batch *fbatch) +{ + fbatch->nr = 0; +} + +static inline void +folio_batch_reinit(struct folio_batch *fbatch) +{ + fbatch->nr = 0; +} + +static inline unsigned int +folio_batch_count(struct folio_batch *fbatch) +{ + return (fbatch->nr); +} + +static inline unsigned int +folio_batch_space(struct folio_batch *fbatch) +{ + return (PAGEVEC_SIZE - fbatch->nr); +} + +static inline unsigned int +folio_batch_add(struct folio_batch *fbatch, struct folio *folio) +{ + KASSERT( + fbatch->nr < PAGEVEC_SIZE, + ("struct folio_batch %p is full", fbatch)); + + fbatch->folios[fbatch->nr++] = folio; + + return (folio_batch_space(fbatch)); +} + +void __folio_batch_release(struct folio_batch *fbatch); + +static inline void +folio_batch_release(struct folio_batch *fbatch) +{ + if (folio_batch_count(fbatch)) + __folio_batch_release(fbatch); +} + +#endif /* _LINUXKPI_LINUX_PAGEVEC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index 1b4f55c2a2e5..06336bf963d6 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -4,7 +4,7 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. * All rights reserved. - * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2020-2025 The FreeBSD Foundation * * Portions of this software were developed by Björn Zeeb * under sponsorship from the FreeBSD Foundation. @@ -29,22 +29,20 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PCI_H_ -#define _LINUX_PCI_H_ +#ifndef _LINUXKPI_LINUX_PCI_H_ +#define _LINUXKPI_LINUX_PCI_H_ #define CONFIG_PCI_MSI #include <linux/types.h> +#include <linux/device/driver.h> #include <sys/param.h> #include <sys/bus.h> +#include <sys/module.h> #include <sys/nv.h> #include <sys/pciio.h> -#include <sys/rman.h> -#include <sys/bus.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> #include <dev/pci/pci_private.h> @@ -57,8 +55,12 @@ #include <linux/compiler.h> #include <linux/errno.h> #include <asm/atomic.h> +#include <asm/memtype.h> #include <linux/device.h> #include <linux/pci_ids.h> +#include <linux/pm.h> + +#include <linux/kernel.h> /* pr_debug */ struct pci_device_id { uint32_t vendor; @@ -70,7 +72,27 @@ struct pci_device_id { uintptr_t driver_data; }; -#define MODULE_DEVICE_TABLE(bus, table) +#define MODULE_DEVICE_TABLE_BUS_pci(_bus, _table) \ +MODULE_PNP_INFO("U32:vendor;U32:device;V32:subvendor;V32:subdevice", \ + _bus, lkpi_ ## _table, _table, nitems(_table) - 1) + +/* Linux has an empty element at the end of the ID table -> nitems() - 1. */ +#define MODULE_DEVICE_TABLE(_bus, _table) \ + \ +static device_method_t _ ## _bus ## _ ## _table ## _methods[] = { \ + DEVMETHOD_END \ +}; \ + \ +static driver_t _ ## _bus ## _ ## _table ## _driver = { \ + "lkpi_" #_bus #_table, \ + _ ## _bus ## _ ## _table ## _methods, \ + 0 \ +}; \ + \ +DRIVER_MODULE(lkpi_ ## _table, _bus, _ ## _bus ## _ ## _table ## _driver,\ + 0, 0); \ + \ +MODULE_DEVICE_TABLE_BUS_ ## _bus(_bus, _table) #define PCI_ANY_ID -1U @@ -78,6 +100,7 @@ struct pci_device_id { #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) #define PCI_BUS_NUM(devfn) (((devfn) >> 8) & 0xff) +#define PCI_DEVID(bus, devfn) ((((uint16_t)(bus)) << 8) | (devfn)) #define PCI_VDEVICE(_vendor, _device) \ .vendor = PCI_VENDOR_ID_##_vendor, .device = (_device), \ @@ -88,14 +111,25 @@ struct pci_device_id { #define to_pci_dev(n) container_of(n, struct pci_dev, dev) -#define PCI_VENDOR_ID PCIR_DEVVENDOR +#define PCI_STD_NUM_BARS 6 +#define PCI_BASE_ADDRESS_0 PCIR_BARS +#define PCI_BASE_ADDRESS_MEM_TYPE_64 PCIM_BAR_MEM_64 +#define PCI_VENDOR_ID PCIR_VENDOR +#define PCI_DEVICE_ID PCIR_DEVICE #define PCI_COMMAND PCIR_COMMAND #define PCI_COMMAND_INTX_DISABLE PCIM_CMD_INTxDIS +#define PCI_COMMAND_MEMORY PCIM_CMD_MEMEN +#define PCI_PRIMARY_BUS PCIR_PRIBUS_1 +#define PCI_SECONDARY_BUS PCIR_SECBUS_1 +#define PCI_SUBORDINATE_BUS PCIR_SUBBUS_1 +#define PCI_SEC_LATENCY_TIMER PCIR_SECLAT_1 #define PCI_EXP_DEVCTL PCIER_DEVICE_CTL /* Device Control */ #define PCI_EXP_LNKCTL PCIER_LINK_CTL /* Link Control */ #define PCI_EXP_LNKCTL_ASPM_L0S PCIEM_LINK_CTL_ASPMC_L0S #define PCI_EXP_LNKCTL_ASPM_L1 PCIEM_LINK_CTL_ASPMC_L1 +#define PCI_EXP_LNKCTL_ASPMC PCIEM_LINK_CTL_ASPMC #define PCI_EXP_LNKCTL_CLKREQ_EN PCIEM_LINK_CTL_ECPM /* Enable clock PM */ +#define PCI_EXP_LNKCTL_HAWD PCIEM_LINK_CTL_HAWD #define PCI_EXP_FLAGS_TYPE PCIEM_FLAGS_TYPE /* Device/Port type */ #define PCI_EXP_DEVCAP PCIER_DEVICE_CAP /* Device capabilities */ #define PCI_EXP_DEVSTA PCIER_DEVICE_STA /* Device Status */ @@ -110,6 +144,7 @@ struct pci_device_id { #define PCI_EXP_DEVCAP2 PCIER_DEVICE_CAP2 /* Device Capabilities 2 */ #define PCI_EXP_DEVCTL2 PCIER_DEVICE_CTL2 /* Device Control 2 */ #define PCI_EXP_DEVCTL2_LTR_EN PCIEM_CTL2_LTR_ENABLE +#define PCI_EXP_DEVCTL2_COMP_TMOUT_DIS PCIEM_CTL2_COMP_TIMO_DISABLE #define PCI_EXP_LNKCAP2 PCIER_LINK_CAP2 /* Link Capabilities 2 */ #define PCI_EXP_LNKCTL2 PCIER_LINK_CTL2 /* Link Control 2 */ #define PCI_EXP_LNKSTA2 PCIER_LINK_STA2 /* Link Status 2 */ @@ -121,25 +156,38 @@ struct pci_device_id { #define PCI_EXP_TYPE_DOWNSTREAM PCIEM_TYPE_DOWNSTREAM_PORT /* Downstream Port */ #define PCI_EXP_FLAGS_SLOT PCIEM_FLAGS_SLOT /* Slot implemented */ #define PCI_EXP_TYPE_RC_EC PCIEM_TYPE_ROOT_EC /* Root Complex Event Collector */ +#define PCI_EXP_LNKSTA_CLS PCIEM_LINK_STA_SPEED +#define PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP_SLS_2_5GB 0x01 /* Supported Link Speed 2.5GT/s */ #define PCI_EXP_LNKCAP_SLS_5_0GB 0x02 /* Supported Link Speed 5.0GT/s */ -#define PCI_EXP_LNKCAP_SLS_8_0GB 0x04 /* Supported Link Speed 8.0GT/s */ -#define PCI_EXP_LNKCAP_SLS_16_0GB 0x08 /* Supported Link Speed 16.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_8_0GB 0x03 /* Supported Link Speed 8.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_16_0GB 0x04 /* Supported Link Speed 16.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_32_0GB 0x05 /* Supported Link Speed 32.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_64_0GB 0x06 /* Supported Link Speed 64.0GT/s */ #define PCI_EXP_LNKCAP_MLW 0x03f0 /* Maximum Link Width */ #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */ #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_16_0GB 0x10 /* Supported Link Speed 16.0GT/s */ +#define PCI_EXP_LNKCAP2_SLS_32_0GB 0x20 /* Supported Link Speed 32.0GT/s */ +#define PCI_EXP_LNKCAP2_SLS_64_0GB 0x40 /* Supported Link Speed 64.0GT/s */ #define PCI_EXP_LNKCTL2_TLS 0x000f #define PCI_EXP_LNKCTL2_TLS_2_5GT 0x0001 /* Supported Speed 2.5GT/s */ #define PCI_EXP_LNKCTL2_TLS_5_0GT 0x0002 /* Supported Speed 5GT/s */ #define PCI_EXP_LNKCTL2_TLS_8_0GT 0x0003 /* Supported Speed 8GT/s */ #define PCI_EXP_LNKCTL2_TLS_16_0GT 0x0004 /* Supported Speed 16GT/s */ #define PCI_EXP_LNKCTL2_TLS_32_0GT 0x0005 /* Supported Speed 32GT/s */ +#define PCI_EXP_LNKCTL2_TLS_64_0GT 0x0006 /* Supported Speed 64GT/s */ #define PCI_EXP_LNKCTL2_ENTER_COMP 0x0010 /* Enter Compliance */ #define PCI_EXP_LNKCTL2_TX_MARGIN 0x0380 /* Transmit Margin */ -#define PCI_EXP_LNKCTL_HAWD PCIEM_LINK_CTL_HAWD +#define PCI_MSI_ADDRESS_LO PCIR_MSI_ADDR +#define PCI_MSI_ADDRESS_HI PCIR_MSI_ADDR_HIGH +#define PCI_MSI_FLAGS PCIR_MSI_CTRL +#define PCI_MSI_FLAGS_ENABLE PCIM_MSICTRL_MSI_ENABLE +#define PCI_MSIX_FLAGS PCIR_MSIX_CTRL +#define PCI_MSIX_FLAGS_ENABLE PCIM_MSIXCTRL_MSIX_ENABLE + #define PCI_EXP_LNKCAP_CLKPM 0x00040000 #define PCI_EXP_DEVSTA_TRPND 0x0020 @@ -153,6 +201,8 @@ enum pci_bus_speed { PCIE_SPEED_5_0GT, PCIE_SPEED_8_0GT, PCIE_SPEED_16_0GT, + PCIE_SPEED_32_0GT, + PCIE_SPEED_64_0GT, }; enum pcie_link_width { @@ -173,22 +223,35 @@ enum pcie_link_width { typedef int pci_power_t; -#define PCI_D0 PCI_POWERSTATE_D0 -#define PCI_D1 PCI_POWERSTATE_D1 -#define PCI_D2 PCI_POWERSTATE_D2 -#define PCI_D3hot PCI_POWERSTATE_D3 -#define PCI_D3cold 4 +#define PCI_D0 PCI_POWERSTATE_D0 +#define PCI_D1 PCI_POWERSTATE_D1 +#define PCI_D2 PCI_POWERSTATE_D2 +#define PCI_D3hot PCI_POWERSTATE_D3_HOT +#define PCI_D3cold PCI_POWERSTATE_D3_COLD #define PCI_POWER_ERROR PCI_POWERSTATE_UNKNOWN +extern const char *pci_power_names[6]; + +#define PCI_ERR_UNCOR_STATUS PCIR_AER_UC_STATUS +#define PCI_ERR_COR_STATUS PCIR_AER_COR_STATUS #define PCI_ERR_ROOT_COMMAND PCIR_AER_ROOTERR_CMD #define PCI_ERR_ROOT_ERR_SRC PCIR_AER_COR_SOURCE_ID #define PCI_EXT_CAP_ID_ERR PCIZ_AER +#define PCI_EXT_CAP_ID_L1SS PCIZ_L1PM + +#define PCI_L1SS_CTL1 0x8 +#define PCI_L1SS_CTL1_L1SS_MASK 0xf -#define PCI_IRQ_LEGACY 0x01 +#define PCI_IRQ_INTX 0x01 #define PCI_IRQ_MSI 0x02 #define PCI_IRQ_MSIX 0x04 +#define PCI_IRQ_ALL_TYPES (PCI_IRQ_MSIX|PCI_IRQ_MSI|PCI_IRQ_INTX) + +#if defined(LINUXKPI_VERSION) && (LINUXKPI_VERSION <= 61000) +#define PCI_IRQ_LEGACY PCI_IRQ_INTX +#endif struct pci_dev; @@ -206,6 +269,7 @@ struct pci_driver { struct device_driver driver; const struct pci_error_handlers *err_handler; bool isdrm; + int bsd_probe_return; int (*bsd_iov_init)(device_t dev, uint16_t num_vfs, const nvlist_t *pf_config); void (*bsd_iov_uninit)(device_t dev); @@ -215,6 +279,7 @@ struct pci_driver { struct pci_bus { struct pci_dev *self; + /* struct pci_bus *parent */ int domain; int number; }; @@ -225,29 +290,34 @@ extern spinlock_t pci_lock; #define __devexit_p(x) x -#define module_pci_driver(_driver) \ - \ -static inline int \ -_pci_init(void) \ -{ \ - \ - return (linux_pci_register_driver(&_driver)); \ -} \ - \ -static inline void \ -_pci_exit(void) \ -{ \ - \ - linux_pci_unregister_driver(&_driver); \ -} \ - \ -module_init(_pci_init); \ -module_exit(_pci_exit) +#define module_pci_driver(_drv) \ + module_driver(_drv, linux_pci_register_driver, linux_pci_unregister_driver) + +struct msi_msg { + uint32_t data; +}; + +struct pci_msi_desc { + struct { + bool is_64; + } msi_attrib; +}; + +struct msi_desc { + struct msi_msg msg; + struct pci_msi_desc pci; +}; + +struct msix_entry { + int entry; + int vector; +}; /* * If we find drivers accessing this from multiple KPIs we may have to * refcount objects of this structure. */ +struct resource; struct pci_mmio_region { TAILQ_ENTRY(pci_mmio_region) next; struct resource *res; @@ -261,6 +331,7 @@ struct pci_dev { struct pci_driver *pdrv; struct pci_bus *bus; struct pci_dev *root; + pci_power_t current_state; uint16_t device; uint16_t vendor; uint16_t subsystem_vendor; @@ -269,32 +340,67 @@ struct pci_dev { unsigned int devfn; uint32_t class; uint8_t revision; + uint8_t msi_cap; + uint8_t msix_cap; bool managed; /* devres "pcim_*(). */ bool want_iomap_res; bool msi_enabled; bool msix_enabled; phys_addr_t rom; size_t romlen; + struct msi_desc **msi_desc; + char *path_name; + spinlock_t pcie_cap_lock; TAILQ_HEAD(, pci_mmio_region) mmio; }; -/* We need some meta-struct to keep track of these for devres. */ -struct pci_devres { - bool enable_io; - /* PCIR_MAX_BAR_0 + 1 = 6 => BIT(0..5). */ - uint8_t region_mask; - struct resource *region_table[PCIR_MAX_BAR_0 + 1]; /* Not needed. */ -}; -struct pcim_iomap_devres { - void *mmio_table[PCIR_MAX_BAR_0 + 1]; - struct resource *res_table[PCIR_MAX_BAR_0 + 1]; -}; +int pci_alloc_irq_vectors(struct pci_dev *pdev, int minv, int maxv, + unsigned int flags); +bool pci_device_is_present(struct pci_dev *pdev); + +int linuxkpi_pcim_enable_device(struct pci_dev *pdev); +void __iomem **linuxkpi_pcim_iomap_table(struct pci_dev *pdev); +void *linuxkpi_pci_iomap_range(struct pci_dev *, int, + unsigned long, unsigned long); +void *linuxkpi_pci_iomap(struct pci_dev *, int, unsigned long); +void *linuxkpi_pcim_iomap(struct pci_dev *, int, unsigned long); +void linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res); +int linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, + const char *name); +int linuxkpi_pci_request_region(struct pci_dev *, int, const char *); +int linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name); +int linuxkpi_pcim_request_all_regions(struct pci_dev *, const char *); +void linuxkpi_pci_release_region(struct pci_dev *pdev, int bar); +void linuxkpi_pci_release_regions(struct pci_dev *pdev); +int linuxkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, + int nreq); /* Internal helper function(s). */ struct pci_dev *lkpinew_pci_dev(device_t); void lkpi_pci_devres_release(struct device *, void *); -void lkpi_pcim_iomap_table_release(struct device *, void *); +struct pci_dev *lkpi_pci_get_device(uint32_t, uint32_t, struct pci_dev *); +struct msi_desc *lkpi_pci_msi_desc_alloc(int); +struct device *lkpi_pci_find_irq_dev(unsigned int irq); +int _lkpi_pci_enable_msi_range(struct pci_dev *pdev, int minvec, int maxvec); + +#define pci_err(pdev, fmt, ...) \ + dev_err(&(pdev)->dev, fmt, ##__VA_ARGS__) +#define pci_info(pdev, fmt, ...) \ + dev_info(&(pdev)->dev, fmt, ##__VA_ARGS__) + +static inline bool +dev_is_pci(struct device *dev) +{ + + return (device_get_devclass(dev->bsddev) == devclass_find("pci")); +} + +static inline uint16_t +pci_dev_id(struct pci_dev *pdev) +{ + return (PCI_DEVID(pdev->bus->number, pdev->devfn)); +} static inline int pci_resource_type(struct pci_dev *pdev, int bar) @@ -311,56 +417,6 @@ pci_resource_type(struct pci_dev *pdev, int bar) return (SYS_RES_MEMORY); } -struct resource_list_entry *linux_pci_reserve_bar(struct pci_dev *pdev, - struct resource_list *rl, int type, int rid); - -static inline struct resource_list_entry * -linux_pci_get_rle(struct pci_dev *pdev, int type, int rid, bool reserve_bar) -{ - struct pci_devinfo *dinfo; - struct resource_list *rl; - struct resource_list_entry *rle; - - dinfo = device_get_ivars(pdev->dev.bsddev); - rl = &dinfo->resources; - rle = resource_list_find(rl, type, rid); - /* Reserve resources for this BAR if needed. */ - if (rle == NULL && reserve_bar) - rle = linux_pci_reserve_bar(pdev, rl, type, rid); - return (rle); -} - -static inline struct resource_list_entry * -linux_pci_get_bar(struct pci_dev *pdev, int bar, bool reserve) -{ - int type; - - type = pci_resource_type(pdev, bar); - if (type < 0) - return (NULL); - bar = PCIR_BAR(bar); - return (linux_pci_get_rle(pdev, type, bar, reserve)); -} - -static inline struct device * -linux_pci_find_irq_dev(unsigned int irq) -{ - struct pci_dev *pdev; - struct device *found; - - found = NULL; - spin_lock(&pci_lock); - list_for_each_entry(pdev, &pci_devices, links) { - if (irq == pdev->dev.irq || - (irq >= pdev->dev.irq_start && irq < pdev->dev.irq_end)) { - found = &pdev->dev; - break; - } - } - spin_unlock(&pci_lock); - return (found); -} - /* * All drivers just seem to want to inspect the type not flags. */ @@ -378,8 +434,7 @@ pci_resource_flags(struct pci_dev *pdev, int bar) static inline const char * pci_name(struct pci_dev *d) { - - return device_get_desc(d->dev.bsddev); + return d->path_name; } static inline void * @@ -453,132 +508,71 @@ pci_clear_master(struct pci_dev *pdev) return (0); } -static inline struct pci_devres * -lkpi_pci_devres_get_alloc(struct pci_dev *pdev) -{ - struct pci_devres *dr; - - dr = lkpi_devres_find(&pdev->dev, lkpi_pci_devres_release, NULL, NULL); - if (dr == NULL) { - dr = lkpi_devres_alloc(lkpi_pci_devres_release, sizeof(*dr), - GFP_KERNEL | __GFP_ZERO); - if (dr != NULL) - lkpi_devres_add(&pdev->dev, dr); - } - - return (dr); -} -static inline struct pci_devres * -lkpi_pci_devres_find(struct pci_dev *pdev) -{ - - if (!pdev->managed) - return (NULL); - - return (lkpi_pci_devres_get_alloc(pdev)); -} - -static inline int -pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) +static inline bool +pci_is_root_bus(struct pci_bus *pbus) { - struct resource *res; - struct pci_devres *dr; - struct pci_mmio_region *mmio; - int rid; - int type; - type = pci_resource_type(pdev, bar); - if (type < 0) - return (-ENODEV); - rid = PCIR_BAR(bar); - res = bus_alloc_resource_any(pdev->dev.bsddev, type, &rid, - RF_ACTIVE|RF_SHAREABLE); - if (res == NULL) { - device_printf(pdev->dev.bsddev, "%s: failed to alloc " - "bar %d type %d rid %d\n", - __func__, bar, type, PCIR_BAR(bar)); - return (-ENODEV); - } - - /* - * It seems there is an implicit devres tracking on these if the device - * is managed; otherwise the resources are not automatiaclly freed on - * FreeBSD/LinuxKPI tough they should be/are expected to be by Linux - * drivers. - */ - dr = lkpi_pci_devres_find(pdev); - if (dr != NULL) { - dr->region_mask |= (1 << bar); - dr->region_table[bar] = res; - } - - /* Even if the device is not managed we need to track it for iomap. */ - mmio = malloc(sizeof(*mmio), M_DEVBUF, M_WAITOK | M_ZERO); - mmio->rid = PCIR_BAR(bar); - mmio->type = type; - mmio->res = res; - TAILQ_INSERT_TAIL(&pdev->mmio, mmio, next); - - return (0); + return (pbus->self == NULL); } -static inline void -pci_release_region(struct pci_dev *pdev, int bar) +static inline struct pci_dev * +pci_upstream_bridge(struct pci_dev *pdev) { - struct resource_list_entry *rle; - struct pci_devres *dr; - struct pci_mmio_region *mmio, *p; - if ((rle = linux_pci_get_bar(pdev, bar, false)) == NULL) - return; + if (pci_is_root_bus(pdev->bus)) + return (NULL); /* - * As we implicitly track the requests we also need to clear them on - * release. Do clear before resource release. + * If we do not have a (proper) "upstream bridge" set, e.g., we point + * to ourselves, try to handle this case on the fly like we do + * for pcie_find_root_port(). */ - dr = lkpi_pci_devres_find(pdev); - if (dr != NULL) { - KASSERT(dr->region_table[bar] == rle->res, ("%s: pdev %p bar %d" - " region_table res %p != rel->res %p\n", __func__, pdev, - bar, dr->region_table[bar], rle->res)); - dr->region_table[bar] = NULL; - dr->region_mask &= ~(1 << bar); + if (pdev == pdev->bus->self) { + device_t bridge; + + /* + * In the case of DRM drivers, the passed device is a child of + * `vgapci`. We want to start the lookup from `vgapci`, so the + * parent of the passed `drmn`. + * + * We can use the `isdrm` flag to determine this. + */ + bridge = pdev->dev.bsddev; + if (pdev->pdrv != NULL && pdev->pdrv->isdrm) + bridge = device_get_parent(bridge); + if (bridge == NULL) + goto done; + + bridge = device_get_parent(bridge); + if (bridge == NULL) + goto done; + bridge = device_get_parent(bridge); + if (bridge == NULL) + goto done; + if (device_get_devclass(device_get_parent(bridge)) != + devclass_find("pci")) + goto done; + + /* + * "bridge" is a PCI-to-PCI bridge. Create a Linux pci_dev + * for it so it can be returned. + */ + pdev->bus->self = lkpinew_pci_dev(bridge); } - - TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) { - if (rle->res != (void *)rman_get_bushandle(mmio->res)) - continue; - TAILQ_REMOVE(&pdev->mmio, mmio, next); - free(mmio, M_DEVBUF); - } - - bus_release_resource(pdev->dev.bsddev, rle->type, rle->rid, rle->res); -} - -static inline void -pci_release_regions(struct pci_dev *pdev) -{ - int i; - - for (i = 0; i <= PCIR_MAX_BAR_0; i++) - pci_release_region(pdev, i); +done: + return (pdev->bus->self); } -static inline int -pci_request_regions(struct pci_dev *pdev, const char *res_name) -{ - int error; - int i; - - for (i = 0; i <= PCIR_MAX_BAR_0; i++) { - error = pci_request_region(pdev, i, res_name); - if (error && error != -ENODEV) { - pci_release_regions(pdev); - return (error); - } - } - return (0); -} +#define pci_request_region(pdev, bar, res_name) \ + linuxkpi_pci_request_region(pdev, bar, res_name) +#define pci_release_region(pdev, bar) \ + linuxkpi_pci_release_region(pdev, bar) +#define pci_request_regions(pdev, res_name) \ + linuxkpi_pci_request_regions(pdev, res_name) +#define pci_release_regions(pdev) \ + linuxkpi_pci_release_regions(pdev) +#define pcim_request_all_regions(pdev, name) \ + linuxkpi_pcim_request_all_regions(pdev, name) static inline void lkpi_pci_disable_msix(struct pci_dev *pdev) @@ -589,7 +583,7 @@ lkpi_pci_disable_msix(struct pci_dev *pdev) /* * The MSIX IRQ numbers associated with this PCI device are no * longer valid and might be re-assigned. Make sure - * linux_pci_find_irq_dev() does no longer see them by + * lkpi_pci_find_irq_dev() does no longer see them by * resetting their references to zero: */ pdev->dev.irq_start = 0; @@ -744,13 +738,10 @@ int linux_pci_register_drm_driver(struct pci_driver *pdrv); void linux_pci_unregister_driver(struct pci_driver *pdrv); void linux_pci_unregister_drm_driver(struct pci_driver *pdrv); -#define pci_register_driver(pdrv) linux_pci_register_driver(pdrv) -#define pci_unregister_driver(pdrv) linux_pci_unregister_driver(pdrv) - -struct msix_entry { - int entry; - int vector; -}; +#define pci_register_driver(pdrv) \ + linux_pci_register_driver(pdrv) +#define pci_unregister_driver(pdrv) \ + linux_pci_unregister_driver(pdrv) /* * Enable msix, positive errors indicate actual number of available @@ -759,45 +750,11 @@ struct msix_entry { * NB: define added to prevent this definition of pci_enable_msix from * clashing with the native FreeBSD version. */ -#define pci_enable_msix(...) \ - linux_pci_enable_msix(__VA_ARGS__) - -static inline int -pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nreq) -{ - struct resource_list_entry *rle; - int error; - int avail; - int i; - - avail = pci_msix_count(pdev->dev.bsddev); - if (avail < nreq) { - if (avail == 0) - return -EINVAL; - return avail; - } - avail = nreq; - if ((error = -pci_alloc_msix(pdev->dev.bsddev, &avail)) != 0) - return error; - /* - * Handle case where "pci_alloc_msix()" may allocate less - * interrupts than available and return with no error: - */ - if (avail < nreq) { - pci_release_msi(pdev->dev.bsddev); - return avail; - } - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); - pdev->dev.irq_start = rle->start; - pdev->dev.irq_end = rle->start + avail; - for (i = 0; i < nreq; i++) - entries[i].vector = pdev->dev.irq_start + i; - pdev->msix_enabled = true; - return (0); -} +#define pci_enable_msix(...) \ + linuxkpi_pci_enable_msix(__VA_ARGS__) -#define pci_enable_msix_range(...) \ - linux_pci_enable_msix_range(__VA_ARGS__) +#define pci_enable_msix_range(...) \ + linux_pci_enable_msix_range(__VA_ARGS__) static inline int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, @@ -822,66 +779,14 @@ pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, return (nvec); } -#define pci_enable_msi(pdev) \ - linux_pci_enable_msi(pdev) +#define pci_enable_msi(pdev) \ + linux_pci_enable_msi(pdev) static inline int pci_enable_msi(struct pci_dev *pdev) { - struct resource_list_entry *rle; - int error; - int avail; - - avail = pci_msi_count(pdev->dev.bsddev); - if (avail < 1) - return -EINVAL; - - avail = 1; /* this function only enable one MSI IRQ */ - if ((error = -pci_alloc_msi(pdev->dev.bsddev, &avail)) != 0) - return error; - - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); - pdev->dev.irq_start = rle->start; - pdev->dev.irq_end = rle->start + avail; - pdev->irq = rle->start; - pdev->msi_enabled = true; - return (0); -} - -static inline int -pci_alloc_irq_vectors(struct pci_dev *pdev, int minv, int maxv, - unsigned int flags) -{ - int error; - - if (flags & PCI_IRQ_MSIX) { - struct msix_entry *entries; - int i; - - entries = kcalloc(maxv, sizeof(*entries), GFP_KERNEL); - if (entries == NULL) { - error = -ENOMEM; - goto out; - } - for (i = 0; i < maxv; ++i) - entries[i].entry = i; - error = pci_enable_msix(pdev, entries, maxv); -out: - kfree(entries); - if (error == 0 && pdev->msix_enabled) - return (pdev->dev.irq_end - pdev->dev.irq_start); - } - if (flags & PCI_IRQ_MSI) { - error = pci_enable_msi(pdev); - if (error == 0 && pdev->msi_enabled) - return (pdev->dev.irq_end - pdev->dev.irq_start); - } - if (flags & PCI_IRQ_LEGACY) { - if (pdev->irq) - return (1); - } - return (-EINVAL); + return (_lkpi_pci_enable_msi_range(pdev, 1, 1)); } static inline int @@ -895,79 +800,19 @@ static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) { return -ENODEV; } -static inline void pci_disable_sriov(struct pci_dev *dev) -{ -} - -static inline struct resource * -_lkpi_pci_iomap(struct pci_dev *pdev, int bar, int mmio_size __unused) -{ - struct pci_mmio_region *mmio, *p; - int type; - - type = pci_resource_type(pdev, bar); - if (type < 0) { - device_printf(pdev->dev.bsddev, "%s: bar %d type %d\n", - __func__, bar, type); - return (NULL); - } - - /* - * Check for duplicate mappings. - * This can happen if a driver calls pci_request_region() first. - */ - TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) { - if (mmio->type == type && mmio->rid == PCIR_BAR(bar)) { - return (mmio->res); - } - } - - mmio = malloc(sizeof(*mmio), M_DEVBUF, M_WAITOK | M_ZERO); - mmio->rid = PCIR_BAR(bar); - mmio->type = type; - mmio->res = bus_alloc_resource_any(pdev->dev.bsddev, mmio->type, - &mmio->rid, RF_ACTIVE|RF_SHAREABLE); - if (mmio->res == NULL) { - device_printf(pdev->dev.bsddev, "%s: failed to alloc " - "bar %d type %d rid %d\n", - __func__, bar, type, PCIR_BAR(bar)); - free(mmio, M_DEVBUF); - return (NULL); - } - TAILQ_INSERT_TAIL(&pdev->mmio, mmio, next); - return (mmio->res); -} - -static inline void * -pci_iomap(struct pci_dev *pdev, int mmio_bar, int mmio_size) +static inline void pci_disable_sriov(struct pci_dev *dev) { - struct resource *res; - - res = _lkpi_pci_iomap(pdev, mmio_bar, mmio_size); - if (res == NULL) - return (NULL); - /* This is a FreeBSD extension so we can use bus_*(). */ - if (pdev->want_iomap_res) - return (res); - return ((void *)rman_get_bushandle(res)); } -static inline void -pci_iounmap(struct pci_dev *pdev, void *res) -{ - struct pci_mmio_region *mmio, *p; - - TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) { - if (res != (void *)rman_get_bushandle(mmio->res)) - continue; - bus_release_resource(pdev->dev.bsddev, - mmio->type, mmio->rid, mmio->res); - TAILQ_REMOVE(&pdev->mmio, mmio, next); - free(mmio, M_DEVBUF); - return; - } -} +#define pci_iomap_range(pdev, mmio_bar, mmio_off, mmio_size) \ + linuxkpi_pci_iomap_range(pdev, mmio_bar, mmio_off, mmio_size) +#define pci_iomap(pdev, mmio_bar, mmio_size) \ + linuxkpi_pci_iomap(pdev, mmio_bar, mmio_size) +#define pcim_iomap(pdev, bar, maxlen) \ + linuxkpi_pcim_iomap(pdev, bar, maxlen) +#define pci_iounmap(pdev, res) \ + linuxkpi_pci_iounmap(pdev, res) static inline void lkpi_pci_save_state(struct pci_dev *pdev) @@ -986,6 +831,26 @@ lkpi_pci_restore_state(struct pci_dev *pdev) #define pci_save_state(dev) lkpi_pci_save_state(dev) #define pci_restore_state(dev) lkpi_pci_restore_state(dev) +static inline int +linuxkpi_pci_enable_wake(struct pci_dev *pdev, pci_power_t state, bool ena) +{ + /* + * We do not currently support this in device.h either to + * check if the device is allowed to wake up in first place. + */ + pr_debug("%s: TODO\n", __func__); + return (0); +} +#define pci_enable_wake(dev, state, ena) \ + linuxkpi_pci_enable_wake(dev, state, ena) + +static inline int +pci_reset_function(struct pci_dev *pdev) +{ + + return (-ENOSYS); +} + #define DEFINE_PCI_DEVICE_TABLE(_table) \ const struct pci_device_id _table[] __devinitdata @@ -1170,6 +1035,7 @@ static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) static inline int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *dst) { + *dst = 0; if (pos & 3) return -EINVAL; @@ -1182,6 +1048,7 @@ pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *dst) static inline int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *dst) { + *dst = 0; if (pos & 3) return -EINVAL; @@ -1203,6 +1070,41 @@ pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); } +static inline int +pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, + uint16_t clear, uint16_t set) +{ + int error; + uint16_t v; + + if (pos == PCI_EXP_LNKCTL || pos == PCI_EXP_RTCTL) + spin_lock(&dev->pcie_cap_lock); + + error = pcie_capability_read_word(dev, pos, &v); + if (error == 0) { + v &= ~clear; + v |= set; + error = pcie_capability_write_word(dev, pos, v); + } + + if (pos == PCI_EXP_LNKCTL || pos == PCI_EXP_RTCTL) + spin_unlock(&dev->pcie_cap_lock); + + return (error); +} + +static inline int +pcie_capability_set_word(struct pci_dev *dev, int pos, uint16_t val) +{ + return (pcie_capability_clear_and_set_word(dev, pos, 0, val)); +} + +static inline int +pcie_capability_clear_word(struct pci_dev *dev, int pos, uint16_t val) +{ + return (pcie_capability_clear_and_set_word(dev, pos, val, 0)); +} + static inline int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed, enum pcie_link_width *width) { @@ -1252,6 +1154,10 @@ pcie_get_speed_cap(struct pci_dev *dev) return (PCIE_SPEED_8_0GT); if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB) return (PCIE_SPEED_16_0GT); + if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_32_0GB) + return (PCIE_SPEED_32_0GT); + if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_64_0GB) + return (PCIE_SPEED_64_0GT); } else { /* pre-r3.0 */ lnkcap = pci_read_config(root, pos + PCIER_LINK_CAP, 4); if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB) @@ -1262,6 +1168,10 @@ pcie_get_speed_cap(struct pci_dev *dev) return (PCIE_SPEED_8_0GT); if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB) return (PCIE_SPEED_16_0GT); + if (lnkcap & PCI_EXP_LNKCAP_SLS_32_0GB) + return (PCIE_SPEED_32_0GT); + if (lnkcap & PCI_EXP_LNKCAP_SLS_64_0GB) + return (PCIE_SPEED_64_0GT); } return (PCI_SPEED_UNKNOWN); } @@ -1289,6 +1199,10 @@ PCIE_SPEED2MBS_ENC(enum pci_bus_speed spd) { switch(spd) { + case PCIE_SPEED_64_0GT: + return (64000 * 128 / 130); + case PCIE_SPEED_32_0GT: + return (32000 * 128 / 130); case PCIE_SPEED_16_0GT: return (16000 * 128 / 130); case PCIE_SPEED_8_0GT: @@ -1319,6 +1233,12 @@ pcie_bandwidth_available(struct pci_dev *pdev, return (nwidth * PCIE_SPEED2MBS_ENC(nspeed)); } +static inline bool +pcie_aspm_enabled(struct pci_dev *pdev) +{ + return (false); +} + static inline struct pci_dev * pcie_find_root_port(struct pci_dev *pdev) { @@ -1351,6 +1271,29 @@ pci_stop_and_remove_bus_device(struct pci_dev *pdev) { } +static inline int +pci_rescan_bus(struct pci_bus *pbus) +{ + device_t *devlist, parent; + int devcount, error; + + if (!device_is_attached(pbus->self->dev.bsddev)) + return (0); + /* pci_rescan_method() will work on the pcib (parent). */ + error = BUS_RESCAN(pbus->self->dev.bsddev); + if (error != 0) + return (0); + + parent = device_get_parent(pbus->self->dev.bsddev); + error = device_get_children(parent, &devlist, &devcount); + if (error != 0) + return (0); + if (devcount != 0) + free(devlist, M_TEMP); + + return (devcount); +} + /* * The following functions can be used to attach/detach the LinuxKPI's * PCI device runtime. The pci_driver and pci_device_id pointer is @@ -1374,11 +1317,27 @@ pci_dev_present(const struct pci_device_id *cur) return (0); } -static inline bool -pci_is_root_bus(struct pci_bus *pbus) +static inline const struct pci_device_id * +pci_match_id(const struct pci_device_id *ids, struct pci_dev *pdev) { + if (ids == NULL) + return (NULL); - return (pbus->self == NULL); + for (; + ids->vendor != 0 || ids->subvendor != 0 || ids->class_mask != 0; + ids++) + if ((ids->vendor == PCI_ANY_ID || + ids->vendor == pdev->vendor) && + (ids->device == PCI_ANY_ID || + ids->device == pdev->device) && + (ids->subvendor == PCI_ANY_ID || + ids->subvendor == pdev->subsystem_vendor) && + (ids->subdevice == PCI_ANY_ID || + ids->subdevice == pdev->subsystem_device) && + ((ids->class ^ pdev->class) & ids->class_mask) == 0) + return (ids); + + return (NULL); } struct pci_dev *lkpi_pci_get_domain_bus_and_slot(int domain, @@ -1386,6 +1345,12 @@ struct pci_dev *lkpi_pci_get_domain_bus_and_slot(int domain, #define pci_get_domain_bus_and_slot(domain, bus, devfn) \ lkpi_pci_get_domain_bus_and_slot(domain, bus, devfn) +struct pci_dev *lkpi_pci_get_slot(struct pci_bus *, unsigned int); +#ifndef WANT_NATIVE_PCI_GET_SLOT +#define pci_get_slot(_pbus, _devfn) \ + lkpi_pci_get_slot(_pbus, _devfn) +#endif + static inline int pci_domain_nr(struct pci_bus *pbus) { @@ -1449,140 +1414,162 @@ pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, int pos, struct pci_dev *lkpi_pci_get_class(unsigned int class, struct pci_dev *from); #define pci_get_class(class, from) lkpi_pci_get_class(class, from) +struct pci_dev *lkpi_pci_get_base_class(unsigned int class, + struct pci_dev *from); +#define pci_get_base_class(class, from) lkpi_pci_get_base_class(class, from) /* -------------------------------------------------------------------------- */ +#define pcim_enable_device(pdev) \ + linuxkpi_pcim_enable_device(pdev) +#define pcim_iomap_table(pdev) \ + linuxkpi_pcim_iomap_table(pdev) +#define pcim_iomap_regions(pdev, mask, name) \ + linuxkpi_pcim_iomap_regions(pdev, mask, name) + static inline int -pcim_enable_device(struct pci_dev *pdev) +pcim_iomap_regions_request_all(struct pci_dev *pdev, uint32_t mask, char *name) { - struct pci_devres *dr; - int error; + uint32_t requests, req_mask; + int bar, error; - /* Here we cannot run through the pdev->managed check. */ - dr = lkpi_pci_devres_get_alloc(pdev); - if (dr == NULL) - return (-ENOMEM); + /* Request all the BARs ("regions") we do not iomap. */ + req_mask = ((1 << (PCIR_MAX_BAR_0 + 1)) - 1) & ~mask; + for (bar = requests = 0; requests != req_mask; bar++) { + if ((req_mask & (1 << bar)) == 0) + continue; + error = pci_request_region(pdev, bar, name); + if (error != 0 && error != -ENODEV) + goto err; + requests |= (1 << bar); + } - /* If resources were enabled before do not do it again. */ - if (dr->enable_io) - return (0); + error = pcim_iomap_regions(pdev, mask, name); + if (error != 0) + goto err; - error = pci_enable_device(pdev); - if (error == 0) - dr->enable_io = true; + return (0); - /* This device is not managed. */ - pdev->managed = true; +err: + for (bar = PCIR_MAX_BAR_0; bar >= 0; bar--) { + if ((requests & (1 << bar)) != 0) + pci_release_region(pdev, bar); + } - return (error); + return (-EINVAL); } -static inline struct pcim_iomap_devres * -lkpi_pcim_iomap_devres_find(struct pci_dev *pdev) +/* + * We cannot simply re-define pci_get_device() as we would normally do + * and then hide it in linux_pci.c as too many semi-native drivers still + * include linux/pci.h and run into the conflict with native PCI. Linux drivers + * using pci_get_device() need to be changed to call linuxkpi_pci_get_device(). + */ +static inline struct pci_dev * +linuxkpi_pci_get_device(uint32_t vendor, uint32_t device, struct pci_dev *odev) { - struct pcim_iomap_devres *dr; - dr = lkpi_devres_find(&pdev->dev, lkpi_pcim_iomap_table_release, - NULL, NULL); - if (dr == NULL) { - dr = lkpi_devres_alloc(lkpi_pcim_iomap_table_release, - sizeof(*dr), GFP_KERNEL | __GFP_ZERO); - if (dr != NULL) - lkpi_devres_add(&pdev->dev, dr); - } + return (lkpi_pci_get_device(vendor, device, odev)); +} - if (dr == NULL) - device_printf(pdev->dev.bsddev, "%s: NULL\n", __func__); +#define for_each_pci_dev(_pdev) \ + while ((_pdev = linuxkpi_pci_get_device(PCI_ANY_ID, PCI_ANY_ID, _pdev)) != NULL) - return (dr); +/* This is a FreeBSD extension so we can use bus_*(). */ +static inline void +linuxkpi_pcim_want_to_use_bus_functions(struct pci_dev *pdev) +{ + pdev->want_iomap_res = true; } -static inline void __iomem ** -pcim_iomap_table(struct pci_dev *pdev) +static inline bool +pci_is_thunderbolt_attached(struct pci_dev *pdev) { - struct pcim_iomap_devres *dr; - dr = lkpi_pcim_iomap_devres_find(pdev); - if (dr == NULL) - return (NULL); + return (false); +} - /* - * If the driver has manually set a flag to be able to request the - * resource to use bus_read/write_<n>, return the shadow table. - */ - if (pdev->want_iomap_res) - return ((void **)dr->res_table); +static inline void * +pci_platform_rom(struct pci_dev *pdev, size_t *size) +{ + + return (NULL); +} + +static inline void +pci_ignore_hotplug(struct pci_dev *pdev) +{ +} - /* This is the Linux default. */ - return (dr->mmio_table); +static inline const char * +pci_power_name(pci_power_t state) +{ + int pstate = state + 1; + + if (pstate >= 0 && pstate < nitems(pci_power_names)) + return (pci_power_names[pstate]); + else + return (pci_power_names[0]); } static inline int -pcim_iomap_regions_request_all(struct pci_dev *pdev, uint32_t mask, char *name) +pcie_get_readrq(struct pci_dev *dev) { - struct pcim_iomap_devres *dr; - void *res; - uint32_t mappings, requests, req_mask; - int bar, error; + u16 ctl; - dr = lkpi_pcim_iomap_devres_find(pdev); - if (dr == NULL) - return (-ENOMEM); + if (pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl)) + return (-EINVAL); - /* Request all the BARs ("regions") we do not iomap. */ - req_mask = ((1 << (PCIR_MAX_BAR_0 + 1)) - 1) & ~mask; - for (bar = requests = 0; requests != req_mask; bar++) { - if ((req_mask & (1 << bar)) == 0) - continue; - error = pci_request_region(pdev, bar, name); - if (error != 0 && error != -ENODEV) - goto err; - requests |= (1 << bar); - } + return (128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12)); +} - /* Now iomap all the requested (by "mask") ones. */ - for (bar = mappings = 0; mappings != mask; bar++) { - if ((mask & (1 << bar)) == 0) - continue; +static inline bool +pci_is_enabled(struct pci_dev *pdev) +{ - /* Request double is not allowed. */ - if (dr->mmio_table[bar] != NULL) { - device_printf(pdev->dev.bsddev, "%s: bar %d %p\n", - __func__, bar, dr->mmio_table[bar]); - goto err; - } + return ((pci_read_config(pdev->dev.bsddev, PCIR_COMMAND, 2) & + PCIM_CMD_BUSMASTEREN) != 0); +} - res = _lkpi_pci_iomap(pdev, bar, 0); - if (res == NULL) - goto err; - dr->mmio_table[bar] = (void *)rman_get_bushandle(res); - dr->res_table[bar] = res; +static inline int +pci_wait_for_pending_transaction(struct pci_dev *pdev) +{ - mappings |= (1 << bar); - } + return (0); +} + +static inline int +pci_assign_resource(struct pci_dev *pdev, int bar) +{ return (0); +} -err: - for (bar = PCIR_MAX_BAR_0; bar >= 0; bar--) { - if ((mappings & (1 << bar)) != 0) { - res = dr->mmio_table[bar]; - if (res == NULL) - continue; - pci_iounmap(pdev, res); - } else if ((requests & (1 << bar)) != 0) { - pci_release_region(pdev, bar); - } +static inline int +pci_irq_vector(struct pci_dev *pdev, unsigned int vector) +{ + + if (!pdev->msix_enabled && !pdev->msi_enabled) { + if (vector != 0) + return (-EINVAL); + return (pdev->irq); } - return (-EINVAL); + if (pdev->msix_enabled || pdev->msi_enabled) { + if ((pdev->dev.irq_start + vector) >= pdev->dev.irq_end) + return (-EINVAL); + return (pdev->dev.irq_start + vector); + } + + return (-ENXIO); } -/* This is a FreeBSD extension so we can use bus_*(). */ -static inline void -linuxkpi_pcim_want_to_use_bus_functions(struct pci_dev *pdev) +static inline int +pci_wake_from_d3(struct pci_dev *pdev, bool enable) { - pdev->want_iomap_res = true; + + pr_debug("%s: TODO\n", __func__); + return (0); } -#endif /* _LINUX_PCI_H_ */ +#endif /* _LINUXKPI_LINUX_PCI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pci_ids.h b/sys/compat/linuxkpi/common/include/linux/pci_ids.h index 519d1b6eb663..e318f6f75ce7 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci_ids.h +++ b/sys/compat/linuxkpi/common/include/linux/pci_ids.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PCI_IDS_H @@ -41,23 +39,31 @@ #define PCI_BASE_CLASS_BRIDGE 0x06 #define PCI_CLASS_BRIDGE_ISA 0x0601 +#define PCI_CLASS_ACCELERATOR_PROCESSING 0x1200 + /* XXX We should really generate these and use them throughout the tree. */ #define PCI_VENDOR_ID_APPLE 0x106b #define PCI_VENDOR_ID_ASUSTEK 0x1043 +#define PCI_VENDOR_ID_ASMEDIA 0x1b21 +#define PCI_VENDOR_ID_ATHEROS 0x168c #define PCI_VENDOR_ID_ATI 0x1002 #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_VENDOR_ID_DELL 0x1028 #define PCI_VENDOR_ID_HP 0x103c #define PCI_VENDOR_ID_IBM 0x1014 #define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_VENDOR_ID_ITTIM 0x0b48 +#define PCI_VENDOR_ID_MEDIATEK 0x14c3 #define PCI_VENDOR_ID_MELLANOX 0x15b3 +#define PCI_VENDOR_ID_QCOM 0x17cb #define PCI_VENDOR_ID_REALTEK 0x10ec #define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 #define PCI_VENDOR_ID_SERVERWORKS 0x1166 #define PCI_VENDOR_ID_SONY 0x104d #define PCI_VENDOR_ID_TOPSPIN 0x1867 +#define PCI_VENDOR_ID_UBIQUITI 0x0777 #define PCI_VENDOR_ID_VIA 0x1106 #define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4 #define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 diff --git a/sys/compat/linuxkpi/common/include/linux/perf_event.h b/sys/compat/linuxkpi/common/include/linux/perf_event.h new file mode 100644 index 000000000000..86b0d06cdc1f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/perf_event.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PERF_EVENT_H_ +#define _LINUXKPI_LINUX_PERF_EVENT_H_ + +#include <linux/cgroup.h> + +#endif /* _LINUXKPI_LINUX_PERF_EVENT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pfn.h b/sys/compat/linuxkpi/common/include/linux/pfn.h index 162ca102c951..26d47b9bc3b1 100644 --- a/sys/compat/linuxkpi/common/include/linux/pfn.h +++ b/sys/compat/linuxkpi/common/include/linux/pfn.h @@ -22,12 +22,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PFN_H_ -#define _LINUX_PFN_H_ +#ifndef _LINUXKPI_LINUX_PFN_H_ +#define _LINUXKPI_LINUX_PFN_H_ #include <linux/types.h> @@ -41,4 +39,4 @@ typedef struct { #define PFN_PHYS(x) ((phys_addr_t)(x) << PAGE_SHIFT) #define PHYS_PFN(x) ((unsigned long)((x) >> PAGE_SHIFT)) -#endif /* _LINUX_PFN_H_ */ +#endif /* _LINUXKPI_LINUX_PFN_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pfn_t.h b/sys/compat/linuxkpi/common/include/linux/pfn_t.h index bfa80b14ae94..f22289802cb8 100644 --- a/sys/compat/linuxkpi/common/include/linux/pfn_t.h +++ b/sys/compat/linuxkpi/common/include/linux/pfn_t.h @@ -22,12 +22,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PFN_T_H_ -#define _LINUX_PFN_T_H_ +#ifndef _LINUXKPI_LINUX_PFN_T_H_ +#define _LINUXKPI_LINUX_PFN_T_H_ #include <linux/mm.h> @@ -53,4 +51,4 @@ pfn_to_pfn_t(unsigned long pfn) return (__pfn_to_pfn_t (pfn, 0)); } -#endif /* _LINUX_PFN_T_H_ */ +#endif /* _LINUXKPI_LINUX_PFN_T_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pid.h b/sys/compat/linuxkpi/common/include/linux/pid.h index 73d8f1f6edfe..60cb9f725b21 100644 --- a/sys/compat/linuxkpi/common/include/linux/pid.h +++ b/sys/compat/linuxkpi/common/include/linux/pid.h @@ -22,12 +22,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PID_H_ -#define _LINUX_PID_H_ +#ifndef _LINUXKPI_LINUX_PID_H_ +#define _LINUXKPI_LINUX_PID_H_ #include <sys/param.h> #include <sys/systm.h> @@ -67,4 +65,4 @@ struct task_struct; extern struct task_struct *linux_pid_task(pid_t); extern struct task_struct *linux_get_pid_task(pid_t); -#endif /* _LINUX_PID_H_ */ +#endif /* _LINUXKPI_LINUX_PID_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/platform_device.h b/sys/compat/linuxkpi/common/include/linux/platform_device.h new file mode 100644 index 000000000000..dba79f5936cc --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/platform_device.h @@ -0,0 +1,97 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020-2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PLATFORM_DEVICE_H +#define _LINUXKPI_LINUX_PLATFORM_DEVICE_H + +#include <linux/kernel.h> +#include <linux/device.h> + +struct platform_device { + const char *name; + int id; + bool id_auto; + struct device dev; +}; + +struct platform_driver { + void (*remove)(struct platform_device *); + struct device_driver driver; +}; + +#define dev_is_platform(dev) (false) +#define to_platform_device(dev) (NULL) + +static __inline int +platform_driver_register(struct platform_driver *pdrv) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENXIO); +} + +static __inline void * +dev_get_platdata(struct device *dev) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static __inline int +platform_driver_probe(struct platform_driver *pdrv, + int(*pd_probe_f)(struct platform_device *)) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENODEV); +} + +static __inline void +platform_driver_unregister(struct platform_driver *pdrv) +{ + + pr_debug("%s: TODO\n", __func__); + return; +} + +static __inline int +platform_device_register(struct platform_device *pdev) +{ + pr_debug("%s: TODO\n", __func__); + return (0); +} + +static __inline void +platform_device_unregister(struct platform_device *pdev) +{ + + pr_debug("%s: TODO\n", __func__); + return; +} + +#endif /* _LINUXKPI_LINUX_PLATFORM_DEVICE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pm.h b/sys/compat/linuxkpi/common/include/linux/pm.h index 6b8a7e768a8c..c8d943027909 100644 --- a/sys/compat/linuxkpi/common/include/linux/pm.h +++ b/sys/compat/linuxkpi/common/include/linux/pm.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,27 +26,75 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PM_H #define _LINUXKPI_LINUX_PM_H +#include <linux/kernel.h> /* pr_debug */ +#include <asm/atomic.h> + +/* Needed but breaks linux_usb.c */ +/* #include <linux/completion.h> */ +/* #include <linux/wait.h> */ + +struct device; + +typedef struct pm_message { + int event; +} pm_message_t; + +struct dev_pm_domain { +}; + +struct dev_pm_info { + atomic_t usage_count; +}; + +#define PM_EVENT_FREEZE 0x0001 +#define PM_EVENT_SUSPEND 0x0002 + +#define pm_sleep_ptr(_p) \ + IS_ENABLED(CONFIG_PM_SLEEP) ? (_p) : NULL + #ifdef CONFIG_PM_SLEEP +#define __SET_PM_OPS(_suspendfunc, _resumefunc) \ + .suspend = _suspendfunc, \ + .resume = _resumefunc, \ + .freeze = _suspendfunc, \ + .thaw = _resumefunc, \ + .poweroff = _suspendfunc, \ + .restore = _resumefunc, \ + #define SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ const struct dev_pm_ops _name = { \ - .suspend = _suspendfunc, \ - .resume = _resumefunc, \ - .freeze = _suspendfunc, \ - .thaw = _resumefunc, \ - .poweroff = _suspendfunc, \ - .restore = _resumefunc, \ + __SET_PM_OPS(_suspendfunc, _resumefunc) \ } + +#define DEFINE_SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ +const struct dev_pm_ops _name = { \ + __SET_PM_OPS(_suspendfunc, _resumefunc) \ +} + +#define SET_SYSTEM_SLEEP_PM_OPS(_suspendfunc, _resumefunc) \ + __SET_PM_OPS(_suspendfunc, _resumefunc) #else #define SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ const struct dev_pm_ops _name = { \ } +#define DEFINE_SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ +const struct dev_pm_ops _name = { \ +} #endif +bool linuxkpi_device_can_wakeup(struct device *); +#define device_can_wakeup(_dev) linuxkpi_device_can_wakeup(_dev) + +static inline void +pm_wakeup_event(struct device *dev __unused, unsigned int x __unused) +{ + + pr_debug("%s: TODO\n", __func__); +} + #endif /* _LINUXKPI_LINUX_PM_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pm_qos.h b/sys/compat/linuxkpi/common/include/linux/pm_qos.h new file mode 100644 index 000000000000..47c41a819ba8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/pm_qos.h @@ -0,0 +1,57 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PM_QOS_H +#define _LINUXKPI_LINUX_PM_QOS_H + +#define PM_QOS_DEFAULT_VALUE (-1) + +struct pm_qos_request { +}; + +static inline void +cpu_latency_qos_add_request(struct pm_qos_request *qos, int x) +{ +} + +static inline void +cpu_latency_qos_update_request(struct pm_qos_request *qos, int x) +{ +} + +static inline void +cpu_latency_qos_remove_request(struct pm_qos_request *qos) +{ +} + +static inline bool +cpu_latency_qos_request_active(struct pm_qos_request *qos) +{ + return (false); +} + +#endif /* _LINUXKPI_LINUX_PM_QOS_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pm_runtime.h b/sys/compat/linuxkpi/common/include/linux/pm_runtime.h new file mode 100644 index 000000000000..6114b7b159d7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/pm_runtime.h @@ -0,0 +1,54 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_PM_RUNTIME_H_ +#define _LINUXKPI_LINUX_PM_RUNTIME_H_ + +#include <linux/device.h> +#include <linux/pm.h> + +#define pm_runtime_mark_last_busy(x) (void)(x) +#define pm_runtime_use_autosuspend(x) (void)(x) +#define pm_runtime_dont_use_autosuspend(x) (void)(x) +#define pm_runtime_put_autosuspend(x) (void)(x) +#define pm_runtime_set_autosuspend_delay(x, y) (void)(x); (void)(y) +#define pm_runtime_set_active(x) (void)(x) +#define pm_runtime_allow(x) (void)(x) +#define pm_runtime_put_noidle(x) (void)(x) +#define pm_runtime_forbid(x) (void)(x) +#define pm_runtime_get_noresume(x) (void)(x) +#define pm_runtime_put(x) (void)(x) +#define pm_runtime_enable(x) (void)(x) +#define pm_runtime_disable(x) (void)(x) +#define pm_runtime_autosuspend(x) (void)(x) +#define pm_runtime_resume(x) (void)(x) + +static inline int +pm_runtime_get_sync(struct device *dev) +{ + return 0; +} + +static inline int +pm_runtime_get_if_in_use(struct device *dev) +{ + return 1; +} + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION < 60900 +static inline int +pm_runtime_get_if_active(struct device *dev, bool x) +#else +static inline int +pm_runtime_get_if_active(struct device *dev) +#endif +{ + return 1; +} + +static inline int +pm_runtime_suspended(struct device *dev) +{ + return 0; +} + +#endif /* _LINUXKPI_LINUX_PM_RUNTIME_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/poison.h b/sys/compat/linuxkpi/common/include/linux/poison.h index 35ccb5b5499a..f1594c6dd1dc 100644 --- a/sys/compat/linuxkpi/common/include/linux/poison.h +++ b/sys/compat/linuxkpi/common/include/linux/poison.h @@ -1,7 +1,7 @@ /* Public domain. */ -#ifndef _LINUX_POISON_H -#define _LINUX_POISON_H +#ifndef _LINUXKPI_LINUX_POISON_H +#define _LINUXKPI_LINUX_POISON_H #define POISON_INUSE 0xdb #define POISON_FREE 0xdf diff --git a/sys/compat/linuxkpi/common/include/linux/poll.h b/sys/compat/linuxkpi/common/include/linux/poll.h index 33501165df24..3acb3c740954 100644 --- a/sys/compat/linuxkpi/common/include/linux/poll.h +++ b/sys/compat/linuxkpi/common/include/linux/poll.h @@ -25,15 +25,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_POLL_H_ -#define _LINUX_POLL_H_ +#ifndef _LINUXKPI_LINUX_POLL_H_ +#define _LINUXKPI_LINUX_POLL_H_ #include <sys/poll.h> #include <sys/fcntl.h> +#include <linux/eventpoll.h> #include <linux/wait.h> #include <linux/file.h> @@ -45,4 +44,4 @@ extern void linux_poll_wait(struct linux_file *, wait_queue_head_t *, poll_table extern void linux_poll_wakeup(struct linux_file *); -#endif /* _LINUX_POLL_H_ */ +#endif /* _LINUXKPI_LINUX_POLL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/power_supply.h b/sys/compat/linuxkpi/common/include/linux/power_supply.h index 6f6d8b28c5ee..8855cfff0539 100644 --- a/sys/compat/linuxkpi/common/include/linux/power_supply.h +++ b/sys/compat/linuxkpi/common/include/linux/power_supply.h @@ -24,12 +24,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_POWER_SUPPLY_H_ -#define _LINUX_POWER_SUPPLY_H_ +#ifndef _LINUXKPI_LINUX_POWER_SUPPLY_H_ +#define _LINUXKPI_LINUX_POWER_SUPPLY_H_ #include <sys/types.h> #include <sys/power.h> diff --git a/sys/compat/linuxkpi/common/include/linux/preempt.h b/sys/compat/linuxkpi/common/include/linux/preempt.h index e19e7ee09a48..32177d4a980c 100644 --- a/sys/compat/linuxkpi/common/include/linux/preempt.h +++ b/sys/compat/linuxkpi/common/include/linux/preempt.h @@ -22,12 +22,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PREEMPT_H_ -#define _LINUX_PREEMPT_H_ +#ifndef _LINUXKPI_LINUX_PREEMPT_H_ +#define _LINUXKPI_LINUX_PREEMPT_H_ #include <linux/hardirq.h> #include <linux/list.h> @@ -40,4 +38,4 @@ #define preempt_disable() critical_enter() #define preempt_enable() critical_exit() -#endif /* _LINUX_PREEMPT_H_ */ +#endif /* _LINUXKPI_LINUX_PREEMPT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/prefetch.h b/sys/compat/linuxkpi/common/include/linux/prefetch.h index ed8f1838e178..71839f0ca191 100644 --- a/sys/compat/linuxkpi/common/include/linux/prefetch.h +++ b/sys/compat/linuxkpi/common/include/linux/prefetch.h @@ -24,13 +24,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PREFETCH_H_ -#define _LINUX_PREFETCH_H_ +#ifndef _LINUXKPI_LINUX_PREFETCH_H_ +#define _LINUXKPI_LINUX_PREFETCH_H_ #define prefetchw(x) __builtin_prefetch(x,1) -#endif /* _LINUX_PREFETCH_H_ */ +#endif /* _LINUXKPI_LINUX_PREFETCH_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/printk.h b/sys/compat/linuxkpi/common/include/linux/printk.h index e6510e9e9834..d2d197682782 100644 --- a/sys/compat/linuxkpi/common/include/linux/printk.h +++ b/sys/compat/linuxkpi/common/include/linux/printk.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_PRINTK_H_ -#define _LINUX_PRINTK_H_ +#ifndef _LINUXKPI_LINUX_PRINTK_H_ +#define _LINUXKPI_LINUX_PRINTK_H_ #include <linux/kernel.h> @@ -46,57 +44,19 @@ enum { DUMP_PREFIX_OFFSET }; +int __lkpi_hexdump_printf(void *, const char *, ...) __printflike(2, 3); + +void lkpi_hex_dump(int(*)(void *, const char *, ...), void *arg1, + const char *, const char *, const int, const int, const int, + const void *, size_t, const bool); + static inline void print_hex_dump(const char *level, const char *prefix_str, const int prefix_type, const int rowsize, const int groupsize, const void *buf, size_t len, const bool ascii) { - typedef const struct { long long value; } __packed *print_64p_t; - typedef const struct { uint32_t value; } __packed *print_32p_t; - typedef const struct { uint16_t value; } __packed *print_16p_t; - const void *buf_old = buf; - int row; - - while (len > 0) { - if (level != NULL) - printf("%s", level); - if (prefix_str != NULL) - printf("%s ", prefix_str); - - switch (prefix_type) { - case DUMP_PREFIX_ADDRESS: - printf("[%p] ", buf); - break; - case DUMP_PREFIX_OFFSET: - printf("[%#tx] ", ((const char *)buf - - (const char *)buf_old)); - break; - default: - break; - } - for (row = 0; row != rowsize; row++) { - if (groupsize == 8 && len > 7) { - printf("%016llx ", ((print_64p_t)buf)->value); - buf = (const uint8_t *)buf + 8; - len -= 8; - } else if (groupsize == 4 && len > 3) { - printf("%08x ", ((print_32p_t)buf)->value); - buf = (const uint8_t *)buf + 4; - len -= 4; - } else if (groupsize == 2 && len > 1) { - printf("%04x ", ((print_16p_t)buf)->value); - buf = (const uint8_t *)buf + 2; - len -= 2; - } else if (len > 0) { - printf("%02x ", *(const uint8_t *)buf); - buf = (const uint8_t *)buf + 1; - len--; - } else { - break; - } - } - printf("\n"); - } + lkpi_hex_dump(__lkpi_hexdump_printf, NULL, level, prefix_str, prefix_type, + rowsize, groupsize, buf, len, ascii); } static inline void @@ -127,4 +87,17 @@ print_hex_dump_bytes(const char *prefix_str, const int prefix_type, #define pr_info_ratelimited(fmt, ...) \ printk_ratelimited(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) -#endif /* _LINUX_PRINTK_H_ */ +#define no_printk(fmt, ...) \ +({ \ + if (0) \ + printk(pr_fmt(fmt), ##__VA_ARGS__); \ + 0; \ +}) + +#define FW_BUG "[Firmware Bug]: " +#define FW_WARN "[Firmware Warn]: " +#define FW_INFO "[Firmware Info]: " +#define HW_ERR "[Hardware Error]: " +#define DEPRECATED "[Deprecated]: " + +#endif /* _LINUXKPI_LINUX_PRINTK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h b/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h new file mode 100644 index 000000000000..aad46cc25b1b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2023 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PTP_CLOCK_KERNEL_H +#define _LINUXKPI_LINUX_PTP_CLOCK_KERNEL_H + +#include <linux/types.h> +#include <linux/device.h> +#include <linux/kernel.h> /* pr_debug */ +#include <linux/ktime.h> /* system_device_crosststamp */ + +/* This very likely belongs elsewhere. */ +struct system_device_crosststamp { + ktime_t device; + ktime_t sys_realtime; + ktime_t sys_monotonic_raw; /* name guessed based on comment */ +}; + +struct ptp_clock_info { + char name[32]; + int max_adj; + void *owner; /* THIS_MODULE */ + int (*adjfine)(struct ptp_clock_info *, long); + int (*adjtime)(struct ptp_clock_info *, s64); + int (*getcrosststamp)(struct ptp_clock_info *, struct system_device_crosststamp *); + int (*gettime64)(struct ptp_clock_info *, struct timespec *); +}; + +static inline struct ptp_clock * +ptp_clock_register(struct ptp_clock_info *ptpci, struct device *dev) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline void +ptp_clock_unregister(struct ptp_clock *ptpc) +{ + pr_debug("%s: TODO\n", __func__); +} + +static inline int +ptp_clock_index(struct ptp_clock *ptpc) +{ + pr_debug("%s: TODO\n", __func__); + return (0); +} + +#endif /* _LINUXKPI_LINUX_PTP_CLOCK_KERNEL_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pwm.h b/sys/compat/linuxkpi/common/include/linux/pwm.h new file mode 100644 index 000000000000..c0740db675e8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/pwm.h @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2022 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PWM_H_ +#define _LINUXKPI_LINUX_PWM_H_ + +#include <linux/device.h> +#include <linux/err.h> + +struct pwm_state { + uint64_t period; + bool enabled; +}; + +struct pwm_device { + struct pwm_state state; +}; + +static inline struct pwm_device * +pwm_get(struct device *dev, const char *consumer) +{ + return (ERR_PTR(-ENODEV)); +} + +static inline void +pwm_put(struct pwm_device *pwm) +{ +} + +static inline int +pwm_enable(struct pwm_device *pwm) +{ + return (-EINVAL); +} + +static inline void +pwm_disable(struct pwm_device *pwm) +{ +} + +static inline bool +pwm_is_enabled(const struct pwm_device *pwm) +{ + return (false); +} + +static inline unsigned int +pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale) +{ + return (0); +} + +static inline int +pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle, + unsigned int scale) +{ + return (0); +} + +static inline void +pwm_get_state(const struct pwm_device *pwm, struct pwm_state *state) +{ + *state = pwm->state; +} + +static inline int +pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) +{ + return (-ENOTSUPP); +} + +static inline int +pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state) +{ + return (0); +} + +#endif /* _LINUXKPI_LINUX_PWM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/qrtr.h b/sys/compat/linuxkpi/common/include/linux/qrtr.h new file mode 100644 index 000000000000..1d2af0efdce2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/qrtr.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_QRTR_H +#define _LINUXKPI_LINUX_QRTR_H + +/* Qualcomm IPC Router (QRTR) */ + +#include <sys/socket.h> + +struct sockaddr_qrtr { + sa_family_t sq_family; + uint32_t sq_node; + uint32_t sq_port; +}; + +#endif /* _LINUXKPI_LINUX_QRTR_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/radix-tree.h b/sys/compat/linuxkpi/common/include/linux/radix-tree.h index 1bef60c44c41..ea75836c26fb 100644 --- a/sys/compat/linuxkpi/common/include/linux/radix-tree.h +++ b/sys/compat/linuxkpi/common/include/linux/radix-tree.h @@ -25,12 +25,11 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_RADIX_TREE_H_ -#define _LINUX_RADIX_TREE_H_ +#ifndef _LINUXKPI_LINUX_RADIX_TREE_H_ +#define _LINUXKPI_LINUX_RADIX_TREE_H_ +#include <linux/rcupdate.h> #include <linux/types.h> #define RADIX_TREE_MAP_SHIFT 6 @@ -82,4 +81,4 @@ int radix_tree_store(struct radix_tree_root *, unsigned long, void **); bool radix_tree_iter_find(struct radix_tree_root *, struct radix_tree_iter *, void ***); void radix_tree_iter_delete(struct radix_tree_root *, struct radix_tree_iter *, void **); -#endif /* _LINUX_RADIX_TREE_H_ */ +#endif /* _LINUXKPI_LINUX_RADIX_TREE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/random.h b/sys/compat/linuxkpi/common/include/linux/random.h index 12de0e12bc5a..893ee2b7b728 100644 --- a/sys/compat/linuxkpi/common/include/linux/random.h +++ b/sys/compat/linuxkpi/common/include/linux/random.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright 2023 The FreeBSD Foundation + * + * Portions of this software was developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,19 +29,15 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_RANDOM_H_ -#define _LINUX_RANDOM_H_ +#ifndef _LINUXKPI_LINUX_RANDOM_H_ +#define _LINUXKPI_LINUX_RANDOM_H_ #include <linux/types.h> #include <sys/random.h> #include <sys/libkern.h> -#define get_random_u32() get_random_int() - static inline void get_random_bytes(void *buf, int nbytes) { @@ -54,6 +54,39 @@ get_random_int(void) return (val); } +static inline uint8_t +get_random_u8(void) +{ + uint8_t val; + + get_random_bytes(&val, sizeof(val)); + return (val); +} + +#define get_random_u32() get_random_int() + +/* + * See "Fast Random Integer Generation in an Interval" by Daniel Lemire + * [https://arxiv.org/pdf/1805.10941.pdf] for implementation insights. + */ +static inline uint32_t +get_random_u32_inclusive(uint32_t floor, uint32_t ceil) +{ + uint64_t x; + uint32_t t, v; + + MPASS(ceil >= floor); + + v = get_random_u32(); + t = ceil - floor + 1; + x = (uint64_t)t * v; + while (x < t) + x = (uint64_t)t * get_random_u32(); + v = x >> 32; + + return (floor + v); +} + static inline u_long get_random_long(void) { @@ -63,6 +96,21 @@ get_random_long(void) return (val); } +static inline uint64_t +get_random_u64(void) +{ + uint64_t val; + + get_random_bytes(&val, sizeof(val)); + return (val); +} + +static inline uint32_t +get_random_u32_below(uint32_t max) +{ + return (arc4random_uniform(max)); +} + static __inline uint32_t prandom_u32(void) { @@ -78,4 +126,4 @@ prandom_u32_max(u32 max) return (arc4random_uniform(max)); } -#endif /* _LINUX_RANDOM_H_ */ +#endif /* _LINUXKPI_LINUX_RANDOM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ratelimit.h b/sys/compat/linuxkpi/common/include/linux/ratelimit.h new file mode 100644 index 000000000000..9585b4b994d7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ratelimit.h @@ -0,0 +1,17 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_RATELIMIT_H +#define _LINUXKPI_LINUX_RATELIMIT_H + +struct ratelimit_state { +}; + +#define DEFINE_RATELIMIT_STATE(name, interval, burst) \ + int name __used = 1; + +#define __ratelimit(x) (1) + +#define ratelimit_state_init(x, y, z) +#define ratelimit_set_flags(x, y) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/rbtree.h b/sys/compat/linuxkpi/common/include/linux/rbtree.h index 78da33ad2658..e6033cfd760d 100644 --- a/sys/compat/linuxkpi/common/include/linux/rbtree.h +++ b/sys/compat/linuxkpi/common/include/linux/rbtree.h @@ -25,23 +25,22 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_RBTREE_H_ -#define _LINUX_RBTREE_H_ +#ifndef _LINUXKPI_LINUX_RBTREE_H_ +#define _LINUXKPI_LINUX_RBTREE_H_ #ifndef _STANDALONE #include <sys/stddef.h> #endif +#include <sys/types.h> #include <sys/tree.h> struct rb_node { RB_ENTRY(rb_node) __entry; }; -#define rb_left __entry.rbe_left -#define rb_right __entry.rbe_right +#define rb_left __entry.rbe_link[_RB_L] +#define rb_right __entry.rbe_link[_RB_R] /* * We provide a false structure that has the same bit pattern as tree.h @@ -51,6 +50,11 @@ struct rb_root { struct rb_node *rb_node; }; +struct rb_root_cached { + struct rb_root rb_root; + struct rb_node *rb_leftmost; +}; + /* * In linux all of the comparisons are done by the caller. */ @@ -59,20 +63,62 @@ int panic_cmp(struct rb_node *one, struct rb_node *two); RB_HEAD(linux_root, rb_node); RB_PROTOTYPE(linux_root, rb_node, __entry, panic_cmp); +#define rb_parent(r) RB_PARENT(r, __entry) #define rb_entry(ptr, type, member) container_of(ptr, type, member) +#define rb_entry_safe(ptr, type, member) \ + ((ptr) != NULL ? rb_entry(ptr, type, member) : NULL) -#define RB_EMPTY_ROOT(root) RB_EMPTY((struct linux_root *)root) +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) #define RB_EMPTY_NODE(node) (RB_PARENT(node, __entry) == node) #define RB_CLEAR_NODE(node) RB_SET_PARENT(node, node, __entry) -#define rb_insert_color(node, root) \ - linux_root_RB_INSERT_COLOR((struct linux_root *)(root), (node)) +#define rb_insert_color(node, root) do { \ + if (rb_parent(node)) \ + linux_root_RB_INSERT_COLOR((struct linux_root *)(root), \ + rb_parent(node), (node)); \ +} while (0) #define rb_erase(node, root) \ linux_root_RB_REMOVE((struct linux_root *)(root), (node)) #define rb_next(node) RB_NEXT(linux_root, NULL, (node)) #define rb_prev(node) RB_PREV(linux_root, NULL, (node)) #define rb_first(root) RB_MIN(linux_root, (struct linux_root *)(root)) #define rb_last(root) RB_MAX(linux_root, (struct linux_root *)(root)) +#define rb_first_cached(root) (root)->rb_leftmost + +static inline struct rb_node * +__rb_deepest_left(struct rb_node *node) +{ + struct rb_node *parent = NULL; + while (node != NULL) { + parent = node; + if (RB_LEFT(node, __entry)) + node = RB_LEFT(node, __entry); + else + node = RB_RIGHT(node, __entry); + } + return (parent); +} + +static inline struct rb_node * +rb_next_postorder(const struct rb_node *node) +{ + struct rb_node *parent = + RB_PARENT(__DECONST(struct rb_node *, node), __entry); + /* left -> right, right -> root */ + if (parent != NULL && + (node == RB_LEFT(parent, __entry)) && + (RB_RIGHT(parent, __entry))) + return (__rb_deepest_left(RB_RIGHT(parent, __entry))); + else + return (parent); +} + +#define rbtree_postorder_for_each_entry_safe(x, y, head, member) \ + for ((x) = rb_entry_safe(__rb_deepest_left((head)->rb_node), \ + __typeof(*x), member); \ + ((x) != NULL) && ((y) = \ + rb_entry_safe(rb_next_postorder(&x->member), typeof(*x), member), 1); \ + (x) = (y)) static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, @@ -87,15 +133,74 @@ rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root) { - RB_SWAP_CHILD((struct linux_root *)root, victim, new, __entry); - if (victim->rb_left) - RB_SET_PARENT(victim->rb_left, new, __entry); - if (victim->rb_right) - RB_SET_PARENT(victim->rb_right, new, __entry); + RB_SWAP_CHILD((struct linux_root *)root, rb_parent(victim), + victim, new, __entry); + if (RB_LEFT(victim, __entry)) + RB_SET_PARENT(RB_LEFT(victim, __entry), new, __entry); + if (RB_RIGHT(victim, __entry)) + RB_SET_PARENT(RB_RIGHT(victim, __entry), new, __entry); *new = *victim; } +static inline void +rb_insert_color_cached(struct rb_node *node, struct rb_root_cached *root, + bool leftmost) +{ + if (rb_parent(node)) + linux_root_RB_INSERT_COLOR((struct linux_root *)&root->rb_root, + rb_parent(node), node); + if (leftmost) + root->rb_leftmost = node; +} + +static inline struct rb_node * +rb_erase_cached(struct rb_node *node, struct rb_root_cached *root) +{ + struct rb_node *retval; + + if (node == root->rb_leftmost) + retval = root->rb_leftmost = linux_root_RB_NEXT(node); + else + retval = NULL; + linux_root_RB_REMOVE((struct linux_root *)&root->rb_root, node); + return (retval); +} + +static inline void +rb_replace_node_cached(struct rb_node *old, struct rb_node *new, + struct rb_root_cached *root) +{ + rb_replace_node(old, new, &root->rb_root); + if (root->rb_leftmost == old) + root->rb_leftmost = new; +} + +static inline struct rb_node * +rb_add_cached(struct rb_node *node, struct rb_root_cached *tree, + bool (*less)(struct rb_node *, const struct rb_node *)) +{ + struct rb_node **link = &tree->rb_root.rb_node; + struct rb_node *parent = NULL; + bool leftmost = true; + + while (*link != NULL) { + parent = *link; + if (less(node, parent)) { + link = &RB_LEFT(parent, __entry); + } else { + link = &RB_RIGHT(parent, __entry); + leftmost = false; + } + } + + rb_link_node(node, parent, link); + rb_insert_color_cached(node, tree, leftmost); + + return (leftmost ? node : NULL); +} + #undef RB_ROOT #define RB_ROOT (struct rb_root) { NULL } +#define RB_ROOT_CACHED (struct rb_root_cached) { RB_ROOT, NULL } -#endif /* _LINUX_RBTREE_H_ */ +#endif /* _LINUXKPI_LINUX_RBTREE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/rculist.h b/sys/compat/linuxkpi/common/include/linux/rculist.h index 6c21a6943f98..066ed92b7996 100644 --- a/sys/compat/linuxkpi/common/include/linux/rculist.h +++ b/sys/compat/linuxkpi/common/include/linux/rculist.h @@ -23,12 +23,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_RCULIST_H_ -#define _LINUX_RCULIST_H_ +#ifndef _LINUXKPI_LINUX_RCULIST_H_ +#define _LINUXKPI_LINUX_RCULIST_H_ #include <linux/list.h> #include <linux/rcupdate.h> @@ -44,6 +42,11 @@ &(pos)->member != (head); \ pos = list_entry_rcu((pos)->member.next, typeof(*(pos)), member)) +#define list_for_each_entry_from_rcu(pos, head, member) \ + for (; \ + &(pos)->member != (head); \ + pos = list_entry_rcu((pos)->member.next, typeof(*(pos)), member)) + #define list_for_each_entry_lockless(pos, head, member) \ list_for_each_entry_rcu(pos, head, member) @@ -141,4 +144,4 @@ hlist_del_init_rcu(struct hlist_node *n) } } -#endif /* _LINUX_RCULIST_H_ */ +#endif /* _LINUXKPI_LINUX_RCULIST_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/rcupdate.h b/sys/compat/linuxkpi/common/include/linux/rcupdate.h index bd8335216d1d..4aceb7296cd6 100644 --- a/sys/compat/linuxkpi/common/include/linux/rcupdate.h +++ b/sys/compat/linuxkpi/common/include/linux/rcupdate.h @@ -1,6 +1,10 @@ /*- * Copyright (c) 2016-2017 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2024-2025 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,17 +26,25 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_RCUPDATE_H_ -#define _LINUX_RCUPDATE_H_ +#ifndef _LINUXKPI_LINUX_RCUPDATE_H_ +#define _LINUXKPI_LINUX_RCUPDATE_H_ + +#include <sys/cdefs.h> #include <linux/compiler.h> #include <linux/types.h> +#include <linux/kernel.h> +#include <linux/cleanup.h> #include <machine/atomic.h> +extern int linuxkpi_rcu_debug; +#define RCU_WARN_ONCE(c, ...) do { \ + if (unlikely(linuxkpi_rcu_debug > 0)) \ + WARN_ONCE((c), ##__VA_ARGS__); \ +} while(0) + #define LINUX_KFREE_RCU_OFFSET_MAX 4096 /* exclusive */ /* BSD specific defines */ @@ -63,6 +75,9 @@ linux_rcu_read_unlock(RCU_TYPE_REGULAR);\ } while (0) +#define rcu_read_lock_held(void) \ + linux_rcu_read_lock_held(RCU_TYPE_REGULAR) + #define synchronize_rcu(void) do { \ linux_synchronize_rcu(RCU_TYPE_REGULAR); \ } while (0) @@ -81,14 +96,34 @@ #define rcu_access_pointer(p) \ ((__typeof(*p) *)READ_ONCE(p)) -#define rcu_dereference_protected(p, c) \ +#define rcu_dereference(p) \ ((__typeof(*p) *)READ_ONCE(p)) -#define rcu_dereference(p) \ - rcu_dereference_protected(p, 0) +#define __rcu_var_name(n, f, l) \ + __CONCAT(__CONCAT(__CONCAT(rcu_, n), _), __COUNTER__) -#define rcu_dereference_check(p, c) \ - rcu_dereference_protected(p, c) +#define __rcu_dereference_protected(p, c, n) \ +({ \ + RCU_WARN_ONCE(!(c), "%s:%d: condition for %s failed\n", \ + __func__, __LINE__, __XSTRING(n)); \ + rcu_dereference(p); \ +}) + +#define rcu_dereference_protected(p, c) \ + __rcu_dereference_protected((p), (c), \ + __rcu_var_name(protected, __func__, __LINE__)) + +#define __rcu_dereference_check(p, c, n) \ +({ \ + __typeof(*p) *n = rcu_dereference(p); \ + RCU_WARN_ONCE(!(c), "%s:%d: condition for %s failed\n", \ + __func__, __LINE__, __XSTRING(n)); \ + n; \ +}) + +#define rcu_dereference_check(p, c) \ + __rcu_dereference_check((p), (c) || rcu_read_lock_held(), \ + __rcu_var_name(check, __func__, __LINE__)) #define rcu_dereference_raw(p) \ ((__typeof(*p) *)READ_ONCE(p)) @@ -115,11 +150,12 @@ /* prototypes */ -extern void linux_call_rcu(unsigned type, struct rcu_head *ptr, rcu_callback_t func); -extern void linux_rcu_barrier(unsigned type); -extern void linux_rcu_read_lock(unsigned type); -extern void linux_rcu_read_unlock(unsigned type); -extern void linux_synchronize_rcu(unsigned type); +void linux_call_rcu(unsigned type, struct rcu_head *ptr, rcu_callback_t func); +void linux_rcu_barrier(unsigned type); +void linux_rcu_read_lock(unsigned type); +void linux_rcu_read_unlock(unsigned type); +bool linux_rcu_read_lock_held(unsigned); +void linux_synchronize_rcu(unsigned type); /* Empty implementation for !DEBUG */ #define init_rcu_head(...) @@ -127,4 +163,6 @@ extern void linux_synchronize_rcu(unsigned type); #define init_rcu_head_on_stack(...) #define destroy_rcu_head_on_stack(...) -#endif /* _LINUX_RCUPDATE_H_ */ +DEFINE_LOCK_GUARD_0(rcu, rcu_read_lock(), rcu_read_unlock()) + +#endif /* _LINUXKPI_LINUX_RCUPDATE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/reboot.h b/sys/compat/linuxkpi/common/include/linux/reboot.h new file mode 100644 index 000000000000..eb696d7b9d2e --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/reboot.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_REBOOT_H_ +#define _LINUXKPI_LINUX_REBOOT_H_ + +#include <sys/reboot.h> + +static inline void +orderly_poweroff(bool force) +{ + + shutdown_nice(RB_POWEROFF); +} + +#endif + diff --git a/sys/compat/linuxkpi/common/include/linux/ref_tracker.h b/sys/compat/linuxkpi/common/include/linux/ref_tracker.h new file mode 100644 index 000000000000..fa510b2498e1 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ref_tracker.h @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_REF_TRACKER_H_ +#define _LINUXKPI_LINUX_REF_TRACKER_H_ + +#include <linux/refcount.h> +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/stackdepot.h> + +struct ref_tracker; + +struct ref_tracker_dir { +}; + +/* + * The following functions currently have dummy implementations that, on Linux, + * are used when CONFIG_REF_TRACKER is not set at compile time. + * + * The ref tracker is a tool to associate a refcount increase to a refcount + * decrease. This helps developers track, document and debug refcounts. We + * don't need this feature for now in linuxkpi. + */ + +static inline void +ref_tracker_dir_init(struct ref_tracker_dir *dir, + unsigned int quarantine_count, const char *name) +{ +} + +static inline void +ref_tracker_dir_exit(struct ref_tracker_dir *dir) +{ +} + +static inline void +ref_tracker_dir_print_locked(struct ref_tracker_dir *dir, + unsigned int display_limit) +{ +} + +static inline void +ref_tracker_dir_print(struct ref_tracker_dir *dir, unsigned int display_limit) +{ +} + +static inline int +ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size) +{ + return (0); +} + +static inline int +ref_tracker_alloc(struct ref_tracker_dir *dir, struct ref_tracker **trackerp, + gfp_t gfp) +{ + return (0); +} + +static inline int +ref_tracker_free(struct ref_tracker_dir *dir, struct ref_tracker **trackerp) +{ + return (0); +} + +#endif /* !defined(_LINUXKPI_LINUX_REF_TRACKER_H_) */ diff --git a/sys/compat/linuxkpi/common/include/linux/refcount.h b/sys/compat/linuxkpi/common/include/linux/refcount.h index 02f9f32f7eb4..46e501a65396 100644 --- a/sys/compat/linuxkpi/common/include/linux/refcount.h +++ b/sys/compat/linuxkpi/common/include/linux/refcount.h @@ -24,59 +24,62 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_REFCOUNT_H -#define _LINUX_REFCOUNT_H +#ifndef _LINUXKPI_LINUX_REFCOUNT_H +#define _LINUXKPI_LINUX_REFCOUNT_H #include <linux/atomic.h> +#include <linux/spinlock.h> -struct refcount_linux { - atomic_t value; -}; -typedef struct refcount_linux refcount_t; +typedef atomic_t refcount_t; static inline void refcount_set(refcount_t *ref, unsigned int i) { - atomic_set(&ref->value, i); + atomic_set(ref, i); } static inline void refcount_inc(refcount_t *ref) { - atomic_inc(&ref->value); + atomic_inc(ref); } static inline bool refcount_inc_not_zero(refcount_t *ref) { - return (atomic_inc_not_zero(&ref->value)); + return (atomic_inc_not_zero(ref)); } static inline void refcount_dec(refcount_t *ref) { - atomic_dec(&ref->value); + atomic_dec(ref); } static inline unsigned int refcount_read(refcount_t *ref) { - return atomic_read(&ref->value); + return atomic_read(ref); } static inline bool refcount_dec_and_lock_irqsave(refcount_t *ref, spinlock_t *lock, unsigned long *flags) { - if (atomic_dec_and_test(&ref->value) == true) { + if (atomic_dec_and_test(ref) == true) { spin_lock_irqsave(lock, flags); return (true); } return (false); } -#endif /* __LINUX_REFCOUNT_H__ */ +static inline bool +refcount_dec_and_test(refcount_t *r) +{ + + return (atomic_dec_and_test(r)); +} + +#endif /* __LINUXKPI_LINUX_REFCOUNT_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/rhashtable.h b/sys/compat/linuxkpi/common/include/linux/rhashtable.h new file mode 100644 index 000000000000..c6958b6ee5f3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/rhashtable.h @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_RHASHTABLE_H +#define _LINUXKPI_LINUX_RHASHTABLE_H + +#include <linux/kernel.h> /* pr_debug */ + +struct rhash_head { +}; + +struct rhashtable_params { + uint16_t head_offset; + uint16_t key_len; + uint16_t key_offset; + uint16_t nelem_hint; + bool automatic_shrinking; +}; + +struct rhashtable { +}; + +static inline int +rhashtable_init(struct rhashtable *rht, + const struct rhashtable_params *params) +{ + + pr_debug("%s: TODO\n", __func__); + return (-1); +} + +static inline void +rhashtable_destroy(struct rhashtable *rht) +{ + pr_debug("%s: TODO\n", __func__); +} + +static inline void * +rhashtable_lookup_fast(struct rhashtable *rht, const void *key, + const struct rhashtable_params params) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline void * +rhashtable_lookup_get_insert_fast(struct rhashtable *rht, + struct rhash_head *obj, const struct rhashtable_params params) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline int +rhashtable_remove_fast(struct rhashtable *rht, + struct rhash_head *obj, const struct rhashtable_params params) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENOENT); +} + +#endif /* _LINUXKPI_LINUX_RHASHTABLE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/rwlock.h b/sys/compat/linuxkpi/common/include/linux/rwlock.h index 621afb1e954b..3030ec89ff1e 100644 --- a/sys/compat/linuxkpi/common/include/linux/rwlock.h +++ b/sys/compat/linuxkpi/common/include/linux/rwlock.h @@ -25,25 +25,21 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_RWLOCK_H_ -#define _LINUX_RWLOCK_H_ +#ifndef _LINUXKPI_LINUX_RWLOCK_H_ +#define _LINUXKPI_LINUX_RWLOCK_H_ #include <sys/types.h> #include <sys/lock.h> #include <sys/rwlock.h> #include <sys/libkern.h> -typedef struct { - struct rwlock rw; -} rwlock_t; +typedef struct rwlock rwlock_t; -#define read_lock(_l) rw_rlock(&(_l)->rw) -#define write_lock(_l) rw_wlock(&(_l)->rw) -#define read_unlock(_l) rw_runlock(&(_l)->rw) -#define write_unlock(_l) rw_wunlock(&(_l)->rw) +#define read_lock(_l) rw_rlock(_l) +#define write_lock(_l) rw_wlock(_l) +#define read_unlock(_l) rw_runlock(_l) +#define write_unlock(_l) rw_wunlock(_l) #define read_lock_irq(lock) read_lock((lock)) #define read_unlock_irq(lock) read_unlock((lock)) #define write_lock_irq(lock) write_lock((lock)) @@ -56,13 +52,6 @@ typedef struct { do { read_unlock(lock); } while (0) #define write_unlock_irqrestore(lock, flags) \ do { write_unlock(lock); } while (0) +#define rwlock_init(_l) rw_init_flags(_l, "lnxrw", RW_NOWITNESS | RW_NEW) -static inline void -rwlock_init(rwlock_t *lock) -{ - - memset(&lock->rw, 0, sizeof(lock->rw)); - rw_init_flags(&lock->rw, "lnxrw", RW_NOWITNESS); -} - -#endif /* _LINUX_RWLOCK_H_ */ +#endif /* _LINUXKPI_LINUX_RWLOCK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/rwsem.h b/sys/compat/linuxkpi/common/include/linux/rwsem.h index 8850da91bd4d..b7a800b12e18 100644 --- a/sys/compat/linuxkpi/common/include/linux/rwsem.h +++ b/sys/compat/linuxkpi/common/include/linux/rwsem.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_RWSEM_H_ -#define _LINUX_RWSEM_H_ +#ifndef _LINUXKPI_LINUX_RWSEM_H_ +#define _LINUXKPI_LINUX_RWSEM_H_ #include <sys/param.h> #include <sys/lock.h> @@ -46,11 +44,13 @@ struct rw_semaphore { #define down_read(_rw) sx_slock(&(_rw)->sx) #define up_read(_rw) sx_sunlock(&(_rw)->sx) #define down_read_trylock(_rw) !!sx_try_slock(&(_rw)->sx) +#define down_read_killable(_rw) linux_down_read_killable(_rw) #define down_write_trylock(_rw) !!sx_try_xlock(&(_rw)->sx) #define down_write_killable(_rw) linux_down_write_killable(_rw) #define downgrade_write(_rw) sx_downgrade(&(_rw)->sx) #define down_read_nested(_rw, _sc) down_read(_rw) #define init_rwsem(_rw) linux_init_rwsem(_rw, rwsem_name("lnxrwsem")) +#define down_write_nest_lock(sem, _rw) down_write(_rw) #ifdef WITNESS_ALL /* NOTE: the maximum WITNESS name is 64 chars */ @@ -79,6 +79,7 @@ linux_init_rwsem(struct rw_semaphore *rw, const char *name) sx_init_flags(&rw->sx, name, SX_NOWITNESS); } +extern int linux_down_read_killable(struct rw_semaphore *); extern int linux_down_write_killable(struct rw_semaphore *); -#endif /* _LINUX_RWSEM_H_ */ +#endif /* _LINUXKPI_LINUX_RWSEM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/scatterlist.h b/sys/compat/linuxkpi/common/include/linux/scatterlist.h index 295ca2ba3cfd..537f5bebc5aa 100644 --- a/sys/compat/linuxkpi/common/include/linux/scatterlist.h +++ b/sys/compat/linuxkpi/common/include/linux/scatterlist.h @@ -27,15 +27,16 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SCATTERLIST_H_ -#define _LINUX_SCATTERLIST_H_ +#ifndef _LINUXKPI_LINUX_SCATTERLIST_H_ +#define _LINUXKPI_LINUX_SCATTERLIST_H_ #include <sys/types.h> +#include <sys/proc.h> +#include <sys/sched.h> #include <sys/sf_buf.h> +#include <linux/err.h> #include <linux/page.h> #include <linux/slab.h> #include <linux/mm.h> @@ -99,6 +100,18 @@ struct sg_dma_page_iter { #define for_each_sg(sglist, sg, sgmax, iter) \ for (iter = 0, sg = (sglist); iter < (sgmax); iter++, sg = sg_next(sg)) +#define for_each_sgtable_sg(sgt, sg, i) \ + for_each_sg((sgt)->sgl, sg, (sgt)->orig_nents, i) + +#define for_each_sgtable_page(sgt, iter, pgoffset) \ + for_each_sg_page((sgt)->sgl, iter, (sgt)->orig_nents, pgoffset) + +#define for_each_sgtable_dma_sg(sgt, sg, iter) \ + for_each_sg((sgt)->sgl, sg, (sgt)->nents, iter) + +#define for_each_sgtable_dma_page(sgt, iter, pgoffset) \ + for_each_sg_dma_page((sgt)->sgl, iter, (sgt)->nents, pgoffset) + typedef struct scatterlist *(sg_alloc_fn) (unsigned int, gfp_t); typedef void (sg_free_fn) (struct scatterlist *, unsigned int); @@ -146,7 +159,7 @@ sg_next(struct scatterlist *sg) static inline vm_paddr_t sg_phys(struct scatterlist *sg) { - return (VM_PAGE_TO_PHYS(sg_page(sg)) + sg->offset); + return (page_to_phys(sg_page(sg)) + sg->offset); } static inline void * @@ -315,18 +328,40 @@ sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) return (ret); } +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 +static inline struct scatterlist * +__sg_alloc_table_from_pages(struct sg_table *sgt, + struct page **pages, unsigned int count, + unsigned long off, unsigned long size, + unsigned int max_segment, + struct scatterlist *prv, unsigned int left_pages, + gfp_t gfp_mask) +#else static inline int __sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages, unsigned int count, unsigned long off, unsigned long size, unsigned int max_segment, gfp_t gfp_mask) +#endif { unsigned int i, segs, cur, len; int rc; - struct scatterlist *s; + struct scatterlist *s, *sg_iter; + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + if (prv != NULL) { + panic( + "Support for prv != NULL not implemented in " + "__sg_alloc_table_from_pages()"); + } +#endif if (__predict_false(!max_segment || offset_in_page(max_segment))) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (ERR_PTR(-EINVAL)); +#else return (-EINVAL); +#endif len = 0; for (segs = i = 1; i < count; ++i) { @@ -338,13 +373,25 @@ __sg_alloc_table_from_pages(struct sg_table *sgt, } } if (__predict_false((rc = sg_alloc_table(sgt, segs, gfp_mask)))) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (ERR_PTR(rc)); +#else return (rc); +#endif cur = 0; - for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { + for_each_sg(sgt->sgl, sg_iter, sgt->orig_nents, i) { unsigned long seg_size; unsigned int j; + /* + * We need to make sure that when we exit this loop "s" has the + * last sg in the chain so we can call sg_mark_end() on it. + * Only set this inside the loop since sg_iter will be iterated + * until it is NULL. + */ + s = sg_iter; + len = 0; for (j = cur + 1; j < count; ++j) { len += PAGE_SIZE; @@ -359,7 +406,16 @@ __sg_alloc_table_from_pages(struct sg_table *sgt, off = 0; cur = j; } + KASSERT(s != NULL, ("s is NULL after loop in __sg_alloc_table_from_pages()")); + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + if (left_pages == 0) + sg_mark_end(s); + + return (s); +#else return (0); +#endif } static inline int @@ -369,8 +425,27 @@ sg_alloc_table_from_pages(struct sg_table *sgt, gfp_t gfp_mask) { +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (PTR_ERR_OR_ZERO(__sg_alloc_table_from_pages(sgt, pages, count, off, size, + SCATTERLIST_MAX_SEGMENT, NULL, 0, gfp_mask))); +#else return (__sg_alloc_table_from_pages(sgt, pages, count, off, size, SCATTERLIST_MAX_SEGMENT, gfp_mask)); +#endif +} + +static inline int +sg_alloc_table_from_pages_segment(struct sg_table *sgt, + struct page **pages, unsigned int count, unsigned int off, + unsigned long size, unsigned int max_segment, gfp_t gfp_mask) +{ +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (PTR_ERR_OR_ZERO(__sg_alloc_table_from_pages(sgt, pages, count, off, size, + max_segment, NULL, 0, gfp_mask))); +#else + return (__sg_alloc_table_from_pages(sgt, pages, count, off, size, + max_segment, gfp_mask)); +#endif } static inline int @@ -581,7 +656,7 @@ sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, break; vaddr = (char *)sf_buf_kva(sf); } else - vaddr = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(page)); + vaddr = (char *)PHYS_TO_DMAP(page_to_phys(page)); memcpy(buf, vaddr + sg->offset + offset, len); if (!PMAP_HAS_DMAP) sf_buf_free(sf); @@ -599,4 +674,11 @@ sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, return (total); } -#endif /* _LINUX_SCATTERLIST_H_ */ +static inline void +sg_set_folio(struct scatterlist *sg, struct folio *folio, size_t len, + size_t offset) +{ + sg_set_page(sg, &folio->page, len, offset); +} + +#endif /* _LINUXKPI_LINUX_SCATTERLIST_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/sched.h b/sys/compat/linuxkpi/common/include/linux/sched.h index 5954b16f6496..3ad2f8e4ce8b 100644 --- a/sys/compat/linuxkpi/common/include/linux/sched.h +++ b/sys/compat/linuxkpi/common/include/linux/sched.h @@ -25,15 +25,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SCHED_H_ -#define _LINUX_SCHED_H_ +#ifndef _LINUXKPI_LINUX_SCHED_H_ +#define _LINUXKPI_LINUX_SCHED_H_ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/rtprio.h> #include <sys/sched.h> #include <sys/sleepqueue.h> #include <sys/time.h> @@ -41,15 +40,20 @@ #include <linux/bitmap.h> #include <linux/compat.h> #include <linux/completion.h> +#include <linux/hrtimer.h> #include <linux/mm_types.h> +#include <linux/nodemask.h> #include <linux/pid.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/spinlock.h> #include <linux/time.h> +#include <linux/sched/mm.h> + #include <asm/atomic.h> -#define MAX_SCHEDULE_TIMEOUT INT_MAX +#define MAX_SCHEDULE_TIMEOUT LONG_MAX #define TASK_RUNNING 0x0000 #define TASK_INTERRUPTIBLE 0x0001 @@ -60,6 +64,8 @@ #define TASK_COMM_LEN (MAXCOMLEN + 1) +struct seq_file; + struct work_struct; struct task_struct { struct thread *task_thread; @@ -125,7 +131,20 @@ put_task_struct(struct task_struct *task) #define yield() kern_yield(PRI_UNCHANGED) #define sched_yield() sched_relinquish(curthread) -#define need_resched() (curthread->td_flags & TDF_NEEDRESCHED) +#define need_resched() (curthread->td_owepreempt || \ + td_ast_pending(curthread, TDA_SCHED)) + +static inline int +cond_resched_lock(spinlock_t *lock) +{ + + if (need_resched() == 0) + return (0); + spin_unlock(lock); + cond_resched(); + spin_lock(lock); + return (1); +} bool linux_signal_pending(struct task_struct *task); bool linux_fatal_signal_pending(struct task_struct *task); @@ -141,7 +160,7 @@ void linux_send_sig(int signo, struct task_struct *task); linux_send_sig(signo, task); \ } while (0) -int linux_schedule_timeout(int timeout); +long linux_schedule_timeout(long timeout); static inline void linux_schedule_save_interrupt_value(struct task_struct *task, int value) @@ -162,8 +181,12 @@ linux_schedule_get_interrupt_value(struct task_struct *task) return (value); } -#define schedule() \ - (void)linux_schedule_timeout(MAX_SCHEDULE_TIMEOUT) +static inline void +schedule(void) +{ + (void)linux_schedule_timeout(MAX_SCHEDULE_TIMEOUT); +} + #define schedule_timeout(timeout) \ linux_schedule_timeout(timeout) #define schedule_timeout_killable(timeout) \ @@ -197,4 +220,24 @@ get_task_comm(char *buf, struct task_struct *task) return (task->comm); } -#endif /* _LINUX_SCHED_H_ */ +static inline void +sched_set_fifo(struct task_struct *t) +{ + struct rtprio rtp; + + rtp.prio = (RTP_PRIO_MIN + RTP_PRIO_MAX) / 2; + rtp.type = RTP_PRIO_FIFO; + rtp_to_pri(&rtp, t->task_thread); +} + +static inline void +sched_set_fifo_low(struct task_struct *t) +{ + struct rtprio rtp; + + rtp.prio = RTP_PRIO_MAX; /* lowest priority */ + rtp.type = RTP_PRIO_FIFO; + rtp_to_pri(&rtp, t->task_thread); +} + +#endif /* _LINUXKPI_LINUX_SCHED_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/sched/mm.h b/sys/compat/linuxkpi/common/include/linux/sched/mm.h new file mode 100644 index 000000000000..c26d99378974 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/sched/mm.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_SCHED_MM_H_ +#define _LINUXKPI_LINUX_SCHED_MM_H_ + +#include <linux/gfp.h> + +#define fs_reclaim_acquire(x) do { \ + } while (0) +#define fs_reclaim_release(x) do { \ + } while (0) +#define memalloc_nofs_save(x) 0 +#define memalloc_nofs_restore(x) do { \ + } while (0) +#define memalloc_noreclaim_save(x) 0 +#define memalloc_noreclaim_restore(x) do { \ + } while (0) + +#endif /* _BSD_LKPI_LINUX_SCHED_MM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/semaphore.h b/sys/compat/linuxkpi/common/include/linux/semaphore.h index e4a72fd9b47a..4b1a1502e589 100644 --- a/sys/compat/linuxkpi/common/include/linux/semaphore.h +++ b/sys/compat/linuxkpi/common/include/linux/semaphore.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SEMAPHORE_H_ -#define _LINUX_SEMAPHORE_H_ +#ifndef _LINUXKPI_LINUX_SEMAPHORE_H_ +#define _LINUXKPI_LINUX_SEMAPHORE_H_ #include <sys/param.h> #include <sys/lock.h> @@ -67,4 +65,4 @@ init_MUTEX(struct semaphore *sem) #define sema_init(...) linux_sema_init(__VA_ARGS__) -#endif /* _LINUX_SEMAPHORE_H_ */ +#endif /* _LINUXKPI_LINUX_SEMAPHORE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/seq_file.h b/sys/compat/linuxkpi/common/include/linux/seq_file.h index dab8020a0336..47da16ab8688 100644 --- a/sys/compat/linuxkpi/common/include/linux/seq_file.h +++ b/sys/compat/linuxkpi/common/include/linux/seq_file.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org> * @@ -23,20 +23,24 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SEQ_FILE_H_ -#define _LINUX_SEQ_FILE_H_ +#ifndef _LINUXKPI_LINUX_SEQ_FILE_H_ +#define _LINUXKPI_LINUX_SEQ_FILE_H_ + +#include <sys/types.h> +#include <sys/sbuf.h> #include <linux/types.h> #include <linux/fs.h> -#include <sys/sbuf.h> +#include <linux/string_helpers.h> +#include <linux/printk.h> #undef file #define inode vnode +MALLOC_DECLARE(M_LSEQ); + #define DEFINE_SHOW_ATTRIBUTE(__name) \ static int __name ## _open(struct inode *inode, struct linux_file *file) \ { \ @@ -51,11 +55,24 @@ static const struct file_operations __name ## _fops = { \ .release = single_release, \ } -struct seq_operations; +#define DEFINE_SHOW_STORE_ATTRIBUTE(__name) \ +static int __name ## _open(struct inode *inode, struct linux_file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ + \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __name ## _open, \ + .read = seq_read, \ + .write = __name ## _write, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} struct seq_file { - struct sbuf *buf; - + struct sbuf *buf; + size_t size; const struct seq_operations *op; const struct linux_file *file; void *private; @@ -70,19 +87,37 @@ struct seq_operations { ssize_t seq_read(struct linux_file *, char *, size_t, off_t *); int seq_write(struct seq_file *seq, const void *data, size_t len); +void seq_putc(struct seq_file *m, char c); +void seq_puts(struct seq_file *m, const char *str); +bool seq_has_overflowed(struct seq_file *m); + +void *__seq_open_private(struct linux_file *, const struct seq_operations *, int); +int seq_release_private(struct inode *, struct linux_file *); int seq_open(struct linux_file *f, const struct seq_operations *op); int seq_release(struct inode *inode, struct linux_file *file); off_t seq_lseek(struct linux_file *file, off_t offset, int whence); int single_open(struct linux_file *, int (*)(struct seq_file *, void *), void *); +int single_open_size(struct linux_file *, int (*)(struct seq_file *, void *), void *, size_t); int single_release(struct inode *, struct linux_file *); -#define seq_printf(m, fmt, ...) sbuf_printf((m)->buf, (fmt), ##__VA_ARGS__) +void lkpi_seq_vprintf(struct seq_file *m, const char *fmt, va_list args); +void lkpi_seq_printf(struct seq_file *m, const char *fmt, ...); + +#define seq_vprintf(...) lkpi_seq_vprintf(__VA_ARGS__) +#define seq_printf(...) lkpi_seq_printf(__VA_ARGS__) -#define seq_puts(m, str) sbuf_printf((m)->buf, str) -#define seq_putc(m, str) sbuf_putc((m)->buf, str) +int __lkpi_hexdump_sbuf_printf(void *, const char *, ...) __printflike(2, 3); + +static inline void +seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type, + int rowsize, int groupsize, const void *buf, size_t len, bool ascii) +{ + lkpi_hex_dump(__lkpi_hexdump_sbuf_printf, m->buf, NULL, prefix_str, prefix_type, + rowsize, groupsize, buf, len, ascii); +} #define file linux_file -#endif /* _LINUX_SEQ_FILE_H_ */ +#endif /* _LINUXKPI_LINUX_SEQ_FILE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/seqlock.h b/sys/compat/linuxkpi/common/include/linux/seqlock.h index b7ae6e32ae69..554fdfd6e202 100644 --- a/sys/compat/linuxkpi/common/include/linux/seqlock.h +++ b/sys/compat/linuxkpi/common/include/linux/seqlock.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> * @@ -26,12 +26,15 @@ * SUCH DAMAGE. */ -#ifndef _LINUX_SEQLOCK_H__ -#define _LINUX_SEQLOCK_H__ +#ifndef _LINUXKPI_LINUX_SEQLOCK_H__ +#define _LINUXKPI_LINUX_SEQLOCK_H__ #include <sys/param.h> +#include <sys/systm.h> +#include <sys/cdefs.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/rwlock.h> #include <sys/seqc.h> struct lock_class_key; @@ -47,6 +50,12 @@ struct seqlock { }; typedef struct seqlock seqlock_t; +struct seqcount_mutex { + seqc_t seqc; +}; +typedef struct seqcount_mutex seqcount_mutex_t; +typedef struct seqcount_mutex seqcount_ww_mutex_t; + static inline void __seqcount_init(struct seqcount *seqcount, const char *name __unused, struct lock_class_key *key __unused) @@ -56,37 +65,52 @@ __seqcount_init(struct seqcount *seqcount, const char *name __unused, #define seqcount_init(seqcount) __seqcount_init(seqcount, NULL, NULL) static inline void -write_seqcount_begin(struct seqcount *seqcount) +seqcount_mutex_init(struct seqcount_mutex *seqcount, void *mutex __unused) { - seqc_sleepable_write_begin(&seqcount->seqc); + seqcount->seqc = 0; } +#define seqcount_ww_mutex_init(seqcount, ww_mutex) \ + seqcount_mutex_init((seqcount), (ww_mutex)) + +#define write_seqcount_begin(s) \ + _Generic(*(s), \ + struct seqcount: seqc_sleepable_write_begin, \ + struct seqcount_mutex: seqc_write_begin \ + )(&(s)->seqc) + +#define write_seqcount_end(s) \ + _Generic(*(s), \ + struct seqcount: seqc_sleepable_write_end, \ + struct seqcount_mutex: seqc_write_end \ + )(&(s)->seqc) + static inline void -write_seqcount_end(struct seqcount *seqcount) +lkpi_write_seqcount_invalidate(seqc_t *seqcp) { - seqc_sleepable_write_end(&seqcount->seqc); + atomic_thread_fence_rel(); + *seqcp += SEQC_MOD * 2; } +#define write_seqcount_invalidate(s) lkpi_write_seqcount_invalidate(&(s)->seqc) + +#define read_seqcount_begin(s) seqc_read(&(s)->seqc) +#define raw_read_seqcount(s) seqc_read_any(&(s)->seqc) + +static inline seqc_t +lkpi_seqprop_sequence(const seqc_t *seqcp) +{ + return (atomic_load_int(seqcp)); +} +#define seqprop_sequence(s) lkpi_seqprop_sequence(&(s)->seqc) /* * XXX: Are predicts from inline functions still not honored by clang? */ #define __read_seqcount_retry(seqcount, gen) \ - (!seqc_consistent_nomb(&(seqcount)->seqc, gen)) + (!seqc_consistent_no_fence(&(seqcount)->seqc, gen)) #define read_seqcount_retry(seqcount, gen) \ (!seqc_consistent(&(seqcount)->seqc, gen)) -static inline unsigned -read_seqcount_begin(const struct seqcount *seqcount) -{ - return (seqc_read(&seqcount->seqc)); -} - -static inline unsigned -raw_read_seqcount(const struct seqcount *seqcount) -{ - return (seqc_read_any(&seqcount->seqc)); -} - static inline void seqlock_init(struct seqlock *seqlock) { @@ -100,29 +124,52 @@ seqlock_init(struct seqlock *seqlock) } static inline void -write_seqlock(struct seqlock *seqlock) +lkpi_write_seqlock(struct seqlock *seqlock, const bool irqsave) { mtx_lock(&seqlock->seql_lock); + if (irqsave) + critical_enter(); write_seqcount_begin(&seqlock->seql_count); } static inline void -write_sequnlock(struct seqlock *seqlock) +write_seqlock(struct seqlock *seqlock) +{ + lkpi_write_seqlock(seqlock, false); +} + +static inline void +lkpi_write_sequnlock(struct seqlock *seqlock, const bool irqsave) { write_seqcount_end(&seqlock->seql_count); + if (irqsave) + critical_exit(); mtx_unlock(&seqlock->seql_lock); } +static inline void +write_sequnlock(struct seqlock *seqlock) +{ + lkpi_write_sequnlock(seqlock, false); +} + +/* + * Disable preemption when the consumer wants to disable interrupts. This + * ensures that the caller won't be starved if it is preempted by a + * higher-priority reader, but assumes that the caller won't perform any + * blocking operations while holding the write lock; probably a safe + * assumption. + */ #define write_seqlock_irqsave(seqlock, flags) do { \ (flags) = 0; \ - write_seqlock(seqlock); \ + lkpi_write_seqlock(seqlock, true); \ } while (0) static inline void write_sequnlock_irqrestore(struct seqlock *seqlock, unsigned long flags __unused) { - write_sequnlock(seqlock); + lkpi_write_sequnlock(seqlock, true); } static inline unsigned @@ -134,4 +181,4 @@ read_seqbegin(const struct seqlock *seqlock) #define read_seqretry(seqlock, gen) \ read_seqcount_retry(&(seqlock)->seql_count, gen) -#endif /* _LINUX_SEQLOCK_H__ */ +#endif /* _LINUXKPI_LINUX_SEQLOCK_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/shmem_fs.h b/sys/compat/linuxkpi/common/include/linux/shmem_fs.h index 63aff012c6bb..5e91725d4a1c 100644 --- a/sys/compat/linuxkpi/common/include/linux/shmem_fs.h +++ b/sys/compat/linuxkpi/common/include/linux/shmem_fs.h @@ -25,20 +25,22 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SHMEM_FS_H_ -#define _LINUX_SHMEM_FS_H_ +#ifndef _LINUXKPI_LINUX_SHMEM_FS_H_ +#define _LINUXKPI_LINUX_SHMEM_FS_H_ -/* Shared memory support */ -unsigned long linux_invalidate_mapping_pages(vm_object_t, pgoff_t, pgoff_t); -struct page *linux_shmem_read_mapping_page_gfp(vm_object_t, int, gfp_t); -struct linux_file *linux_shmem_file_setup(const char *, loff_t, unsigned long); -void linux_shmem_truncate_range(vm_object_t, loff_t, loff_t); +#include <linux/file.h> +#include <linux/mempolicy.h> +#include <linux/pagemap.h> +#include <linux/swap.h> -#define invalidate_mapping_pages(...) \ - linux_invalidate_mapping_pages(__VA_ARGS__) +/* Shared memory support */ +struct page *linux_shmem_read_mapping_page_gfp(vm_object_t obj, int pindex, + gfp_t gfp); +struct linux_file *linux_shmem_file_setup(const char *name, loff_t size, + unsigned long flags); +void linux_shmem_truncate_range(vm_object_t obj, loff_t lstart, + loff_t lend); #define shmem_read_mapping_page(...) \ linux_shmem_read_mapping_page_gfp(__VA_ARGS__, 0) @@ -52,4 +54,14 @@ void linux_shmem_truncate_range(vm_object_t, loff_t, loff_t); #define shmem_truncate_range(...) \ linux_shmem_truncate_range(__VA_ARGS__) -#endif /* _LINUX_SHMEM_FS_H_ */ +static inline struct folio * +shmem_read_folio_gfp(vm_object_t obj, int pindex, gfp_t gfp) +{ + struct page *page; + + page = shmem_read_mapping_page_gfp(obj, pindex, gfp); + + return (page_folio(page)); +} + +#endif /* _LINUXKPI_LINUX_SHMEM_FS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/shrinker.h b/sys/compat/linuxkpi/common/include/linux/shrinker.h index d18bb60645f8..eb95dafb83ce 100644 --- a/sys/compat/linuxkpi/common/include/linux/shrinker.h +++ b/sys/compat/linuxkpi/common/include/linux/shrinker.h @@ -21,16 +21,18 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUX_SHRINKER_H__ -#define __LINUX_SHRINKER_H__ +#ifndef _LINUXKPI_LINUX_SHRINKER_H_ +#define _LINUXKPI_LINUX_SHRINKER_H_ #include <sys/queue.h> +#include <linux/bitops.h> +#include <linux/gfp.h> + struct shrink_control { + gfp_t gfp_mask; unsigned long nr_to_scan; unsigned long nr_scanned; }; @@ -39,6 +41,8 @@ struct shrinker { unsigned long (*count_objects)(struct shrinker *, struct shrink_control *); unsigned long (*scan_objects)(struct shrinker *, struct shrink_control *); int seeks; + unsigned int flags; + void * private_data; long batch; TAILQ_ENTRY(shrinker) next; }; @@ -47,10 +51,29 @@ struct shrinker { #define DEFAULT_SEEKS 2 +#define SHRINKER_REGISTERED BIT(0) +#define SHRINKER_ALLOCATED BIT(1) + +struct shrinker *linuxkpi_shrinker_alloc( + unsigned int flags, const char *fmt, ...); int linuxkpi_register_shrinker(struct shrinker *s); void linuxkpi_unregister_shrinker(struct shrinker *s); +void linuxkpi_shrinker_free(struct shrinker *shrinker); +void linuxkpi_synchronize_shrinkers(void); + +#define shrinker_alloc(flags, fmt, ...) \ + linuxkpi_shrinker_alloc(flags, fmt __VA_OPT__(,) __VA_ARGS__) +#define shrinker_register(shrinker) \ + linuxkpi_register_shrinker(shrinker) +#define shrinker_free(shrinker) \ + linuxkpi_shrinker_free(shrinker) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60000 +#define register_shrinker(s, ...) linuxkpi_register_shrinker(s) +#else #define register_shrinker(s) linuxkpi_register_shrinker(s) +#endif #define unregister_shrinker(s) linuxkpi_unregister_shrinker(s) +#define synchronize_shrinkers() linuxkpi_synchronize_shrinkers() -#endif /* __LINUX_SHRINKER_H__ */ +#endif /* _LINUXKPI_LINUX_SHRINKER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/sizes.h b/sys/compat/linuxkpi/common/include/linux/sizes.h index a180cee5f022..d8a6e75192f6 100644 --- a/sys/compat/linuxkpi/common/include/linux/sizes.h +++ b/sys/compat/linuxkpi/common/include/linux/sizes.h @@ -24,14 +24,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUX_SIZES_H__ -#define __LINUX_SIZES_H__ +#ifndef _LINUXKPI_LINUX_SIZES_H_ +#define _LINUXKPI_LINUX_SIZES_H_ #define SZ_1K (1024 * 1) +#define SZ_2K (1024 * 2) #define SZ_4K (1024 * 4) #define SZ_8K (1024 * 8) #define SZ_16K (1024 * 16) @@ -43,9 +42,22 @@ #define SZ_1M (1024 * 1024 * 1) #define SZ_2M (1024 * 1024 * 2) +#define SZ_4M (1024 * 1024 * 4) #define SZ_8M (1024 * 1024 * 8) #define SZ_16M (1024 * 1024 * 16) #define SZ_32M (1024 * 1024 * 32) #define SZ_64M (1024 * 1024 * 64) +#define SZ_128M (1024 * 1024 * 128) +#define SZ_256M (1024 * 1024 * 256) +#define SZ_512M (1024 * 1024 * 512) + +#define SZ_1G (1024 * 1024 * 1024 * 1) +#define SZ_2G (1024 * 1024 * 1024 * 2) +#define SZ_4G (1024 * 1024 * 1024 * 4) +#define SZ_8G (1024 * 1024 * 1024 * 8) +#define SZ_16G (1024 * 1024 * 1024 * 16) +#define SZ_32G (1024 * 1024 * 1024 * 32) + +#define SZ_64T (1024 * 1024 * 1024 * 1024 * 64) #endif diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h new file mode 100644 index 000000000000..2e560a120e41 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h @@ -0,0 +1,1168 @@ +/*- + * Copyright (c) 2020-2025 The FreeBSD Foundation + * Copyright (c) 2021-2025 Bjoern A. Zeeb + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * NOTE: this socket buffer compatibility code is highly EXPERIMENTAL. + * Do not rely on the internals of this implementation. They are highly + * likely to change as we will improve the integration to FreeBSD mbufs. + */ + +#ifndef _LINUXKPI_LINUX_SKBUFF_H +#define _LINUXKPI_LINUX_SKBUFF_H + +#include <linux/kernel.h> +#include <linux/page.h> +#include <linux/dma-mapping.h> +#include <linux/netdev_features.h> +#include <linux/list.h> +#include <linux/gfp.h> +#include <linux/compiler.h> +#include <linux/spinlock.h> +#include <linux/ktime.h> +#include <linux/compiler.h> + +/* + * At least the net/intel-irdma-kmod port pulls this header in; likely through + * if_ether.h (see PR289268). This means we no longer can rely on + * IEEE80211_DEBUG (opt_wlan.h) to automatically set SKB_DEBUG. + */ +/* #define SKB_DEBUG */ + +#ifdef SKB_DEBUG +#define DSKB_TODO 0x01 +#define DSKB_IMPROVE 0x02 +#define DSKB_TRACE 0x10 +#define DSKB_TRACEX 0x20 +extern int linuxkpi_debug_skb; + +#define SKB_TODO() \ + if (linuxkpi_debug_skb & DSKB_TODO) \ + printf("SKB_TODO %s:%d\n", __func__, __LINE__) +#define SKB_IMPROVE(...) \ + if (linuxkpi_debug_skb & DSKB_IMPROVE) \ + printf("SKB_IMPROVE %s:%d\n", __func__, __LINE__) +#define SKB_TRACE(_s) \ + if (linuxkpi_debug_skb & DSKB_TRACE) \ + printf("SKB_TRACE %s:%d %p\n", __func__, __LINE__, _s) +#define SKB_TRACE2(_s, _p) \ + if (linuxkpi_debug_skb & DSKB_TRACE) \ + printf("SKB_TRACE %s:%d %p, %p\n", __func__, __LINE__, _s, _p) +#define SKB_TRACE_FMT(_s, _fmt, ...) \ + if (linuxkpi_debug_skb & DSKB_TRACE) \ + printf("SKB_TRACE %s:%d %p " _fmt "\n", __func__, __LINE__, _s, \ + __VA_ARGS__) +#else +#define SKB_TODO() do { } while(0) +#define SKB_IMPROVE(...) do { } while(0) +#define SKB_TRACE(_s) do { } while(0) +#define SKB_TRACE2(_s, _p) do { } while(0) +#define SKB_TRACE_FMT(_s, ...) do { } while(0) +#endif + +enum sk_buff_pkt_type { + PACKET_BROADCAST, + PACKET_MULTICAST, + PACKET_OTHERHOST, +}; + +struct skb_shared_hwtstamps { + ktime_t hwtstamp; +}; + +#define NET_SKB_PAD max(CACHE_LINE_SIZE, 32) +#define SKB_DATA_ALIGN(_x) roundup2(_x, CACHE_LINE_SIZE) + +struct sk_buff_head { + /* XXX TODO */ + union { + struct { + struct sk_buff *next; + struct sk_buff *prev; + }; + struct sk_buff_head_l { + struct sk_buff *next; + struct sk_buff *prev; + } list; + }; + size_t qlen; + spinlock_t lock; +}; + +enum sk_checksum_flags { + CHECKSUM_NONE = 0x00, + CHECKSUM_UNNECESSARY = 0x01, + CHECKSUM_PARTIAL = 0x02, + CHECKSUM_COMPLETE = 0x03, +}; + +struct skb_frag { + /* XXX TODO */ + struct page *page; /* XXX-BZ These three are a wild guess so far! */ + off_t offset; + size_t size; +}; +typedef struct skb_frag skb_frag_t; + +enum skb_shared_info_gso_type { + SKB_GSO_TCPV4, + SKB_GSO_TCPV6, +}; + +struct skb_shared_info { + enum skb_shared_info_gso_type gso_type; + uint16_t gso_size; + uint16_t nr_frags; + struct sk_buff *frag_list; + skb_frag_t frags[64]; /* XXX TODO, 16xpage? */ +}; + +struct sk_buff { + /* XXX TODO */ + union { + /* struct sk_buff_head */ + struct { + struct sk_buff *next; + struct sk_buff *prev; + }; + struct list_head list; + }; + + uint8_t *head; /* Head of buffer. */ + uint8_t *data; /* Head of data. */ + uint8_t *tail; /* End of data. */ + uint8_t *end; /* End of buffer. */ + + uint32_t len; /* ? */ + uint32_t data_len; /* ? If we have frags? */ + union { + __wsum csum; + struct { + uint16_t csum_offset; + uint16_t csum_start; + }; + }; + uint16_t protocol; + uint8_t ip_summed; /* 2 bit only. */ + /* uint8_t */ + + /* "Scratch" area for layers to store metadata. */ + /* ??? I see sizeof() operations so probably an array. */ + uint8_t cb[64] __aligned(CACHE_LINE_SIZE); + + struct skb_shared_info *shinfo __aligned(CACHE_LINE_SIZE); + + uint32_t truesize; /* The total size of all buffers, incl. frags. */ + uint32_t priority; + uint16_t qmap; /* queue mapping */ + uint16_t _flags; /* Internal flags. */ +#define _SKB_FLAGS_SKBEXTFRAG 0x0001 + uint16_t l3hdroff; /* network header offset from *head */ + uint16_t l4hdroff; /* transport header offset from *head */ + uint16_t mac_header; /* offset of mac_header */ + uint16_t mac_len; /* Link-layer header length. */ + enum sk_buff_pkt_type pkt_type; + refcount_t refcnt; + + struct net_device *dev; + void *sk; /* XXX net/sock.h? */ + + /* FreeBSD specific bandaid (see linuxkpi_kfree_skb). */ + void *m; + void(*m_free_func)(void *); + + /* Force padding to CACHE_LINE_SIZE. */ + uint8_t __scratch[0] __aligned(CACHE_LINE_SIZE); +}; + +/* -------------------------------------------------------------------------- */ + +struct sk_buff *linuxkpi_alloc_skb(size_t, gfp_t); +struct sk_buff *linuxkpi_dev_alloc_skb(size_t, gfp_t); +struct sk_buff *linuxkpi_build_skb(void *, size_t); +void linuxkpi_kfree_skb(struct sk_buff *); + +struct sk_buff *linuxkpi_skb_copy(const struct sk_buff *, gfp_t); + +/* -------------------------------------------------------------------------- */ + +static inline struct sk_buff * +alloc_skb(size_t size, gfp_t gfp) +{ + struct sk_buff *skb; + + skb = linuxkpi_alloc_skb(size, gfp); + SKB_TRACE(skb); + return (skb); +} + +static inline struct sk_buff * +__dev_alloc_skb(size_t len, gfp_t gfp) +{ + struct sk_buff *skb; + + skb = linuxkpi_dev_alloc_skb(len, gfp); + SKB_IMPROVE(); + SKB_TRACE(skb); + return (skb); +} + +static inline struct sk_buff * +dev_alloc_skb(size_t len) +{ + struct sk_buff *skb; + + skb = __dev_alloc_skb(len, GFP_NOWAIT); + SKB_IMPROVE(); + SKB_TRACE(skb); + return (skb); +} + +static inline void +kfree_skb(struct sk_buff *skb) +{ + SKB_TRACE(skb); + linuxkpi_kfree_skb(skb); +} + +static inline void +consume_skb(struct sk_buff *skb) +{ + SKB_TRACE(skb); + kfree_skb(skb); +} + +static inline void +dev_kfree_skb(struct sk_buff *skb) +{ + SKB_TRACE(skb); + kfree_skb(skb); +} + +static inline void +dev_kfree_skb_any(struct sk_buff *skb) +{ + SKB_TRACE(skb); + dev_kfree_skb(skb); +} + +static inline void +dev_kfree_skb_irq(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_IMPROVE("Do we have to defer this?"); + dev_kfree_skb(skb); +} + +static inline struct sk_buff * +build_skb(void *data, unsigned int fragsz) +{ + struct sk_buff *skb; + + skb = linuxkpi_build_skb(data, fragsz); + SKB_TRACE(skb); + return (skb); +} + +/* -------------------------------------------------------------------------- */ + +static inline bool +skb_is_nonlinear(struct sk_buff *skb) +{ + SKB_TRACE(skb); + return ((skb->data_len > 0) ? true : false); +} + +/* Add headroom; cannot do once there is data in there. */ +static inline void +skb_reserve(struct sk_buff *skb, size_t len) +{ + SKB_TRACE(skb); +#if 0 + /* Apparently it is allowed to call skb_reserve multiple times in a row. */ + KASSERT(skb->data == skb->head, ("%s: skb %p not empty head %p data %p " + "tail %p\n", __func__, skb, skb->head, skb->data, skb->tail)); +#else + KASSERT(skb->len == 0 && skb->data == skb->tail, ("%s: skb %p not " + "empty head %p data %p tail %p len %u\n", __func__, skb, + skb->head, skb->data, skb->tail, skb->len)); +#endif + skb->data += len; + skb->tail += len; +} + +/* + * Remove headroom; return new data pointer; basically make space at the + * front to copy data in (manually). + */ +static inline void * +__skb_push(struct sk_buff *skb, size_t len) +{ + SKB_TRACE(skb); + KASSERT(((skb->data - len) >= skb->head), ("%s: skb %p (data %p - " + "len %zu) < head %p\n", __func__, skb, skb->data, len, skb->data)); + skb->len += len; + skb->data -= len; + return (skb->data); +} + +static inline void * +skb_push(struct sk_buff *skb, size_t len) +{ + + SKB_TRACE(skb); + return (__skb_push(skb, len)); +} + +/* + * Length of the data on the skb (without any frags)??? + */ +static inline size_t +skb_headlen(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + return (skb->len - skb->data_len); +} + + +/* Return the end of data (tail pointer). */ +static inline uint8_t * +skb_tail_pointer(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + return (skb->tail); +} + +/* Return number of bytes available at end of buffer. */ +static inline unsigned int +skb_tailroom(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + KASSERT((skb->end - skb->tail) >= 0, ("%s: skb %p tailroom < 0, " + "end %p tail %p\n", __func__, skb, skb->end, skb->tail)); + if (unlikely(skb_is_nonlinear(skb))) + return (0); + return (skb->end - skb->tail); +} + +/* Return number of bytes available at the beginning of buffer. */ +static inline unsigned int +skb_headroom(const struct sk_buff *skb) +{ + SKB_TRACE(skb); + KASSERT((skb->data - skb->head) >= 0, ("%s: skb %p headroom < 0, " + "data %p head %p\n", __func__, skb, skb->data, skb->head)); + return (skb->data - skb->head); +} + + +/* + * Remove tailroom; return the old tail pointer; basically make space at + * the end to copy data in (manually). See also skb_put_data() below. + */ +static inline void * +__skb_put(struct sk_buff *skb, size_t len) +{ + void *s; + + SKB_TRACE(skb); + KASSERT(((skb->tail + len) <= skb->end), ("%s: skb %p (tail %p + " + "len %zu) > end %p, head %p data %p len %u\n", __func__, + skb, skb->tail, len, skb->end, skb->head, skb->data, skb->len)); + + s = skb_tail_pointer(skb); + if (len == 0) + return (s); + skb->tail += len; + skb->len += len; +#ifdef SKB_DEBUG + if (linuxkpi_debug_skb & DSKB_TRACEX) + printf("%s: skb %p (%u) head %p data %p tail %p end %p, s %p len %zu\n", + __func__, skb, skb->len, skb->head, skb->data, skb->tail, skb->end, + s, len); +#endif + return (s); +} + +static inline void * +skb_put(struct sk_buff *skb, size_t len) +{ + + SKB_TRACE(skb); + return (__skb_put(skb, len)); +} + +/* skb_put() + copying data in. */ +static inline void * +skb_put_data(struct sk_buff *skb, const void *buf, size_t len) +{ + void *s; + + SKB_TRACE2(skb, buf); + s = skb_put(skb, len); + if (len == 0) + return (s); + memcpy(s, buf, len); + return (s); +} + +/* skb_put() + filling with zeros. */ +static inline void * +skb_put_zero(struct sk_buff *skb, size_t len) +{ + void *s; + + SKB_TRACE(skb); + s = skb_put(skb, len); + memset(s, '\0', len); + return (s); +} + +/* + * Remove len bytes from beginning of data. + * + * XXX-BZ ath10k checks for !NULL conditions so I assume this doesn't panic; + * we return the advanced data pointer so we don't have to keep a temp, correct? + */ +static inline void * +skb_pull(struct sk_buff *skb, size_t len) +{ + + SKB_TRACE(skb); +#if 0 /* Apparently this doesn't barf... */ + KASSERT(skb->len >= len, ("%s: skb %p skb->len %u < len %u, data %p\n", + __func__, skb, skb->len, len, skb->data)); +#endif + if (skb->len < len) + return (NULL); + skb->len -= len; + skb->data += len; + return (skb->data); +} + +/* Reduce skb data to given length or do nothing if smaller already. */ +static inline void +__skb_trim(struct sk_buff *skb, unsigned int len) +{ + + SKB_TRACE(skb); + if (skb->len < len) + return; + + skb->len = len; + skb->tail = skb->data + skb->len; +} + +static inline void +skb_trim(struct sk_buff *skb, unsigned int len) +{ + + return (__skb_trim(skb, len)); +} + +static inline struct skb_shared_info * +skb_shinfo(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + return (skb->shinfo); +} + +static inline void +skb_add_rx_frag(struct sk_buff *skb, int fragno, struct page *page, + off_t offset, size_t size, unsigned int truesize) +{ + struct skb_shared_info *shinfo; + + SKB_TRACE(skb); +#ifdef SKB_DEBUG + if (linuxkpi_debug_skb & DSKB_TRACEX) + printf("%s: skb %p head %p data %p tail %p end %p len %u fragno %d " + "page %#jx offset %ju size %zu truesize %u\n", __func__, + skb, skb->head, skb->data, skb->tail, skb->end, skb->len, fragno, + (uintmax_t)(uintptr_t)linux_page_address(page), (uintmax_t)offset, + size, truesize); +#endif + + shinfo = skb_shinfo(skb); + KASSERT(fragno >= 0 && fragno < nitems(shinfo->frags), ("%s: skb %p " + "fragno %d too big\n", __func__, skb, fragno)); + shinfo->frags[fragno].page = page; + shinfo->frags[fragno].offset = offset; + shinfo->frags[fragno].size = size; + shinfo->nr_frags = fragno + 1; + skb->len += size; + skb->data_len += size; + skb->truesize += truesize; +} + +/* -------------------------------------------------------------------------- */ + +#define skb_queue_walk(_q, skb) \ + for ((skb) = (_q)->next; (skb) != (struct sk_buff *)(_q); \ + (skb) = (skb)->next) + +#define skb_queue_walk_safe(_q, skb, tmp) \ + for ((skb) = (_q)->next, (tmp) = (skb)->next; \ + (skb) != (struct sk_buff *)(_q); (skb) = (tmp), (tmp) = (skb)->next) + +#define skb_list_walk_safe(_q, skb, tmp) \ + for ((skb) = (_q), (tmp) = ((skb) != NULL) ? (skb)->next ? NULL; \ + ((skb) != NULL); \ + (skb) = (tmp), (tmp) = ((skb) != NULL) ? (skb)->next ? NULL) + +static inline bool +skb_queue_empty(const struct sk_buff_head *q) +{ + SKB_TRACE(q); + return (q->next == (const struct sk_buff *)q); +} + +static inline bool +skb_queue_empty_lockless(const struct sk_buff_head *q) +{ + SKB_TRACE(q); + return (READ_ONCE(q->next) == (const struct sk_buff *)q); +} + +static inline void +__skb_queue_head_init(struct sk_buff_head *q) +{ + SKB_TRACE(q); + q->prev = q->next = (struct sk_buff *)q; + q->qlen = 0; +} + +static inline void +skb_queue_head_init(struct sk_buff_head *q) +{ + SKB_TRACE(q); + __skb_queue_head_init(q); + spin_lock_init(&q->lock); +} + +static inline void +__skb_insert(struct sk_buff *new, struct sk_buff *prev, struct sk_buff *next, + struct sk_buff_head *q) +{ + + SKB_TRACE_FMT(new, "prev %p next %p q %p", prev, next, q); + WRITE_ONCE(new->prev, prev); + WRITE_ONCE(new->next, next); + WRITE_ONCE(((struct sk_buff_head_l *)next)->prev, new); + WRITE_ONCE(((struct sk_buff_head_l *)prev)->next, new); + WRITE_ONCE(q->qlen, q->qlen + 1); +} + +static inline void +__skb_queue_after(struct sk_buff_head *q, struct sk_buff *skb, + struct sk_buff *new) +{ + + SKB_TRACE_FMT(q, "skb %p new %p", skb, new); + __skb_insert(new, skb, ((struct sk_buff_head_l *)skb)->next, q); +} + +static inline void +__skb_queue_before(struct sk_buff_head *q, struct sk_buff *skb, + struct sk_buff *new) +{ + + SKB_TRACE_FMT(q, "skb %p new %p", skb, new); + __skb_insert(new, skb->prev, skb, q); +} + +static inline void +__skb_queue_tail(struct sk_buff_head *q, struct sk_buff *new) +{ + + SKB_TRACE2(q, new); + __skb_queue_before(q, (struct sk_buff *)q, new); +} + +static inline void +skb_queue_tail(struct sk_buff_head *q, struct sk_buff *new) +{ + unsigned long flags; + + SKB_TRACE2(q, new); + spin_lock_irqsave(&q->lock, flags); + __skb_queue_tail(q, new); + spin_unlock_irqrestore(&q->lock, flags); +} + +static inline struct sk_buff * +skb_peek(const struct sk_buff_head *q) +{ + struct sk_buff *skb; + + skb = q->next; + SKB_TRACE2(q, skb); + if (skb == (const struct sk_buff *)q) + return (NULL); + return (skb); +} + +static inline struct sk_buff * +skb_peek_tail(const struct sk_buff_head *q) +{ + struct sk_buff *skb; + + skb = READ_ONCE(q->prev); + SKB_TRACE2(q, skb); + if (skb == (const struct sk_buff *)q) + return (NULL); + return (skb); +} + +static inline void +__skb_unlink(struct sk_buff *skb, struct sk_buff_head *q) +{ + struct sk_buff *p, *n; + + SKB_TRACE2(skb, q); + + WRITE_ONCE(q->qlen, q->qlen - 1); + p = skb->prev; + n = skb->next; + WRITE_ONCE(n->prev, p); + WRITE_ONCE(p->next, n); + skb->prev = skb->next = NULL; +} + +static inline void +skb_unlink(struct sk_buff *skb, struct sk_buff_head *q) +{ + unsigned long flags; + + SKB_TRACE2(skb, q); + spin_lock_irqsave(&q->lock, flags); + __skb_unlink(skb, q); + spin_unlock_irqrestore(&q->lock, flags); +} + +static inline struct sk_buff * +__skb_dequeue(struct sk_buff_head *q) +{ + struct sk_buff *skb; + + skb = skb_peek(q); + if (skb != NULL) + __skb_unlink(skb, q); + SKB_TRACE2(q, skb); + return (skb); +} + +static inline struct sk_buff * +skb_dequeue(struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb = __skb_dequeue(q); + spin_unlock_irqrestore(&q->lock, flags); + SKB_TRACE2(q, skb); + return (skb); +} + +static inline struct sk_buff * +__skb_dequeue_tail(struct sk_buff_head *q) +{ + struct sk_buff *skb; + + skb = skb_peek_tail(q); + if (skb != NULL) + __skb_unlink(skb, q); + SKB_TRACE2(q, skb); + return (skb); +} + +static inline struct sk_buff * +skb_dequeue_tail(struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb = __skb_dequeue_tail(q); + spin_unlock_irqrestore(&q->lock, flags); + SKB_TRACE2(q, skb); + return (skb); +} + +static inline void +__skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb) +{ + + SKB_TRACE2(q, skb); + __skb_queue_after(q, (struct sk_buff *)q, skb); +} + +static inline void +skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb) +{ + unsigned long flags; + + SKB_TRACE2(q, skb); + spin_lock_irqsave(&q->lock, flags); + __skb_queue_head(q, skb); + spin_unlock_irqrestore(&q->lock, flags); +} + +static inline uint32_t +skb_queue_len(const struct sk_buff_head *q) +{ + + SKB_TRACE(q); + return (q->qlen); +} + +static inline uint32_t +skb_queue_len_lockless(const struct sk_buff_head *q) +{ + + SKB_TRACE(q); + return (READ_ONCE(q->qlen)); +} + +static inline void +___skb_queue_splice(const struct sk_buff_head *from, + struct sk_buff *p, struct sk_buff *n) +{ + struct sk_buff *b, *e; + + b = from->next; + e = from->prev; + + WRITE_ONCE(b->prev, p); + WRITE_ONCE(((struct sk_buff_head_l *)p)->next, b); + WRITE_ONCE(e->next, n); + WRITE_ONCE(((struct sk_buff_head_l *)n)->prev, e); +} + +static inline void +skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to) +{ + + SKB_TRACE2(from, to); + + if (skb_queue_empty(from)) + return; + + ___skb_queue_splice(from, (struct sk_buff *)to, to->next); + to->qlen += from->qlen; + __skb_queue_head_init(from); +} + +static inline void +skb_queue_splice_tail_init(struct sk_buff_head *from, struct sk_buff_head *to) +{ + + SKB_TRACE2(from, to); + + if (skb_queue_empty(from)) + return; + + ___skb_queue_splice(from, to->prev, (struct sk_buff *)to); + to->qlen += from->qlen; + __skb_queue_head_init(from); +} + + +static inline void +__skb_queue_purge(struct sk_buff_head *q) +{ + struct sk_buff *skb; + + SKB_TRACE(q); + while ((skb = __skb_dequeue(q)) != NULL) + kfree_skb(skb); + WARN_ONCE(skb_queue_len(q) != 0, "%s: queue %p not empty: %u", + __func__, q, skb_queue_len(q)); +} + +static inline void +skb_queue_purge(struct sk_buff_head *q) +{ + struct sk_buff_head _q; + unsigned long flags; + + SKB_TRACE(q); + + if (skb_queue_empty_lockless(q)) + return; + + __skb_queue_head_init(&_q); + spin_lock_irqsave(&q->lock, flags); + skb_queue_splice_init(q, &_q); + spin_unlock_irqrestore(&q->lock, flags); + __skb_queue_purge(&_q); +} + +static inline struct sk_buff * +skb_queue_prev(struct sk_buff_head *q, struct sk_buff *skb) +{ + + SKB_TRACE2(q, skb); + /* XXX what is the q argument good for? */ + return (skb->prev); +} + +/* -------------------------------------------------------------------------- */ + +static inline struct sk_buff * +skb_copy(const struct sk_buff *skb, gfp_t gfp) +{ + struct sk_buff *new; + + new = linuxkpi_skb_copy(skb, gfp); + SKB_TRACE2(skb, new); + return (new); +} + +static inline uint16_t +skb_checksum(struct sk_buff *skb, int offs, size_t len, int x) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (0xffff); +} + +static inline int +skb_checksum_start_offset(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (-1); +} + +static inline dma_addr_t +skb_frag_dma_map(struct device *dev, const skb_frag_t *frag, int x, + size_t fragsz, enum dma_data_direction dir) +{ + SKB_TRACE2(frag, dev); + SKB_TODO(); + return (-1); +} + +static inline size_t +skb_frag_size(const skb_frag_t *frag) +{ + SKB_TRACE(frag); + return (frag->size); +} + +#define skb_walk_frags(_skb, _frag) \ + for ((_frag) = (_skb); false; (_frag)++) + +static inline void +skb_checksum_help(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); +} + +static inline bool +skb_ensure_writable(struct sk_buff *skb, size_t off) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (false); +} + +static inline void * +skb_frag_address(const skb_frag_t *frag) +{ + SKB_TRACE(frag); + return (page_address(frag->page + frag->offset)); +} + +static inline void +skb_free_frag(void *frag) +{ + + page_frag_free(frag); +} + +static inline struct sk_buff * +skb_gso_segment(struct sk_buff *skb, netdev_features_t netdev_flags) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (NULL); +} + +static inline bool +skb_is_gso(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_IMPROVE("Really a TODO but get it away from logging"); + return (false); +} + +static inline void +skb_mark_not_on_list(struct sk_buff *skb) +{ + SKB_TRACE(skb); + skb->next = NULL; +} + +static inline void +skb_reset_transport_header(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + skb->l4hdroff = skb->data - skb->head; +} + +static inline uint8_t * +skb_transport_header(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + return (skb->head + skb->l4hdroff); +} + +static inline uint8_t * +skb_network_header(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + return (skb->head + skb->l3hdroff); +} + +static inline int +__skb_linearize(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (-ENXIO); +} + +static inline int +skb_linearize(struct sk_buff *skb) +{ + return (skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0); +} + +static inline int +pskb_expand_head(struct sk_buff *skb, int x, int len, gfp_t gfp) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (-ENXIO); +} + +/* Not really seen this one but need it as symmetric accessor function. */ +static inline void +skb_set_queue_mapping(struct sk_buff *skb, uint16_t qmap) +{ + + SKB_TRACE_FMT(skb, "qmap %u", qmap); + skb->qmap = qmap; +} + +static inline uint16_t +skb_get_queue_mapping(struct sk_buff *skb) +{ + + SKB_TRACE_FMT(skb, "qmap %u", skb->qmap); + return (skb->qmap); +} + +static inline void +skb_copy_header(struct sk_buff *to, const struct sk_buff *from) +{ + SKB_TRACE2(to, from); + SKB_TODO(); +} + +static inline bool +skb_header_cloned(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (true); +} + +static inline uint8_t * +skb_mac_header(const struct sk_buff *skb) +{ + SKB_TRACE(skb); + return (skb->head + skb->mac_header); +} + +static inline void +skb_reset_mac_header(struct sk_buff *skb) +{ + SKB_TRACE(skb); + skb->mac_header = skb->data - skb->head; +} + +static inline void +skb_set_mac_header(struct sk_buff *skb, const size_t len) +{ + SKB_TRACE(skb); + skb_reset_mac_header(skb); + skb->mac_header += len; +} + +static inline struct skb_shared_hwtstamps * +skb_hwtstamps(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (NULL); +} + +static inline void +skb_orphan(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); +} + +static inline __wsum +csum_unfold(__sum16 sum) +{ + return (sum); +} + +static __inline void +skb_postpush_rcsum(struct sk_buff *skb, const void *data, size_t len) +{ + SKB_TODO(); +} + +static inline void +skb_reset_tail_pointer(struct sk_buff *skb) +{ + + SKB_TRACE(skb); +#ifdef SKB_DOING_OFFSETS_US_NOT + skb->tail = (uint8_t *)(uintptr_t)(skb->data - skb->head); +#endif + skb->tail = skb->data; + SKB_TRACE(skb); +} + +static inline struct sk_buff * +skb_get(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + refcount_inc(&skb->refcnt); + return (skb); +} + +static inline struct sk_buff * +skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) +{ + + SKB_TODO(); + return (NULL); +} + +static inline void +skb_copy_from_linear_data(const struct sk_buff *skb, void *dst, size_t len) +{ + + SKB_TRACE(skb); + /* Let us just hope the destination has len space ... */ + memcpy(dst, skb->data, len); +} + +static inline int +skb_pad(struct sk_buff *skb, int pad) +{ + + SKB_TRACE(skb); + SKB_TODO(); + return (-1); +} + +static inline void +skb_list_del_init(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + __list_del_entry(&skb->list); + skb_mark_not_on_list(skb); +} + +static inline void +napi_consume_skb(struct sk_buff *skb, int budget) +{ + + SKB_TRACE(skb); + SKB_TODO(); +} + +static inline struct sk_buff * +napi_build_skb(void *data, size_t len) +{ + + SKB_TODO(); + return (NULL); +} + +static inline uint32_t +skb_get_hash(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (0); +} + +static inline void +skb_mark_for_recycle(struct sk_buff *skb) +{ + SKB_TRACE(skb); + /* page_pool */ + SKB_TODO(); +} + +static inline int +skb_cow_head(struct sk_buff *skb, unsigned int headroom) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (-1); +} + +/* Misplaced here really but sock comes from skbuff. */ +#define sk_pacing_shift_update(sock, n) + +#define SKB_WITH_OVERHEAD(_s) \ + (_s) - ALIGN(sizeof(struct skb_shared_info), CACHE_LINE_SIZE) + +#endif /* _LINUXKPI_LINUX_SKBUFF_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h index ecd39d711eb4..0e649e1e3c4a 100644 --- a/sys/compat/linuxkpi/common/include/linux/slab.h +++ b/sys/compat/linuxkpi/common/include/linux/slab.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2021 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2024-2025 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,11 +29,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SLAB_H_ -#define _LINUX_SLAB_H_ +#ifndef _LINUXKPI_LINUX_SLAB_H_ +#define _LINUXKPI_LINUX_SLAB_H_ #include <sys/types.h> #include <sys/malloc.h> @@ -38,23 +40,25 @@ #include <linux/compat.h> #include <linux/types.h> #include <linux/gfp.h> +#include <linux/err.h> #include <linux/llist.h> +#include <linux/overflow.h> +#include <linux/cleanup.h> MALLOC_DECLARE(M_KMALLOC); -#define kvmalloc(size, flags) kmalloc(size, flags) -#define kvzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO) +#define kvzalloc(size, flags) kvmalloc(size, (flags) | __GFP_ZERO) #define kvcalloc(n, size, flags) kvmalloc_array(n, size, (flags) | __GFP_ZERO) #define kzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO) #define kzalloc_node(size, flags, node) kmalloc_node(size, (flags) | __GFP_ZERO, node) #define kfree_const(ptr) kfree(ptr) +#define kfree_async(ptr) kfree(ptr) /* drm-kmod 5.4 compat */ #define vzalloc(size) __vmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 0) #define vfree(arg) kfree(arg) #define kvfree(arg) kfree(arg) #define vmalloc_node(size, node) __vmalloc_node(size, GFP_KERNEL, node) #define vmalloc_user(size) __vmalloc(size, GFP_KERNEL | __GFP_ZERO, 0) #define vmalloc(size) __vmalloc(size, GFP_KERNEL, 0) -#define __kmalloc(...) kmalloc(__VA_ARGS__) /* * Prefix some functions with linux_ to avoid namespace conflict @@ -66,6 +70,7 @@ MALLOC_DECLARE(M_KMALLOC); #define kmem_cache_zalloc(...) lkpi_kmem_cache_zalloc(__VA_ARGS__) #define kmem_cache_free(...) lkpi_kmem_cache_free(__VA_ARGS__) #define kmem_cache_destroy(...) linux_kmem_cache_destroy(__VA_ARGS__) +#define kmem_cache_shrink(x) (0) #define KMEM_CACHE(__struct, flags) \ linux_kmem_cache_create(#__struct, sizeof(struct __struct), \ @@ -85,18 +90,22 @@ struct linux_kmem_cache; #define ARCH_KMALLOC_MINALIGN \ __alignof(unsigned long long) -/* - * Critical section-friendly version of kfree(). - * Requires knowledge of the allocation size at build time. - */ -#define kfree_async(ptr) do { \ - _Static_assert(sizeof(*(ptr)) >= sizeof(struct llist_node), \ - "Size of object to free is unknown or too small"); \ - if (curthread->td_critnest != 0) \ - linux_kfree_async(ptr); \ - else \ - kfree(ptr); \ -} while (0) +#define ZERO_SIZE_PTR ((void *)16) +#define ZERO_OR_NULL_PTR(x) ((x) == NULL || (x) == ZERO_SIZE_PTR) + +struct linux_kmem_cache *linux_kmem_cache_create(const char *name, + size_t size, size_t align, unsigned flags, linux_kmem_ctor_t *ctor); +void *lkpi_kmem_cache_alloc(struct linux_kmem_cache *, gfp_t); +void *lkpi_kmem_cache_zalloc(struct linux_kmem_cache *, gfp_t); +void lkpi_kmem_cache_free(struct linux_kmem_cache *, void *); +void linux_kmem_cache_destroy(struct linux_kmem_cache *); + +void *lkpi_kmalloc(size_t, gfp_t); +void *lkpi_kvmalloc(size_t, gfp_t); +void *lkpi___kmalloc(size_t, gfp_t); +void *lkpi___kmalloc_node(size_t, gfp_t, int); +void *lkpi_krealloc(void *, size_t, gfp_t); +void lkpi_kfree(const void *); static inline gfp_t linux_check_m_flags(gfp_t flags) @@ -113,34 +122,91 @@ linux_check_m_flags(gfp_t flags) return (flags & GFP_NATIVE_MASK); } +/* + * Base functions with a native implementation. + */ static inline void * kmalloc(size_t size, gfp_t flags) { - return (malloc(size, M_KMALLOC, linux_check_m_flags(flags))); + return (lkpi_kmalloc(size, flags)); +} + +static inline void * +__kmalloc(size_t size, gfp_t flags) +{ + return (lkpi___kmalloc(size, flags)); } static inline void * kmalloc_node(size_t size, gfp_t flags, int node) { - return (malloc_domainset(size, M_KMALLOC, - linux_get_vm_domain_set(node), linux_check_m_flags(flags))); + return (lkpi___kmalloc_node(size, flags, node)); +} + +static inline void * +krealloc(void *ptr, size_t size, gfp_t flags) +{ + return (lkpi_krealloc(ptr, size, flags)); +} + +static inline void +kfree(const void *ptr) +{ + lkpi_kfree(ptr); +} + +DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T)) + +/* + * Other k*alloc() funtions using the above as underlying allocator. + */ +/* kmalloc */ +static inline void * +kmalloc_array(size_t n, size_t size, gfp_t flags) +{ + if (WOULD_OVERFLOW(n, size)) + panic("%s: %zu * %zu overflowed", __func__, n, size); + + return (kmalloc(size * n, flags)); } static inline void * kcalloc(size_t n, size_t size, gfp_t flags) { flags |= __GFP_ZERO; - return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); + return (kmalloc_array(n, size, flags)); +} + +/* kmalloc_node */ +static inline void * +kmalloc_array_node(size_t n, size_t size, gfp_t flags, int node) +{ + if (WOULD_OVERFLOW(n, size)) + panic("%s: %zu * %zu overflowed", __func__, n, size); + + return (kmalloc_node(size * n, flags, node)); } static inline void * kcalloc_node(size_t n, size_t size, gfp_t flags, int node) { flags |= __GFP_ZERO; - return (mallocarray_domainset(n, size, M_KMALLOC, - linux_get_vm_domain_set(node), linux_check_m_flags(flags))); + return (kmalloc_array_node(n, size, flags, node)); +} + +/* krealloc */ +static inline void * +krealloc_array(void *ptr, size_t n, size_t size, gfp_t flags) +{ + if (WOULD_OVERFLOW(n, size)) + return NULL; + + return (krealloc(ptr, n * size, flags)); } +/* + * vmalloc/kvalloc functions. + */ static inline void * __vmalloc(size_t size, gfp_t flags, int other) { @@ -160,40 +226,49 @@ vmalloc_32(size_t size) return (contigmalloc(size, M_KMALLOC, M_WAITOK, 0, UINT_MAX, 1, 1)); } +/* May return non-contiguous memory. */ static inline void * -kmalloc_array(size_t n, size_t size, gfp_t flags) -{ - return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); -} - -static inline void * -kmalloc_array_node(size_t n, size_t size, gfp_t flags, int node) +kvmalloc(size_t size, gfp_t flags) { - return (mallocarray_domainset(n, size, M_KMALLOC, - linux_get_vm_domain_set(node), linux_check_m_flags(flags))); + return (lkpi_kvmalloc(size, flags)); } static inline void * kvmalloc_array(size_t n, size_t size, gfp_t flags) { - return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); + if (WOULD_OVERFLOW(n, size)) + panic("%s: %zu * %zu overflowed", __func__, n, size); + + return (kvmalloc(size * n, flags)); } static inline void * -krealloc(void *ptr, size_t size, gfp_t flags) +kvrealloc(const void *ptr, size_t oldsize, size_t newsize, gfp_t flags) { - return (realloc(ptr, size, M_KMALLOC, linux_check_m_flags(flags))); -} + void *newptr; -static inline void -kfree(const void *ptr) -{ - free(__DECONST(void *, ptr), M_KMALLOC); + if (newsize <= oldsize) + return (__DECONST(void *, ptr)); + + newptr = kvmalloc(newsize, flags); + if (newptr != NULL) { + memcpy(newptr, ptr, oldsize); + kvfree(ptr); + } + + return (newptr); } +/* + * Misc. + */ + static __inline void kfree_sensitive(const void *ptr) { + if (ZERO_OR_NULL_PTR(ptr)) + return; + zfree(__DECONST(void *, ptr), M_KMALLOC); } @@ -203,12 +278,12 @@ ksize(const void *ptr) return (malloc_usable_size(ptr)); } -extern struct linux_kmem_cache *linux_kmem_cache_create(const char *name, - size_t size, size_t align, unsigned flags, linux_kmem_ctor_t *ctor); -extern void *lkpi_kmem_cache_alloc(struct linux_kmem_cache *, gfp_t); -extern void *lkpi_kmem_cache_zalloc(struct linux_kmem_cache *, gfp_t); -extern void lkpi_kmem_cache_free(struct linux_kmem_cache *, void *); -extern void linux_kmem_cache_destroy(struct linux_kmem_cache *); -void linux_kfree_async(void *); +static inline size_t +kmalloc_size_roundup(size_t size) +{ + if (unlikely(size == 0 || size == SIZE_MAX)) + return (size); + return (malloc_size(size)); +} -#endif /* _LINUX_SLAB_H_ */ +#endif /* _LINUXKPI_LINUX_SLAB_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/smp.h b/sys/compat/linuxkpi/common/include/linux/smp.h index 3f5684015547..b057953e6282 100644 --- a/sys/compat/linuxkpi/common/include/linux/smp.h +++ b/sys/compat/linuxkpi/common/include/linux/smp.h @@ -22,13 +22,25 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SMP_H_ -#define _LINUX_SMP_H_ +#ifndef _LINUXKPI_LINUX_SMP_H_ +#define _LINUXKPI_LINUX_SMP_H_ + +#include <asm/smp.h> +/* + * Important note about the use of the function provided below: + * + * The callback function passed to on_each_cpu() is called from a + * so-called critical section, and if you need a mutex you will have + * to rewrite the code to use native FreeBSD mtx spinlocks instead of + * the spinlocks provided by the LinuxKPI! Be very careful to not call + * any LinuxKPI functions inside the on_each_cpu()'s callback + * function, because they may sleep, unlike in native Linux. + * + * Enabling witness(4) when testing, can catch such issues. + */ #define on_each_cpu(cb, data, wait) ({ \ CTASSERT(wait); \ linux_on_each_cpu(cb, data); \ @@ -36,4 +48,4 @@ extern int linux_on_each_cpu(void (*)(void *), void *); -#endif /* _LINUX_SMP_H_ */ +#endif /* _LINUXKPI_LINUX_SMP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h b/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h new file mode 100644 index 000000000000..9f3a1ee4c139 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2022-2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H +#define _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H + +#include <linux/kernel.h> /* pr_debug */ + +struct mtk_wed_device { +}; + +#define WED_WO_STA_REC 0x6 + +#define mtk_wed_device_start(_dev, _mask) do { pr_debug("%s: TODO\n", __func__); } while(0) +#define mtk_wed_device_detach(_dev) do { pr_debug("%s: TODO\n", __func__); } while(0) +#define mtk_wed_device_irq_get(_dev, _mask) 0 +#define mtk_wed_device_irq_set_mask(_dev, _mask) do { pr_debug("%s: TODO\n", __func__); } while(0) +#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) ({ pr_debug("%s: TODO\n", __func__); -ENODEV; }) +#define mtk_wed_device_dma_reset(_dev) do { pr_debug("%s: TODO\n", __func__); } while (0) +#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _entry) \ + do { pr_debug("%s: TODO\n", __func__); } while (0) +#define mtk_wed_device_stop(_dev) do { pr_debug("%s: TODO\n", __func__); } while(0) +#define mtk_wed_device_start_hw_rro(_dev, _mask, _b) do { pr_debug("%s: TODO\n", __func__); } while(0) +#define mtk_wed_device_setup_tc(_dev, _ndev, _type, _tdata) ({ pr_debug("%s: TODO\n", __func__); -EOPNOTSUPP; }) + +static inline bool +mtk_wed_device_active(struct mtk_wed_device *dev __unused) +{ + + pr_debug("%s: TODO\n", __func__); + return (false); +} + +static inline bool +mtk_wed_get_rx_capa(struct mtk_wed_device *dev __unused) +{ + + pr_debug("%s: TODO\n", __func__); + return (false); +} + +#endif /* _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/soc/qcom/qmi.h b/sys/compat/linuxkpi/common/include/linux/soc/qcom/qmi.h new file mode 100644 index 000000000000..647eaf271d87 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/soc/qcom/qmi.h @@ -0,0 +1,173 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_SOC_QCOM_QMI_H +#define _LINUXKPI_LINUX_SOC_QCOM_QMI_H + +/* QMI (Qualcomm MSM Interface) */ + +#include <linux/qrtr.h> + +enum soc_qcom_qmi_data_type { + QMI_EOTI, + QMI_DATA_LEN, + QMI_OPT_FLAG, + QMI_UNSIGNED_1_BYTE, + QMI_UNSIGNED_2_BYTE, + QMI_UNSIGNED_4_BYTE, + QMI_UNSIGNED_8_BYTE, + QMI_SIGNED_4_BYTE_ENUM, + QMI_STRUCT, + QMI_STRING, +}; + +#define QMI_RESULT_SUCCESS_V01 __LINE__ +#define QMI_INDICATION __LINE__ + +struct qmi_handle; + +enum soc_qcom_qmi_array_type { + NO_ARRAY, + STATIC_ARRAY, + VAR_LEN_ARRAY, +}; + +/* Should this become an enum? */ +#define QMI_COMMON_TLV_TYPE 0 + +struct qmi_elem_info { + enum soc_qcom_qmi_data_type data_type; + uint32_t elem_len; + uint32_t elem_size; + enum soc_qcom_qmi_array_type array_type; + uint8_t tlv_type; + uint32_t offset; + const struct qmi_elem_info *ei_array; +}; + +struct qmi_response_type_v01 { + uint16_t result; + uint16_t error; +}; + +struct qmi_txn { +}; + +struct qmi_service { + uint32_t node; + uint32_t port; +}; + +struct qmi_msg_handler { + uint32_t type; + uint32_t msg_id; + const struct qmi_elem_info *ei; + size_t decoded_size; + void (*fn)(struct qmi_handle *, struct sockaddr_qrtr *, struct qmi_txn *, const void *); +}; + +struct qmi_ops { + int (*new_server)(struct qmi_handle *, struct qmi_service *); + void (*del_server)(struct qmi_handle *, struct qmi_service *); +}; + +struct qmi_handle { + int sock; + + const struct qmi_msg_handler *handler; + struct qmi_ops ops; +}; + + +/* XXX-TODO need implementation somewhere... it is not in ath1xk* */ +extern struct qmi_elem_info qmi_response_type_v01_ei[]; + +static inline int +qmi_handle_init(struct qmi_handle *handle, size_t resp_len_max, + const struct qmi_ops *ops, const struct qmi_msg_handler *handler) +{ + + handle->handler = handler; + if (ops != NULL) + handle->ops = *ops; + + /* We will find out what else to do here. */ + /* XXX TODO */ + + return (0); +} + +static __inline int +qmi_add_lookup(struct qmi_handle *handle, uint32_t service, uint32_t version, + uint32_t service_ins_id) +{ + + /* XXX TODO */ + return (0); +} + +static __inline void +qmi_handle_release(struct qmi_handle *handle) +{ + + /* XXX TODO */ +} + +static __inline int +qmi_send_request(struct qmi_handle *handle, void *x, struct qmi_txn *txn, + uint32_t msd_id, size_t len, const struct qmi_elem_info *ei, void *req) +{ + + /* XXX TODO */ + return (-ENXIO); +} + +static __inline void +qmi_txn_cancel(struct qmi_txn *txn) +{ + + /* XXX TODO */ +} + +static __inline int +qmi_txn_init(struct qmi_handle *handle, struct qmi_txn *txn, + const struct qmi_elem_info *ei, void *resp) +{ + + /* XXX TODO */ + return (-ENXIO); +} + +static __inline int +qmi_txn_wait(struct qmi_txn *txn, uint64_t jiffies) +{ + + /* XXX TODO */ + return (-ENXIO); +} + +#endif /* _LINUXKPI_LINUX_SOC_QCOM_QMI_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/socket.h b/sys/compat/linuxkpi/common/include/linux/socket.h index a9a952e4ffd8..638ee058c2f5 100644 --- a/sys/compat/linuxkpi/common/include/linux/socket.h +++ b/sys/compat/linuxkpi/common/include/linux/socket.h @@ -25,14 +25,23 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SOCKET_H_ -#define _LINUX_SOCKET_H_ +#ifndef _LINUXKPI_LINUX_SOCKET_H_ +#define _LINUXKPI_LINUX_SOCKET_H_ #include <sys/socket.h> +#define AF_QIPCRTR 42 + +static inline int +kernel_connect(int sd, struct sockaddr *sa, size_t salen, int flags) +{ + + /* kern_connectat()? It is used for sockaddr_qrtr by ath1xk/qmi. */ + pr_debug("%s: TODO\n", __func__); + return (-EINVAL); +} + #ifdef notyet static inline int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len) @@ -66,4 +75,4 @@ memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len) } #endif -#endif /* _LINUX_SOCKET_H_ */ +#endif /* _LINUXKPI_LINUX_SOCKET_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/sort.h b/sys/compat/linuxkpi/common/include/linux/sort.h new file mode 100644 index 000000000000..e6196d1f41c7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/sort.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_SORT_H_ +#define _LINUXKPI_LINUX_SORT_H_ + +#include <linux/types.h> +#include <linux/kernel.h> + +#include <sys/libkern.h> + +#define sort(base, num, size, cmp, swap) do { \ + BUILD_BUG_ON_ZERO(swap); \ + qsort(base, num, size, cmp); \ +} while (0) + +#endif /* _LINUXKPI_LINUX_SORT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/spinlock.h b/sys/compat/linuxkpi/common/include/linux/spinlock.h index 56eaecfb4cd6..dc10b0457153 100644 --- a/sys/compat/linuxkpi/common/include/linux/spinlock.h +++ b/sys/compat/linuxkpi/common/include/linux/spinlock.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SPINLOCK_H_ -#define _LINUX_SPINLOCK_H_ +#ifndef _LINUXKPI_LINUX_SPINLOCK_H_ +#define _LINUXKPI_LINUX_SPINLOCK_H_ #include <asm/atomic.h> #include <sys/param.h> @@ -41,10 +39,9 @@ #include <linux/compiler.h> #include <linux/rwlock.h> #include <linux/bottom_half.h> +#include <linux/lockdep.h> -typedef struct { - struct mtx m; -} spinlock_t; +typedef struct mtx spinlock_t; /* * By defining CONFIG_SPIN_SKIP LinuxKPI spinlocks and asserts will be @@ -60,7 +57,7 @@ typedef struct { #define spin_lock(_l) do { \ if (SPIN_SKIP()) \ break; \ - mtx_lock(&(_l)->m); \ + mtx_lock(_l); \ local_bh_disable(); \ } while (0) @@ -77,7 +74,7 @@ typedef struct { if (SPIN_SKIP()) \ break; \ local_bh_enable(); \ - mtx_unlock(&(_l)->m); \ + mtx_unlock(_l); \ } while (0) #define spin_unlock_bh(_l) do { \ @@ -94,7 +91,7 @@ typedef struct { if (SPIN_SKIP()) { \ __ret = 1; \ } else { \ - __ret = mtx_trylock(&(_l)->m); \ + __ret = mtx_trylock(_l); \ if (likely(__ret != 0)) \ local_bh_disable(); \ } \ @@ -112,7 +109,7 @@ typedef struct { #define spin_lock_nested(_l, _n) do { \ if (SPIN_SKIP()) \ break; \ - mtx_lock_flags(&(_l)->m, MTX_DUPOK); \ + mtx_lock_flags(_l, MTX_DUPOK); \ local_bh_disable(); \ } while (0) @@ -127,6 +124,7 @@ typedef struct { } while (0) #define spin_unlock_irqrestore(_l, flags) do { \ + (void)(flags); \ spin_unlock(_l); \ } while (0) @@ -141,31 +139,27 @@ typedef struct { #define _spin_lock_name(...) __spin_lock_name(__VA_ARGS__) #define spin_lock_name(name) _spin_lock_name(name, __FILE__, __LINE__) -#define spin_lock_init(lock) linux_spin_lock_init(lock, spin_lock_name("lnxspin")) - -static inline void -linux_spin_lock_init(spinlock_t *lock, const char *name) -{ +#define spin_lock_init(lock) mtx_init(lock, spin_lock_name("lnxspin"), \ + NULL, MTX_DEF | MTX_NOWITNESS | MTX_NEW) - memset(lock, 0, sizeof(*lock)); - mtx_init(&lock->m, name, NULL, MTX_DEF | MTX_NOWITNESS); -} - -static inline void -spin_lock_destroy(spinlock_t *lock) -{ - - mtx_destroy(&lock->m); -} +#define spin_lock_destroy(_l) mtx_destroy(_l) #define DEFINE_SPINLOCK(lock) \ spinlock_t lock; \ - MTX_SYSINIT(lock, &(lock).m, spin_lock_name("lnxspin"), MTX_DEF) + MTX_SYSINIT(lock, &lock, spin_lock_name("lnxspin"), MTX_DEF) #define assert_spin_locked(_l) do { \ if (SPIN_SKIP()) \ break; \ - mtx_assert(&(_l)->m, MA_OWNED); \ + mtx_assert(_l, MA_OWNED); \ +} while (0) + +#define local_irq_save(flags) do { \ + (flags) = 0; \ +} while (0) + +#define local_irq_restore(flags) do { \ + (void)(flags); \ } while (0) #define atomic_dec_and_lock_irqsave(cnt, lock, flags) \ @@ -184,4 +178,4 @@ _atomic_dec_and_lock_irqsave(atomic_t *cnt, spinlock_t *lock, return (0); } -#endif /* _LINUX_SPINLOCK_H_ */ +#endif /* _LINUXKPI_LINUX_SPINLOCK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/srcu.h b/sys/compat/linuxkpi/common/include/linux/srcu.h index 1de7e8acedb8..b42c28a1311b 100644 --- a/sys/compat/linuxkpi/common/include/linux/srcu.h +++ b/sys/compat/linuxkpi/common/include/linux/srcu.h @@ -22,12 +22,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SRCU_H_ -#define _LINUX_SRCU_H_ +#ifndef _LINUXKPI_LINUX_SRCU_H_ +#define _LINUXKPI_LINUX_SRCU_H_ #include <linux/compiler.h> @@ -53,4 +51,4 @@ extern void cleanup_srcu_struct(struct srcu_struct *); synchronize_srcu(srcu); \ } while (0) -#endif /* _LINUX_SRCU_H_ */ +#endif /* _LINUXKPI_LINUX_SRCU_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/stackdepot.h b/sys/compat/linuxkpi/common/include/linux/stackdepot.h new file mode 100644 index 000000000000..df223d46be6e --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/stackdepot.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_STACKDEPOT_H_ +#define _LINUXKPI_LINUX_STACKDEPOT_H_ + +typedef bool depot_stack_handle_t; + +#endif /* _LINUXKPI_LINUX_STACKDEPOT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/stdarg.h b/sys/compat/linuxkpi/common/include/linux/stdarg.h new file mode 100644 index 000000000000..698ac45e9198 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/stdarg.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_STDARG_H_ +#define _LINUXKPI_STDARG_H_ + +#include <sys/stdarg.h> + +#endif /* _LINUXKPI_STDARG_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/stddef.h b/sys/compat/linuxkpi/common/include/linux/stddef.h new file mode 100644 index 000000000000..d04a5a4bf516 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/stddef.h @@ -0,0 +1,31 @@ +/* Public domain */ + +#ifndef _LINUXKPI_LINUX_STDDEF_H_ +#define _LINUXKPI_LINUX_STDDEF_H_ + +#include <sys/stddef.h> + +/* + * FreeBSD has multiple (vendor) drivers containing copies of this + * and including LinuxKPI headers. Put the #defines behind guards. + */ + +#ifndef __struct_group +#define __struct_group(_tag, _name, _attrs, _members...) \ + union { \ + struct { _members } _attrs; \ + struct _tag { _members } _attrs _name; \ + } _attrs +#endif + +#ifndef struct_group +#define struct_group(_name, _members...) \ + __struct_group(/* no tag */, _name, /* no attrs */, _members) +#endif + +#ifndef struct_group_tagged +#define struct_group_tagged(_tag, _name, _members...) \ + __struct_group(_tag, _name, /* no attrs */, _members) +#endif + +#endif /* _LINUXKPI_LINUX_STDDEF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/string.h b/sys/compat/linuxkpi/common/include/linux/string.h index a757464bf02b..f7b64560d254 100644 --- a/sys/compat/linuxkpi/common/include/linux/string.h +++ b/sys/compat/linuxkpi/common/include/linux/string.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_STRING_H_ -#define _LINUX_STRING_H_ +#ifndef _LINUXKPI_LINUX_STRING_H_ +#define _LINUXKPI_LINUX_STRING_H_ #include <sys/ctype.h> @@ -38,6 +36,9 @@ #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/err.h> +#include <linux/bitops.h> /* for BITS_PER_LONG */ +#include <linux/overflow.h> +#include <linux/stdarg.h> #include <sys/libkern.h> @@ -97,6 +98,27 @@ kmemdup(const void *src, size_t len, gfp_t gfp) return (dst); } +/* See slab.h for kvmalloc/kvfree(). */ +static inline void * +kvmemdup(const void *src, size_t len, gfp_t gfp) +{ + void *dst; + + dst = kvmalloc(len, gfp); + if (dst != NULL) + memcpy(dst, src, len); + return (dst); +} + +static inline char * +strndup_user(const char __user *ustr, long n) +{ + if (n < 1) + return (ERR_PTR(-EINVAL)); + + return (memdup_user_nul(ustr, n - 1)); +} + static inline char * kstrdup(const char *string, gfp_t gfp) { @@ -139,6 +161,24 @@ skip_spaces(const char *str) return (__DECONST(char *, str)); } +/* + * This function trims whitespaces at the end of a string and returns a pointer + * to the first non-whitespace character. + */ +static inline char * +strim(char *str) +{ + char *end; + + end = str + strlen(str); + while (end >= str && (*end == '\0' || isspace(*end))) { + *end = '\0'; + end--; + } + + return (skip_spaces(str)); +} + static inline void * memchr_inv(const void *start, int c, size_t length) { @@ -196,4 +236,94 @@ strscpy(char* dst, const char* src, size_t len) return (-E2BIG); } -#endif /* _LINUX_STRING_H_ */ +static inline ssize_t +strscpy_pad(char* dst, const char* src, size_t len) +{ + + bzero(dst, len); + + return (strscpy(dst, src, len)); +} + +static inline char * +strnchr(const char *cp, size_t n, int ch) +{ + char *p; + + for (p = __DECONST(char *, cp); n--; ++p) { + if (*p == ch) + return (p); + if (*p == '\0') + break; + } + + return (NULL); +} + +static inline void * +memset32(uint32_t *b, uint32_t c, size_t len) +{ + uint32_t *dst = b; + + while (len--) + *dst++ = c; + return (b); +} + +static inline void * +memset64(uint64_t *b, uint64_t c, size_t len) +{ + uint64_t *dst = b; + + while (len--) + *dst++ = c; + return (b); +} + +static inline void * +memset_p(void **p, void *v, size_t n) +{ + + if (BITS_PER_LONG == 32) + return (memset32((uint32_t *)p, (uintptr_t)v, n)); + else + return (memset64((uint64_t *)p, (uintptr_t)v, n)); +} + +static inline void +memcpy_and_pad(void *dst, size_t dstlen, const void *src, size_t len, int ch) +{ + + if (len >= dstlen) { + memcpy(dst, src, dstlen); + } else { + memcpy(dst, src, len); + /* Pad with given padding character. */ + memset((char *)dst + len, ch, dstlen - len); + } +} + +#define memset_startat(ptr, bytepat, smember) \ +({ \ + uint8_t *_ptr = (uint8_t *)(ptr); \ + int _c = (int)(bytepat); \ + size_t _o = offsetof(typeof(*(ptr)), smember); \ + memset(_ptr + _o, _c, sizeof(*(ptr)) - _o); \ +}) + +#define memset_after(ptr, bytepat, smember) \ +({ \ + uint8_t *_ptr = (uint8_t *)(ptr); \ + int _c = (int)(bytepat); \ + size_t _o = offsetofend(typeof(*(ptr)), smember); \ + memset(_ptr + _o, _c, sizeof(*(ptr)) - _o); \ +}) + +static inline void +memzero_explicit(void *p, size_t s) +{ + memset(p, 0, s); + __asm__ __volatile__("": :"r"(p) :"memory"); +} + +#endif /* _LINUXKPI_LINUX_STRING_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/string_choices.h b/sys/compat/linuxkpi/common/include/linux/string_choices.h new file mode 100644 index 000000000000..74aa3fd019b2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/string_choices.h @@ -0,0 +1,71 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_STRING_CHOICES_H_ +#define _LINUXKPI_LINUX_STRING_CHOICES_H_ + +#include <sys/types.h> + +static inline const char * +str_yes_no(bool value) +{ + if (value) + return "yes"; + else + return "no"; +} + +static inline const char * +str_on_off(bool value) +{ + if (value) + return "on"; + else + return "off"; +} + +static inline const char * +str_enabled_disabled(bool value) +{ + if (value) + return "enabled"; + else + return "disabled"; +} + +static inline const char * +str_enable_disable(bool value) +{ + if (value) + return "enable"; + else + return "disable"; +} + +#define str_disable_enable(_v) str_enable_disable(!(_v)) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/string_helpers.h b/sys/compat/linuxkpi/common/include/linux/string_helpers.h new file mode 100644 index 000000000000..07d113c0cb21 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/string_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2025 The FreeBSD Foundation + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_STRING_HELPERS_H_ +#define _LINUXKPI_LINUX_STRING_HELPERS_H_ + +#include <linux/string_choices.h> + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/stringify.h b/sys/compat/linuxkpi/common/include/linux/stringify.h index 08fd0d909fae..9345bdc441aa 100644 --- a/sys/compat/linuxkpi/common/include/linux/stringify.h +++ b/sys/compat/linuxkpi/common/include/linux/stringify.h @@ -22,16 +22,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_STRINGIFY_H_ -#define __LKPI_LINUX_STRINGIFY_H_ +#ifndef _LINUXKPI_LINUX_STRINGIFY_H_ +#define _LINUXKPI_LINUX_STRINGIFY_H_ #include <sys/cdefs.h> #define ___stringify(...) #__VA_ARGS__ #define __stringify(...) ___stringify(__VA_ARGS__) -#endif /* __LKPI_LINUX_STRINGIFY_H_ */ +#endif /* _LINUXKPI_LINUX_STRINGIFY_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/suspend.h b/sys/compat/linuxkpi/common/include/linux/suspend.h new file mode 100644 index 000000000000..dacecbebdc08 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/suspend.h @@ -0,0 +1,23 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_SUSPEND_H_ +#define _LINUXKPI_LINUX_SUSPEND_H_ + +typedef int suspend_state_t; + +extern suspend_state_t pm_suspend_target_state; + +#define PM_SUSPEND_ON 0 +#define PM_SUSPEND_TO_IDLE 1 +#define PM_SUSPEND_STANDBY 2 +#define PM_SUSPEND_MEM 3 +#define PM_SUSPEND_MIN PM_SUSPEND_TO_IDLE +#define PM_SUSPEND_MAX 4 + +static inline int +pm_suspend_via_firmware(void) +{ + return 0; +} + +#endif /* _LINUXKPI_LINUX_SUSPEND_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/swap.h b/sys/compat/linuxkpi/common/include/linux/swap.h index 33f8de4721a4..5828db7ae392 100644 --- a/sys/compat/linuxkpi/common/include/linux/swap.h +++ b/sys/compat/linuxkpi/common/include/linux/swap.h @@ -22,16 +22,24 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SWAP_H_ -#define _LINUX_SWAP_H_ +#ifndef _LINUXKPI_LINUX_SWAP_H_ +#define _LINUXKPI_LINUX_SWAP_H_ + +#include <sys/param.h> +#include <sys/domainset.h> +#include <sys/queue.h> +#include <sys/proc.h> +#include <sys/pcpu.h> +#include <vm/vm.h> #include <vm/swap_pager.h> #include <vm/vm_pageout.h> +#include <linux/pagemap.h> +#include <linux/page-flags.h> + static inline long get_nr_swap_pages(void) { @@ -49,4 +57,15 @@ current_is_kswapd(void) return (curproc == pageproc); } +static inline void +folio_mark_accessed(struct folio *folio) +{ + mark_page_accessed(&folio->page); +} + +static inline void +check_move_unevictable_folios(struct folio_batch *fbatch) +{ +} + #endif diff --git a/sys/compat/linuxkpi/common/include/linux/sysfs.h b/sys/compat/linuxkpi/common/include/linux/sysfs.h index f84790f1b910..470c224a9778 100644 --- a/sys/compat/linuxkpi/common/include/linux/sysfs.h +++ b/sys/compat/linuxkpi/common/include/linux/sysfs.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_SYSFS_H_ -#define _LINUX_SYSFS_H_ +#ifndef _LINUXKPI_LINUX_SYSFS_H_ +#define _LINUXKPI_LINUX_SYSFS_H_ #include <sys/types.h> #include <sys/sysctl.h> @@ -37,6 +35,7 @@ #include <linux/kobject.h> #include <linux/stringify.h> +#include <linux/mm.h> struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *, char *); @@ -51,11 +50,23 @@ struct attribute_group { struct attribute **attrs; }; +struct bin_attribute { + struct attribute attr; + size_t size; + ssize_t (*read)(struct linux_file *, struct kobject *, + struct bin_attribute *, char *, loff_t, size_t); + ssize_t (*write)(struct linux_file *, struct kobject *, + struct bin_attribute *, char *, loff_t, size_t); +}; + #define __ATTR(_name, _mode, _show, _store) { \ .attr = { .name = __stringify(_name), .mode = _mode }, \ .show = _show, .store = _store, \ } -#define __ATTR_RO(_name) __ATTR(_name, 0444, _name##_show, NULL) +#define __ATTR_RO(_name) { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = _name##_show, \ +} #define __ATTR_WO(_name) __ATTR(_name, 0200, NULL, _name##_store) #define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store) #define __ATTR_NULL { .attr = { .name = NULL } } @@ -70,6 +81,39 @@ struct attribute_group { NULL, \ } +#define __BIN_ATTR(_name, _mode, _read, _write, _size) { \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ + .read = _read, .write = _write, .size = _size, \ +} +#define __BIN_ATTR_RO(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .read = _name##_read, .size = _size, \ +} +#define __BIN_ATTR_WO(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = 0200 }, \ + .write = _name##_write, .size = _size, \ +} +#define __BIN_ATTR_WR(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = 0644 }, \ + .read = _name##_read, .write = _name##_write, .size = _size, \ +} + +#define BIN_ATTR(_name, _mode, _read, _write, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR(_name, _mode, _read, _write, _size); + +#define BIN_ATTR_RO(_name, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR_RO(_name, _size); + +#define BIN_ATTR_WO(_name, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR_WO(_name, _size); + +#define BIN_ATTR_WR(_name, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR_WR(_name, _size); + /* * Handle our generic '\0' terminated 'C' string. * Two cases: @@ -145,6 +189,50 @@ sysfs_create_file(struct kobject *kobj, const struct attribute *attr) return (0); } +static inline struct kobject * +__sysfs_lookup_group(struct kobject *kobj, const char *group) +{ + int found; + struct sysctl_oid *group_oidp; + struct kobject *group_kobj; + + found = 0; + if (group != NULL) { + SYSCTL_FOREACH(group_oidp, SYSCTL_CHILDREN(kobj->oidp)) { + if (strcmp(group_oidp->oid_name, group) != 0) + continue; + found = 1; + break; + } + } else { + found = 1; + group_oidp = kobj->oidp; + } + + if (!found) + return (NULL); + + group_kobj = group_oidp->oid_arg1; + + return (group_kobj); +} + +static inline int +sysfs_add_file_to_group(struct kobject *kobj, + const struct attribute *attr, const char *group) +{ + int ret; + struct kobject *group_kobj; + + group_kobj = __sysfs_lookup_group(kobj, group); + if (group_kobj == NULL) + return (-ENOENT); + + ret = sysfs_create_file(group_kobj, attr); + + return (ret); +} + static inline void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr) { @@ -153,6 +241,108 @@ sysfs_remove_file(struct kobject *kobj, const struct attribute *attr) sysctl_remove_name(kobj->oidp, attr->name, 1, 1); } +static inline void +sysfs_remove_file_from_group(struct kobject *kobj, + const struct attribute *attr, const char *group) +{ + struct kobject *group_kobj; + + group_kobj = __sysfs_lookup_group(kobj, group); + if (group_kobj == NULL) + return; + + sysfs_remove_file(group_kobj, attr); +} + +static inline int +sysctl_handle_bin_attr(SYSCTL_HANDLER_ARGS) +{ + struct kobject *kobj; + struct bin_attribute *attr; + char *buf; + int error; + ssize_t len; + + kobj = arg1; + attr = (struct bin_attribute *)(intptr_t)arg2; + if (kobj->ktype == NULL || kobj->ktype->sysfs_ops == NULL) + return (ENODEV); + buf = (char *)get_zeroed_page(GFP_KERNEL); + if (buf == NULL) + return (ENOMEM); + + if (attr->read) { + len = attr->read( + NULL, /* <-- struct file, unimplemented */ + kobj, attr, buf, req->oldidx, PAGE_SIZE); + if (len < 0) { + error = -len; + if (error != EIO) + goto out; + } + } + + error = sysctl_handle_opaque(oidp, buf, PAGE_SIZE, req); + if (error != 0 || req->newptr == NULL || attr->write == NULL) + goto out; + + len = attr->write( + NULL, /* <-- struct file, unimplemented */ + kobj, attr, buf, req->newidx, req->newlen); + if (len < 0) + error = -len; +out: + free_page((unsigned long)buf); + + return (error); +} + +static inline int +sysfs_create_bin_file(struct kobject *kobj, const struct bin_attribute *attr) +{ + struct sysctl_oid *oid; + int ctlflags; + + ctlflags = CTLTYPE_OPAQUE | CTLFLAG_MPSAFE; + if (attr->attr.mode & (S_IRUSR | S_IWUSR)) + ctlflags |= CTLFLAG_RW; + else if (attr->attr.mode & S_IRUSR) + ctlflags |= CTLFLAG_RD; + else if (attr->attr.mode & S_IWUSR) + ctlflags |= CTLFLAG_WR; + + oid = SYSCTL_ADD_OID(NULL, SYSCTL_CHILDREN(kobj->oidp), OID_AUTO, + attr->attr.name, ctlflags, kobj, + (uintptr_t)attr, sysctl_handle_bin_attr, "", ""); + if (oid == NULL) + return (-ENOMEM); + + return (0); +} + +static inline void +sysfs_remove_bin_file(struct kobject *kobj, const struct bin_attribute *attr) +{ + + if (kobj->oidp) + sysctl_remove_name(kobj->oidp, attr->attr.name, 1, 1); +} + +static inline int +sysfs_create_link(struct kobject *kobj __unused, + struct kobject *target __unused, const char *name __unused) +{ + /* TODO */ + + return (0); +} + +static inline void +sysfs_remove_link(struct kobject *kobj, const char *name) +{ + /* TODO (along with sysfs_create_link) */ +} + static inline int sysfs_create_files(struct kobject *kobj, const struct attribute * const *attrs) { @@ -246,7 +436,7 @@ sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp) struct attribute **attr; struct sysctl_oid *oidp; - SLIST_FOREACH(oidp, SYSCTL_CHILDREN(kobj->oidp), oid_link) { + SYSCTL_FOREACH(oidp, SYSCTL_CHILDREN(kobj->oidp)) { if (strcmp(oidp->oid_name, grp->name) != 0) continue; for (attr = grp->attrs; *attr != NULL; attr++) { @@ -295,6 +485,60 @@ sysfs_streq(const char *s1, const char *s2) return (l1 == l2 && strncmp(s1, s2, l1) == 0); } +static inline int +sysfs_emit(char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + if (!buf || offset_in_page(buf)) { + pr_warn("invalid sysfs_emit: buf:%p\n", buf); + return (0); + } + + va_start(args, fmt); + i = vscnprintf(buf, PAGE_SIZE, fmt, args); + va_end(args); + + return (i); +} + +static inline int +sysfs_emit_at(char *buf, int at, const char *fmt, ...) +{ + va_list args; + int i; + + if (!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE) { + pr_warn("invalid sysfs_emit: buf:%p at:%d\n", buf, at); + return (0); + } + + va_start(args, fmt); + i = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args); + va_end(args); + + return (i); +} + +static inline int +_sysfs_match_string(const char * const *a, size_t l, const char *s) +{ + const char *p; + int i; + + for (i = 0; i < l; i++) { + p = a[i]; + if (p == NULL) + break; + if (sysfs_streq(p, s)) + return (i); + } + + return (-ENOENT); +} +#define sysfs_match_string(a, s) _sysfs_match_string(a, ARRAY_SIZE(a), s) + #define sysfs_attr_init(attr) do {} while(0) -#endif /* _LINUX_SYSFS_H_ */ +#endif /* _LINUXKPI_LINUX_SYSFS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/tcp.h b/sys/compat/linuxkpi/common/include/linux/tcp.h index 1197f38b7898..3e461d8e7075 100644 --- a/sys/compat/linuxkpi/common/include/linux/tcp.h +++ b/sys/compat/linuxkpi/common/include/linux/tcp.h @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_TCP_H -#define __LKPI_LINUX_TCP_H +#ifndef _LINUXKPI_LINUX_TCP_H +#define _LINUXKPI_LINUX_TCP_H #include <sys/types.h> #include <linux/skbuff.h> @@ -69,4 +67,4 @@ tcp_hdrlen(struct sk_buff *skb) return (4 * th->doff); } -#endif /* __LKPI_LINUX_TCP_H */ +#endif /* _LINUXKPI_LINUX_TCP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/time.h b/sys/compat/linuxkpi/common/include/linux/time.h index 1c07c69a67a6..ca77a20516ff 100644 --- a/sys/compat/linuxkpi/common/include/linux/time.h +++ b/sys/compat/linuxkpi/common/include/linux/time.h @@ -22,11 +22,11 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_TIME_H_ -#define _LINUX_TIME_H_ +#ifndef _LINUXKPI_LINUX_TIME_H_ +#define _LINUXKPI_LINUX_TIME_H_ + +#define MSEC_PER_SEC 1000L #define NSEC_PER_USEC 1000L #define NSEC_PER_MSEC 1000000L @@ -40,6 +40,10 @@ #include <sys/time.h> #include <sys/stdint.h> +#include <linux/math64.h> + +typedef int64_t time64_t; + static inline struct timeval ns_to_timeval(const int64_t nsec) { @@ -117,6 +121,8 @@ ns_to_timespec(const int64_t nsec) return (ts); } +#define ns_to_timespec64(_x) ns_to_timespec(_x) + static inline int timespec_valid(const struct timespec *ts) { @@ -132,4 +138,4 @@ get_seconds(void) return time_uptime; } -#endif /* _LINUX_TIME_H_ */ +#endif /* _LINUXKPI_LINUX_TIME_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/timer.h b/sys/compat/linuxkpi/common/include/linux/timer.h index 86048af31b2d..d48939e28a02 100644 --- a/sys/compat/linuxkpi/common/include/linux/timer.h +++ b/sys/compat/linuxkpi/common/include/linux/timer.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_TIMER_H_ -#define _LINUX_TIMER_H_ +#ifndef _LINUXKPI_LINUX_TIMER_H_ +#define _LINUXKPI_LINUX_TIMER_H_ #include <linux/types.h> @@ -44,15 +42,20 @@ struct timer_list { void (*function_415) (struct timer_list *); }; unsigned long data; - int expires; + unsigned long expires; }; extern unsigned long linux_timer_hz_mask; #define TIMER_IRQSAFE 0x0001 +#if defined(LINUXKPI_VERSION) && (LINUXKPI_VERSION < 61600) #define from_timer(var, arg, field) \ container_of(arg, typeof(*(var)), field) +#else +#define timer_container_of(var, arg, field) \ + container_of(arg, typeof(*(var)), field) +#endif #define timer_setup(timer, func, flags) do { \ CTASSERT(((flags) & ~TIMER_IRQSAFE) == 0); \ @@ -78,17 +81,31 @@ extern unsigned long linux_timer_hz_mask; callout_init(&(timer)->callout, 1); \ } while (0) -extern int mod_timer(struct timer_list *, int); +extern int mod_timer(struct timer_list *, unsigned long); extern void add_timer(struct timer_list *); extern void add_timer_on(struct timer_list *, int cpu); -extern int del_timer(struct timer_list *); -extern int del_timer_sync(struct timer_list *); + +extern int timer_delete(struct timer_list *); +extern int timer_delete_sync(struct timer_list *); +extern int timer_shutdown_sync(struct timer_list *); + +static inline int +del_timer(struct timer_list *tl) +{ + return (timer_delete(tl)); +} + +static inline int +del_timer_sync(struct timer_list *tl) +{ + return (timer_delete_sync(tl)); +} #define timer_pending(timer) callout_pending(&(timer)->callout) #define round_jiffies(j) \ - ((int)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask)) + ((unsigned long)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask)) #define round_jiffies_relative(j) round_jiffies(j) #define round_jiffies_up(j) round_jiffies(j) #define round_jiffies_up_relative(j) round_jiffies_up(j) -#endif /* _LINUX_TIMER_H_ */ +#endif /* _LINUXKPI_LINUX_TIMER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/topology.h b/sys/compat/linuxkpi/common/include/linux/topology.h new file mode 100644 index 000000000000..16baffc024d1 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/topology.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_TOPOLOGY_H_ +#define _LINUXKPI_LINUX_TOPOLOGY_H_ + +#include <asm/topology.h> + +#endif /* _LINUXKPI_LINUX_TOPOLOGY_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/tracepoint.h b/sys/compat/linuxkpi/common/include/linux/tracepoint.h new file mode 100644 index 000000000000..8ce7992306b9 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/tracepoint.h @@ -0,0 +1,48 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_TRACEPOINT_H +#define _LINUXKPI_LINUX_TRACEPOINT_H + +#define TP_PROTO(...) __VA_ARGS__ +#define TP_ARGS(...) +#define TP_STRUCT__entry(...) +#define TP_fast_assign(...) +#define TP_printk(...) + +#define TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ +static inline void trace_ ## _name(_proto) \ +{ \ +} + +#define DECLARE_EVENT_CLASS(...) +#define DEFINE_EVENT(_x, _name, _proto, _args) \ +static inline void trace_ ## _name(_proto) \ +{ \ +} + +#endif /* _LINUXKPI_LINUX_TRACEPOINT_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/typecheck.h b/sys/compat/linuxkpi/common/include/linux/typecheck.h new file mode 100644 index 000000000000..0e813962a7f5 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/typecheck.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_TYPECHECK_H_ +#define _LINUXKPI_LINUX_TYPECHECK_H_ + +#define typecheck(type,x) \ +({ type __var1; \ + typeof(x) __var2; \ + (void)(&__var1 == &__var2); \ + 1; \ +}) + + +#endif /* _LINUXKPI_LINUX_TYPECHECK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/types.h b/sys/compat/linuxkpi/common/include/linux/types.h index db362c388573..fcc455e5f731 100644 --- a/sys/compat/linuxkpi/common/include/linux/types.h +++ b/sys/compat/linuxkpi/common/include/linux/types.h @@ -25,13 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_TYPES_H_ -#define _LINUX_TYPES_H_ +#ifndef _LINUXKPI_LINUX_TYPES_H_ +#define _LINUXKPI_LINUX_TYPES_H_ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> @@ -66,6 +63,7 @@ typedef unsigned gfp_t; typedef off_t loff_t; typedef vm_paddr_t resource_size_t; typedef uint16_t __bitwise__ __sum16; +typedef uint32_t __bitwise__ __wsum; typedef unsigned long pgoff_t; typedef unsigned __poll_t; @@ -79,6 +77,14 @@ typedef unsigned long kernel_ulong_t; typedef unsigned long irq_hw_number_t; +#ifndef LIST_HEAD_DEF +#define LIST_HEAD_DEF +struct list_head { + struct list_head *next; + struct list_head *prev; +}; +#endif + struct rcu_head { void *raw[2]; } __aligned(sizeof(void *)); @@ -87,4 +93,4 @@ typedef void (*rcu_callback_t)(struct rcu_head *head); typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func); typedef int linux_task_fn_t(void *data); -#endif /* _LINUX_TYPES_H_ */ +#endif /* _LINUXKPI_LINUX_TYPES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/uaccess.h b/sys/compat/linuxkpi/common/include/linux/uaccess.h index 10a06a220f86..660e84e6af3b 100644 --- a/sys/compat/linuxkpi/common/include/linux/uaccess.h +++ b/sys/compat/linuxkpi/common/include/linux/uaccess.h @@ -26,12 +26,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_UACCESS_H_ -#define _LINUX_UACCESS_H_ +#ifndef _LINUXKPI_LINUX_UACCESS_H_ +#define _LINUXKPI_LINUX_UACCESS_H_ #include <sys/param.h> #include <sys/lock.h> @@ -89,4 +87,29 @@ pagefault_disabled(void) return ((curthread->td_pflags & TDP_NOFAULTING) != 0); } -#endif /* _LINUX_UACCESS_H_ */ +static inline int +__copy_to_user_inatomic(void __user *to, const void *from, unsigned n) +{ + + return (copyout_nofault(from, to, n) != 0 ? n : 0); +} +#define __copy_to_user_inatomic_nocache(to, from, n) \ + __copy_to_user_inatomic((to), (from), (n)) + +static inline unsigned long +__copy_from_user_inatomic(void *to, const void __user *from, + unsigned long n) +{ + /* + * XXXKIB. Equivalent Linux function is implemented using + * MOVNTI for aligned moves. For unaligned head and tail, + * normal move is performed. As such, it is not incorrect, if + * only somewhat slower, to use normal copyin. All uses + * except shmem_pwrite_fast() have the destination mapped WC. + */ + return ((copyin_nofault(__DECONST(void *, from), to, n) != 0 ? n : 0)); +} +#define __copy_from_user_inatomic_nocache(to, from, n) \ + __copy_from_user_inatomic((to), (from), (n)) + +#endif /* _LINUXKPI_LINUX_UACCESS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/udp.h b/sys/compat/linuxkpi/common/include/linux/udp.h index 259bdbfc1199..f3cd40cf8bb7 100644 --- a/sys/compat/linuxkpi/common/include/linux/udp.h +++ b/sys/compat/linuxkpi/common/include/linux/udp.h @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_UDP_H -#define __LKPI_LINUX_UDP_H +#ifndef _LINUXKPI_LINUX_UDP_H +#define _LINUXKPI_LINUX_UDP_H #include <sys/types.h> #include <linux/skbuff.h> @@ -51,4 +49,4 @@ udp_hdr(struct sk_buff *skb) return (struct udphdr *)skb_transport_header(skb); } -#endif /* __LKPI_LINUX_UDP_H */ +#endif /* _LINUXKPI_LINUX_UDP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/units.h b/sys/compat/linuxkpi/common/include/linux/units.h new file mode 100644 index 000000000000..304b5c27d87f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/units.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_UNITS_H_ +#define _LINUXKPI_LINUX_UNITS_H_ + +#define NANOHZ_PER_HZ 1000000000UL +#define MICROHZ_PER_HZ 1000000UL +#define MILLIHZ_PER_HZ 1000UL +#define HZ_PER_KHZ 1000UL +#define KHZ_PER_MHZ 1000UL +#define HZ_PER_MHZ 1000000UL + +#endif /* _LINUXKPI_LINUX_UNITS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/usb.h b/sys/compat/linuxkpi/common/include/linux/usb.h index 032c1e53a015..d9649dcb5471 100644 --- a/sys/compat/linuxkpi/common/include/linux/usb.h +++ b/sys/compat/linuxkpi/common/include/linux/usb.h @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ /*- * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved. * Copyright (c) 2007 Hans Petter Selasky. All rights reserved. @@ -37,12 +36,13 @@ #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> +#include <linux/pm.h> + struct usb_device; struct usb_interface; struct usb_driver; struct urb; -typedef void *pm_message_t; typedef void (usb_complete_t)(struct urb *); #define USB_MAX_FULL_SPEED_ISOC_FRAMES (60 * 1) diff --git a/sys/compat/linuxkpi/common/include/linux/utsname.h b/sys/compat/linuxkpi/common/include/linux/utsname.h new file mode 100644 index 000000000000..3239801ca17b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/utsname.h @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_UTSNAME_H +#define _LINUXKPI_LINUX_UTSNAME_H + +#include <sys/types.h> +#include <sys/jail.h> + +struct _utsname { + char release[OSRELEASELEN]; +}; + +struct uts_namespace { + struct _utsname name; +}; + +extern struct uts_namespace init_uts_ns; + +static inline struct _utsname * +init_utsname(void) +{ + + return &init_uts_ns.name; +} + +#endif /* _LINUXKPI_LINUX_UTSNAME_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/uuid.h b/sys/compat/linuxkpi/common/include/linux/uuid.h index f2ff450ee907..4f6f4a8b34f0 100644 --- a/sys/compat/linuxkpi/common/include/linux/uuid.h +++ b/sys/compat/linuxkpi/common/include/linux/uuid.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 The FreeBSD Foundation + * Copyright (c) 2021,2023 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,15 +26,52 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_LINUX_UUID_H -#define __LKPI_LINUX_UUID_H +#ifndef _LINUXKPI_LINUX_UUID_H +#define _LINUXKPI_LINUX_UUID_H + +#include <linux/random.h> + +#define UUID_STRING_LEN 36 + +#define GUID_INIT(x0_3, x4_5, x6_7, x8, x9, x10, x11, x12, x13, x14, x15) \ + ((guid_t) { .x = { \ + [0] = (x0_3) & 0xff, \ + [1] = ((x0_3) >> 8) & 0xff, \ + [2] = ((x0_3) >> 16) & 0xff, \ + [3] = ((x0_3) >> 24) & 0xff, \ + [4] = (x4_5) & 0xff, \ + [5] = ((x4_5) >> 8) & 0xff, \ + [6] = (x6_7) & 0xff, \ + [7] = ((x6_7) >> 8) & 0xff, \ + [8] = (x8), \ + [9] = (x9), \ + [10] = (x10), \ + [11] = (x11), \ + [12] = (x12), \ + [13] = (x13), \ + [14] = (x14), \ + [15] = (x15) \ +}}) typedef struct { char x[16]; } guid_t; -#endif /* __LKPI_LINUX_UUID_H */ +static inline void +guid_gen(guid_t *g) +{ + + get_random_bytes(g, 16); + g->x[7] = (g->x[7] & 0x0f) | 0x40; + g->x[8] = (g->x[8] & 0x3f) | 0x80; +} + +static inline void +guid_copy(guid_t *dst, const guid_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + +#endif /* _LINUXKPI_LINUX_UUID_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/vgaarb.h b/sys/compat/linuxkpi/common/include/linux/vgaarb.h new file mode 100644 index 000000000000..d43a88136864 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/vgaarb.h @@ -0,0 +1,281 @@ +/* + * The VGA aribiter manages VGA space routing and VGA resource decode to + * allow multiple VGA devices to be used in a system in a safe way. + * + * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> + * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com> + * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _LINUXKPI_LINUX_VGA_H_ +#define _LINUXKPI_LINUX_VGA_H_ + +#include <video/vga.h> + +/* Legacy VGA regions */ +#define VGA_RSRC_NONE 0x00 +#define VGA_RSRC_LEGACY_IO 0x01 +#define VGA_RSRC_LEGACY_MEM 0x02 +#define VGA_RSRC_LEGACY_MASK (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM) +/* Non-legacy access */ +#define VGA_RSRC_NORMAL_IO 0x04 +#define VGA_RSRC_NORMAL_MEM 0x08 + +/* Passing that instead of a pci_dev to use the system "default" + * device, that is the one used by vgacon. Archs will probably + * have to provide their own vga_default_device(); + */ +#define VGA_DEFAULT_DEVICE (NULL) + +struct pci_dev; + +/* For use by clients */ + +/** + * vga_set_legacy_decoding + * + * @pdev: pci device of the VGA card + * @decodes: bit mask of what legacy regions the card decodes + * + * Indicates to the arbiter if the card decodes legacy VGA IOs, + * legacy VGA Memory, both, or none. All cards default to both, + * the card driver (fbdev for example) should tell the arbiter + * if it has disabled legacy decoding, so the card can be left + * out of the arbitration process (and can be safe to take + * interrupts at any time. + */ +#if defined(CONFIG_VGA_ARB) +extern void vga_set_legacy_decoding(struct pci_dev *pdev, + unsigned int decodes); +#else +static inline void vga_set_legacy_decoding(struct pci_dev *pdev, + unsigned int decodes) { }; +#endif + +/** + * vga_get - acquire & locks VGA resources + * + * @pdev: pci device of the VGA card or NULL for the system default + * @rsrc: bit mask of resources to acquire and lock + * @interruptible: blocking should be interruptible by signals ? + * + * This function acquires VGA resources for the given + * card and mark those resources locked. If the resource requested + * are "normal" (and not legacy) resources, the arbiter will first check + * whether the card is doing legacy decoding for that type of resource. If + * yes, the lock is "converted" into a legacy resource lock. + * The arbiter will first look for all VGA cards that might conflict + * and disable their IOs and/or Memory access, including VGA forwarding + * on P2P bridges if necessary, so that the requested resources can + * be used. Then, the card is marked as locking these resources and + * the IO and/or Memory accesse are enabled on the card (including + * VGA forwarding on parent P2P bridges if any). + * This function will block if some conflicting card is already locking + * one of the required resources (or any resource on a different bus + * segment, since P2P bridges don't differenciate VGA memory and IO + * afaik). You can indicate whether this blocking should be interruptible + * by a signal (for userland interface) or not. + * Must not be called at interrupt time or in atomic context. + * If the card already owns the resources, the function succeeds. + * Nested calls are supported (a per-resource counter is maintained) + */ + +#if defined(CONFIG_VGA_ARB) +extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible); +#else +static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) { return 0; } +#endif + +/** + * vga_get_interruptible + * + * Shortcut to vga_get + */ + +static inline int vga_get_interruptible(struct pci_dev *pdev, + unsigned int rsrc) +{ + return vga_get(pdev, rsrc, 1); +} + +/** + * vga_get_uninterruptible + * + * Shortcut to vga_get + */ + +static inline int vga_get_uninterruptible(struct pci_dev *pdev, + unsigned int rsrc) +{ + return vga_get(pdev, rsrc, 0); +} + +/** + * vga_tryget - try to acquire & lock legacy VGA resources + * + * @pdev: pci devivce of VGA card or NULL for system default + * @rsrc: bit mask of resources to acquire and lock + * + * This function performs the same operation as vga_get(), but + * will return an error (-EBUSY) instead of blocking if the resources + * are already locked by another card. It can be called in any context + */ + +#if defined(CONFIG_VGA_ARB) +extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc); +#else +static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; } +#endif + +/** + * vga_put - release lock on legacy VGA resources + * + * @pdev: pci device of VGA card or NULL for system default + * @rsrc: but mask of resource to release + * + * This function releases resources previously locked by vga_get() + * or vga_tryget(). The resources aren't disabled right away, so + * that a subsequence vga_get() on the same card will succeed + * immediately. Resources have a counter, so locks are only + * released if the counter reaches 0. + */ + +#if defined(CONFIG_VGA_ARB) +extern void vga_put(struct pci_dev *pdev, unsigned int rsrc); +#else +#define vga_put(pdev, rsrc) +#endif + + +/** + * vga_default_device + * + * This can be defined by the platform. The default implementation + * is rather dumb and will probably only work properly on single + * vga card setups and/or x86 platforms. + * + * If your VGA default device is not PCI, you'll have to return + * NULL here. In this case, I assume it will not conflict with + * any PCI card. If this is not true, I'll have to define two archs + * hooks for enabling/disabling the VGA default device if that is + * possible. This may be a problem with real _ISA_ VGA cards, in + * addition to a PCI one. I don't know at this point how to deal + * with that card. Can theirs IOs be disabled at all ? If not, then + * I suppose it's a matter of having the proper arch hook telling + * us about it, so we basically never allow anybody to succeed a + * vga_get()... + */ + +#ifdef CONFIG_VGA_ARB +extern struct pci_dev *vga_default_device(void); +extern void vga_set_default_device(struct pci_dev *pdev); +#else +static inline struct pci_dev *vga_default_device(void) { return NULL; }; +static inline void vga_set_default_device(struct pci_dev *pdev) { }; +#endif + +/** + * vga_conflicts + * + * Architectures should define this if they have several + * independent PCI domains that can afford concurrent VGA + * decoding + */ + +#ifndef __ARCH_HAS_VGA_CONFLICT +static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2) +{ + return 1; +} +#endif + +/** + * vga_client_register + * + * @pdev: pci device of the VGA client + * @cookie: client cookie to be used in callbacks + * @irq_set_state: irq state change callback + * @set_vga_decode: vga decode change callback + * + * return value: 0 on success, -1 on failure + * Register a client with the VGA arbitration logic + * + * Clients have two callback mechanisms they can use. + * irq enable/disable callback - + * If a client can't disable its GPUs VGA resources, then we + * need to be able to ask it to turn off its irqs when we + * turn off its mem and io decoding. + * set_vga_decode + * If a client can disable its GPU VGA resource, it will + * get a callback from this to set the encode/decode state + * + * Rationale: we cannot disable VGA decode resources unconditionally + * some single GPU laptops seem to require ACPI or BIOS access to the + * VGA registers to control things like backlights etc. + * Hopefully newer multi-GPU laptops do something saner, and desktops + * won't have any special ACPI for this. + * They driver will get a callback when VGA arbitration is first used + * by userspace since we some older X servers have issues. + */ +#if defined(CONFIG_VGA_ARB) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51501 +int vga_client_register(struct pci_dev *pdev, + unsigned int (*set_vga_decode)(struct pci_dev *pdev, bool state)); +#elif defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51500 +int vga_client_register(struct pci_dev *pdev, void *cookie, + unsigned int (*set_vga_decode)(void *cookie, bool state)); +#else +int vga_client_register(struct pci_dev *pdev, void *cookie, + void (*irq_set_state)(void *cookie, bool state), + unsigned int (*set_vga_decode)(void *cookie, bool state)); +#endif +#else +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51501 +static inline int vga_client_register(struct pci_dev *pdev, + unsigned int (*set_vga_decode)(struct pci_dev *pdev, bool state)) +#elif defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51500 +static inline int vga_client_register(struct pci_dev *pdev, void *cookie, + unsigned int (*set_vga_decode)(void *cookie, bool state)) +#else +static inline int vga_client_register(struct pci_dev *pdev, void *cookie, + void (*irq_set_state)(void *cookie, bool state), + unsigned int (*set_vga_decode)(void *cookie, bool state)) +#endif +{ + return 0; +} + +static inline int vga_client_unregister(struct pci_dev *pdev) +{ +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51501 + return (vga_client_register(NULL, NULL)); +#elif defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51500 + return (vga_client_register(NULL, NULL, NULL)); +#else + return (vga_client_register(NULL, NULL, NULL, NULL)); +#endif +} +#endif + +#endif /* _LINUXKPI_LINUX_VGA_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/vmalloc.h b/sys/compat/linuxkpi/common/include/linux/vmalloc.h index 53178314c35a..00650a2df9b6 100644 --- a/sys/compat/linuxkpi/common/include/linux/vmalloc.h +++ b/sys/compat/linuxkpi/common/include/linux/vmalloc.h @@ -25,12 +25,11 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_VMALLOC_H_ -#define _LINUX_VMALLOC_H_ +#ifndef _LINUXKPI_LINUX_VMALLOC_H_ +#define _LINUXKPI_LINUX_VMALLOC_H_ +#include <linux/overflow.h> #include <linux/page.h> #define VM_MAP 0x0000 @@ -40,4 +39,4 @@ void *vmap(struct page **pages, unsigned int count, unsigned long flags, int prot); void vunmap(void *addr); -#endif /* _LINUX_VMALLOC_H_ */ +#endif /* _LINUXKPI_LINUX_VMALLOC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/wait.h b/sys/compat/linuxkpi/common/include/linux/wait.h index 348464fb27df..03ddce2c06f5 100644 --- a/sys/compat/linuxkpi/common/include/linux/wait.h +++ b/sys/compat/linuxkpi/common/include/linux/wait.h @@ -26,12 +26,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_WAIT_H_ -#define _LINUX_WAIT_H_ +#ifndef _LINUXKPI_LINUX_WAIT_H_ +#define _LINUXKPI_LINUX_WAIT_H_ #include <linux/compiler.h> #include <linux/list.h> @@ -63,12 +61,14 @@ typedef struct wait_queue_head wait_queue_head_t; typedef int wait_queue_func_t(wait_queue_t *, unsigned int, int, void *); +#define WQ_FLAG_WOKEN 0x02 + /* * Many API consumers directly reference these fields and those of * wait_queue_head. */ struct wait_queue { - unsigned int flags; /* always 0 */ + unsigned int flags; void *private; wait_queue_func_t *func; union { @@ -89,8 +89,14 @@ struct wait_queue_head { * This function is referenced by at least one DRM driver, so it may not be * renamed and furthermore must be the default wait queue callback. */ -extern wait_queue_func_t autoremove_wake_function; -extern wait_queue_func_t default_wake_function; +wait_queue_func_t autoremove_wake_function; +wait_queue_func_t default_wake_function; +wait_queue_func_t woken_wake_function; + +long linux_wait_woken(wait_queue_t *wq, unsigned state, long timeout); + +#define wait_woken(wq, state, timeout) \ + linux_wait_woken((wq), (state), (timeout)) #define DEFINE_WAIT_FUNC(name, function) \ wait_queue_t name = { \ @@ -112,10 +118,10 @@ extern wait_queue_func_t default_wake_function; wait_queue_head_t name = { \ .task_list = LINUX_LIST_HEAD_INIT(name.task_list), \ }; \ - MTX_SYSINIT(name, &(name).lock.m, spin_lock_name("wqhead"), MTX_DEF) + MTX_SYSINIT(name, &(name).lock, spin_lock_name("wqhead"), MTX_DEF) #define init_waitqueue_head(wqh) do { \ - mtx_init(&(wqh)->lock.m, spin_lock_name("wqhead"), \ + mtx_init(&(wqh)->lock, spin_lock_name("wqhead"), \ NULL, MTX_DEF | MTX_NEW | MTX_NOWITNESS); \ INIT_LIST_HEAD(&(wqh)->task_list); \ } while (0) @@ -140,7 +146,7 @@ void linux_wake_up(wait_queue_head_t *, unsigned int, int, bool); #define wake_up_interruptible_all(wqh) \ linux_wake_up(wqh, TASK_INTERRUPTIBLE, 0, false) -int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, int, +int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, long, unsigned int, spinlock_t *); /* @@ -150,9 +156,9 @@ int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, int, */ #define __wait_event_common(wqh, cond, timeout, state, lock) ({ \ DEFINE_WAIT(__wq); \ - const int __timeout = ((int)(timeout)) < 1 ? 1 : (timeout); \ - int __start = ticks; \ - int __ret = 0; \ + const long __timeout = ((long)(timeout)) < 1 ? 1 : (timeout); \ + long __start = jiffies; \ + long __ret = 0; \ \ for (;;) { \ linux_prepare_to_wait(&(wqh), &__wq, state); \ @@ -168,7 +174,7 @@ int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, int, if (__ret == -EWOULDBLOCK) \ __ret = !!(cond); \ else if (__ret != -ERESTARTSYS) { \ - __ret = __timeout + __start - ticks; \ + __ret = __timeout + __start - jiffies; \ /* range check return value */ \ if (__ret < 1) \ __ret = 1; \ @@ -286,7 +292,7 @@ void linux_finish_wait(wait_queue_head_t *, wait_queue_t *); #define finish_wait(wqh, wq) linux_finish_wait(wqh, wq) void linux_wake_up_bit(void *, int); -int linux_wait_on_bit_timeout(unsigned long *, int, unsigned int, int); +int linux_wait_on_bit_timeout(unsigned long *, int, unsigned int, long); void linux_wake_up_atomic_t(atomic_t *); int linux_wait_on_atomic_t(atomic_t *, unsigned int); @@ -310,4 +316,4 @@ bool linux_wake_up_state(struct task_struct *, unsigned int); #define wake_up_process(task) linux_wake_up_state(task, TASK_NORMAL) #define wake_up_state(task, state) linux_wake_up_state(task, state) -#endif /* _LINUX_WAIT_H_ */ +#endif /* _LINUXKPI_LINUX_WAIT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/wait_bit.h b/sys/compat/linuxkpi/common/include/linux/wait_bit.h index 711b19da6582..573798590b73 100644 --- a/sys/compat/linuxkpi/common/include/linux/wait_bit.h +++ b/sys/compat/linuxkpi/common/include/linux/wait_bit.h @@ -24,12 +24,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LINUX_WAITBIT_H__ -#define __LINUX_WAITBIT_H__ +#ifndef __LINUXKPI_LINUX_WAITBIT_H__ +#define __LINUXKPI_LINUX_WAITBIT_H__ #include <linux/wait.h> #include <linux/bitops.h> @@ -64,4 +62,10 @@ wake_up_var(void *var) wake_up(&linux_var_waitq); } -#endif /* __LINUX_WAITBIT_H__ */ +static inline wait_queue_head_t * +__var_waitqueue(void *p) +{ + return (&linux_var_waitq); +} + +#endif /* __LINUXKPI_LINUX_WAITBIT_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/workqueue.h b/sys/compat/linuxkpi/common/include/linux/workqueue.h index 768ce33bb20d..66d3981d4229 100644 --- a/sys/compat/linuxkpi/common/include/linux/workqueue.h +++ b/sys/compat/linuxkpi/common/include/linux/workqueue.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_WORKQUEUE_H_ -#define _LINUX_WORKQUEUE_H_ +#ifndef _LINUXKPI_LINUX_WORKQUEUE_H_ +#define _LINUXKPI_LINUX_WORKQUEUE_H_ #include <linux/types.h> #include <linux/kernel.h> @@ -92,7 +90,7 @@ struct delayed_work { struct { struct callout callout; struct mtx mtx; - int expires; + unsigned long expires; } timer; }; @@ -190,6 +188,9 @@ do { \ #define delayed_work_pending(dwork) \ linux_work_pending(&(dwork)->work) +#define cancel_work(work) \ + linux_cancel_work(work) + #define cancel_delayed_work(dwork) \ linux_cancel_delayed_work(dwork) @@ -244,7 +245,8 @@ extern struct workqueue_struct *linux_create_workqueue_common(const char *, int) extern void linux_destroy_workqueue(struct workqueue_struct *); extern bool linux_queue_work_on(int cpu, struct workqueue_struct *, struct work_struct *); extern bool linux_queue_delayed_work_on(int cpu, struct workqueue_struct *, - struct delayed_work *, unsigned delay); + struct delayed_work *, unsigned long delay); +extern bool linux_cancel_work(struct work_struct *); extern bool linux_cancel_delayed_work(struct delayed_work *); extern bool linux_cancel_work_sync(struct work_struct *); extern bool linux_cancel_delayed_work_sync(struct delayed_work *); @@ -256,4 +258,10 @@ extern struct work_struct *linux_current_work(void); extern bool linux_queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork); extern bool linux_flush_rcu_work(struct rcu_work *rwork); -#endif /* _LINUX_WORKQUEUE_H_ */ +static inline bool +queue_work_node(int node __unused, struct workqueue_struct *wq, struct work_struct *work) +{ + return (queue_work(wq, work)); +} + +#endif /* _LINUXKPI_LINUX_WORKQUEUE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ww_mutex.h b/sys/compat/linuxkpi/common/include/linux/ww_mutex.h index 49bec6628486..9219755bb78e 100644 --- a/sys/compat/linuxkpi/common/include/linux/ww_mutex.h +++ b/sys/compat/linuxkpi/common/include/linux/ww_mutex.h @@ -22,11 +22,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_WW_MUTEX_H_ -#define _LINUX_WW_MUTEX_H_ +#ifndef _LINUXKPI_LINUX_WW_MUTEX_H_ +#define _LINUXKPI_LINUX_WW_MUTEX_H_ #include <sys/param.h> #include <sys/proc.h> @@ -61,6 +59,8 @@ struct ww_mutex { } \ SYSINIT(name, SI_SUB_LOCK, SI_ORDER_SECOND, name##_init, NULL) +#define DEFINE_WD_CLASS(name) DEFINE_WW_CLASS(name) + #define ww_mutex_is_locked(_m) \ sx_xlocked(&(_m)->base.sx) @@ -70,8 +70,13 @@ struct ww_mutex { #define ww_mutex_lock_slow_interruptible(_m, _x) \ ww_mutex_lock_interruptible(_m, _x) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51600 +static inline int __must_check +ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx __unused) +#else static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock) +#endif { return (mutex_trylock(&lock->base)); } @@ -141,4 +146,4 @@ ww_acquire_done(struct ww_acquire_ctx *ctx) { } -#endif /* _LINUX_WW_MUTEX_H_ */ +#endif /* _LINUXKPI_LINUX_WW_MUTEX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/xarray.h b/sys/compat/linuxkpi/common/include/linux/xarray.h index 7427f6e4f9f9..fba36eea0ab5 100644 --- a/sys/compat/linuxkpi/common/include/linux/xarray.h +++ b/sys/compat/linuxkpi/common/include/linux/xarray.h @@ -22,15 +22,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_XARRAY_H_ -#define _LINUX_XARRAY_H_ +#ifndef _LINUXKPI_LINUX_XARRAY_H_ +#define _LINUXKPI_LINUX_XARRAY_H_ #include <linux/gfp.h> #include <linux/radix-tree.h> #include <linux/err.h> +#include <linux/kconfig.h> #include <sys/lock.h> #include <sys/mutex.h> @@ -40,19 +39,24 @@ #define XA_FLAGS_ALLOC (1U << 0) #define XA_FLAGS_LOCK_IRQ (1U << 1) +#define XA_FLAGS_ALLOC1 (1U << 2) #define XA_ERROR(x) \ ERR_PTR(x) +#define xa_is_err(x) \ + IS_ERR(x) + #define xa_limit_32b XA_LIMIT(0, 0xFFFFFFFF) -#define XA_ASSERT_LOCKED(xa) mtx_assert(&(xa)->mtx, MA_OWNED) -#define xa_lock(xa) mtx_lock(&(xa)->mtx) -#define xa_unlock(xa) mtx_unlock(&(xa)->mtx) +#define XA_ASSERT_LOCKED(xa) mtx_assert(&(xa)->xa_lock, MA_OWNED) +#define xa_lock(xa) mtx_lock(&(xa)->xa_lock) +#define xa_unlock(xa) mtx_unlock(&(xa)->xa_lock) struct xarray { - struct radix_tree_root root; - struct mtx mtx; /* internal mutex */ + struct radix_tree_root xa_head; + struct mtx xa_lock; /* internal mutex */ + uint32_t xa_flags; /* see XA_FLAGS_XXX */ }; /* @@ -63,6 +67,7 @@ void *xa_erase(struct xarray *, uint32_t); void *xa_load(struct xarray *, uint32_t); int xa_alloc(struct xarray *, uint32_t *, void *, uint32_t, gfp_t); int xa_alloc_cyclic(struct xarray *, uint32_t *, void *, uint32_t, uint32_t *, gfp_t); +int xa_alloc_cyclic_irq(struct xarray *, uint32_t *, void *, uint32_t, uint32_t *, gfp_t); int xa_insert(struct xarray *, uint32_t, void *, gfp_t); void *xa_store(struct xarray *, uint32_t, void *, gfp_t); void xa_init_flags(struct xarray *, uint32_t); @@ -85,6 +90,27 @@ void *__xa_store(struct xarray *, uint32_t, void *, gfp_t); bool __xa_empty(struct xarray *); void *__xa_next(struct xarray *, unsigned long *, bool); +#define xa_store_irq(xa, index, ptr, gfp) \ + xa_store((xa), (index), (ptr), (gfp)) + +#define xa_erase_irq(xa, index) \ + xa_erase((xa), (index)) + +#define xa_lock_irq(xa) xa_lock(xa) +#define xa_unlock_irq(xa) xa_unlock(xa) + +#define xa_lock_irqsave(xa, flags) \ + do { \ + xa_lock((xa)); \ + flags = 0; \ + } while (0) + +#define xa_unlock_irqrestore(xa, flags) \ + do { \ + xa_unlock((xa)); \ + flags == 0; \ + } while (0) + static inline int xa_err(void *ptr) { @@ -120,4 +146,4 @@ xa_to_value(const void *e) return (v >> 1); } -#endif /* _LINUX_XARRAY_H_ */ +#endif /* _LINUXKPI_LINUX_XARRAY_H_ */ diff --git a/sys/compat/linuxkpi/common/include/net/addrconf.h b/sys/compat/linuxkpi/common/include/net/addrconf.h index 32bbaf176336..33c07792d807 100644 --- a/sys/compat/linuxkpi/common/include/net/addrconf.h +++ b/sys/compat/linuxkpi/common/include/net/addrconf.h @@ -26,12 +26,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_NET_ADDRCONF_H -#define __LKPI_NET_ADDRCONF_H +#ifndef _LINUXKPI_NET_ADDRCONF_H +#define _LINUXKPI_NET_ADDRCONF_H #include <sys/types.h> #include <netinet/in.h> @@ -48,4 +46,4 @@ addrconf_addr_solict_mult(struct in6_addr *ia6, struct in6_addr *sol) sol->s6_addr8[12] = 0xff; } -#endif /* __LKPI_NET_ADDRCONF_H */ +#endif /* _LINUXKPI_NET_ADDRCONF_H */ diff --git a/sys/compat/linuxkpi/common/include/net/cfg80211.h b/sys/compat/linuxkpi/common/include/net/cfg80211.h new file mode 100644 index 000000000000..f769cfdd4075 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/net/cfg80211.h @@ -0,0 +1,2259 @@ +/*- + * Copyright (c) 2020-2025 The FreeBSD Foundation + * Copyright (c) 2021-2022 Bjoern A. Zeeb + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_NET_CFG80211_H +#define _LINUXKPI_NET_CFG80211_H + +#include <linux/types.h> +#include <linux/nl80211.h> +#include <linux/ieee80211.h> +#include <linux/mutex.h> +#include <linux/if_ether.h> +#include <linux/ethtool.h> +#include <linux/debugfs.h> +#include <linux/device.h> +#include <linux/netdevice.h> +#include <linux/random.h> +#include <linux/skbuff.h> +#include <linux/timer.h> +#include <linux/workqueue.h> +#include <net/regulatory.h> + +#include <net80211/ieee80211.h> + +/* linux_80211.c */ +extern int linuxkpi_debug_80211; +#ifndef D80211_TODO +#define D80211_TODO 0x1 +#endif +#ifndef D80211_IMPROVE +#define D80211_IMPROVE 0x2 +#endif +#define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ + printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) +#define IMPROVE(fmt, ...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \ + printf("%s:%d: XXX LKPI80211 IMPROVE " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) + +enum rfkill_hard_block_reasons { + RFKILL_HARD_BLOCK_NOT_OWNER = BIT(0), +}; + +#define WIPHY_PARAM_FRAG_THRESHOLD __LINE__ /* TODO FIXME brcmfmac */ +#define WIPHY_PARAM_RETRY_LONG __LINE__ /* TODO FIXME brcmfmac */ +#define WIPHY_PARAM_RETRY_SHORT __LINE__ /* TODO FIXME brcmfmac */ +#define WIPHY_PARAM_RTS_THRESHOLD __LINE__ /* TODO FIXME brcmfmac */ + +#define CFG80211_SIGNAL_TYPE_MBM __LINE__ /* TODO FIXME brcmfmac */ + +#define UPDATE_ASSOC_IES 1 + +#define IEEE80211_MAX_CHAINS 4 /* net80211: IEEE80211_MAX_CHAINS copied */ + +enum cfg80211_rate_info_flags { + RATE_INFO_FLAGS_MCS = BIT(0), + RATE_INFO_FLAGS_VHT_MCS = BIT(1), + RATE_INFO_FLAGS_SHORT_GI = BIT(2), + RATE_INFO_FLAGS_HE_MCS = BIT(4), + RATE_INFO_FLAGS_EHT_MCS = BIT(7), + /* Max 8 bits as used in struct rate_info. */ +}; + +#define CFG80211_RATE_INFO_FLAGS_BITS \ + "\20\1MCS\2VHT_MCS\3SGI\5HE_MCS\10EHT_MCS" + +extern const uint8_t rfc1042_header[6]; +extern const uint8_t bridge_tunnel_header[6]; + +enum ieee80211_privacy { + IEEE80211_PRIVACY_ANY, +}; + +enum ieee80211_bss_type { + IEEE80211_BSS_TYPE_ANY, +}; + +enum cfg80211_bss_frame_type { + CFG80211_BSS_FTYPE_UNKNOWN, + CFG80211_BSS_FTYPE_BEACON, + CFG80211_BSS_FTYPE_PRESP, +}; + +enum ieee80211_channel_flags { + IEEE80211_CHAN_DISABLED = BIT(0), + IEEE80211_CHAN_INDOOR_ONLY = BIT(1), + IEEE80211_CHAN_IR_CONCURRENT = BIT(2), + IEEE80211_CHAN_RADAR = BIT(3), + IEEE80211_CHAN_NO_IR = BIT(4), + IEEE80211_CHAN_NO_HT40MINUS = BIT(5), + IEEE80211_CHAN_NO_HT40PLUS = BIT(6), + IEEE80211_CHAN_NO_80MHZ = BIT(7), + IEEE80211_CHAN_NO_160MHZ = BIT(8), + IEEE80211_CHAN_NO_OFDM = BIT(9), + IEEE80211_CHAN_NO_6GHZ_VLP_CLIENT = BIT(10), + IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT = BIT(11), + IEEE80211_CHAN_PSD = BIT(12), + IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP = BIT(13), + IEEE80211_CHAN_CAN_MONITOR = BIT(14), +}; +#define IEEE80211_CHAN_NO_HT40 (IEEE80211_CHAN_NO_HT40MINUS|IEEE80211_CHAN_NO_HT40PLUS) + +struct ieee80211_txrx_stypes { + uint16_t tx; + uint16_t rx; +}; + +/* + * net80211 has an ieee80211_channel as well; we use the linuxkpi_ version + * interally in LinuxKPI and re-define ieee80211_channel for the drivers + * at the end of the file. + */ +struct linuxkpi_ieee80211_channel { + uint32_t center_freq; + uint16_t hw_value; + enum ieee80211_channel_flags flags; + enum nl80211_band band; + bool beacon_found; + enum nl80211_dfs_state dfs_state; + unsigned int dfs_cac_ms; + int max_antenna_gain; + int max_power; + int max_reg_power; + uint32_t orig_flags; + int orig_mpwr; +}; + +struct cfg80211_bitrate_mask { + /* TODO FIXME */ + struct { + uint32_t legacy; + uint8_t ht_mcs[IEEE80211_HT_MCS_MASK_LEN]; + uint16_t vht_mcs[8]; + uint16_t he_mcs[8]; + enum nl80211_txrate_gi gi; + enum nl80211_he_gi he_gi; + uint8_t he_ltf; /* XXX enum? */ + } control[NUM_NL80211_BANDS]; +}; + +enum rate_info_bw { + RATE_INFO_BW_20 = 0, + RATE_INFO_BW_5, + RATE_INFO_BW_10, + RATE_INFO_BW_40, + RATE_INFO_BW_80, + RATE_INFO_BW_160, + RATE_INFO_BW_HE_RU, + RATE_INFO_BW_320, + RATE_INFO_BW_EHT_RU, +}; + +struct rate_info { + uint8_t flags; /* enum cfg80211_rate_info_flags */ + uint8_t bw; /* enum rate_info_bw */ + uint16_t legacy; + uint8_t mcs; + uint8_t nss; + uint8_t he_dcm; + uint8_t he_gi; + uint8_t he_ru_alloc; + uint8_t eht_gi; +}; + +struct ieee80211_rate { + uint32_t flags; /* enum ieee80211_rate_flags */ + uint16_t bitrate; + uint16_t hw_value; + uint16_t hw_value_short; +}; + +struct ieee80211_sta_ht_cap { + bool ht_supported; + uint8_t ampdu_density; + uint8_t ampdu_factor; + uint16_t cap; + struct ieee80211_mcs_info mcs; +}; + +/* XXX net80211 calls these IEEE80211_VHTCAP_* */ +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 /* IEEE80211_VHTCAP_MAX_MPDU_LENGTH_3895 */ +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 /* IEEE80211_VHTCAP_MAX_MPDU_LENGTH_7991 */ +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 /* IEEE80211_VHTCAP_MAX_MPDU_LENGTH_11454 */ +#define IEEE80211_VHT_CAP_MAX_MPDU_MASK 0x00000003 /* IEEE80211_VHTCAP_MAX_MPDU_MASK */ + +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ << IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK_S) +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80P80MHZ << IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK_S) +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK + +#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 /* IEEE80211_VHTCAP_RXLDPC */ + +#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 /* IEEE80211_VHTCAP_SHORT_GI_80 */ +#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 /* IEEE80211_VHTCAP_SHORT_GI_160 */ + +#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 /* IEEE80211_VHTCAP_TXSTBC */ + +#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 /* IEEE80211_VHTCAP_RXSTBC_1 */ +#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 /* IEEE80211_VHTCAP_RXSTBC_MASK */ + +#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 /* IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE */ + +#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 /* IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE */ + +#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 /* IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE */ + +#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 /* IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE */ + +#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 /* IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT */ +#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK (7 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT) /* IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK */ + +#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 /* IEEE80211_VHTCAP_HTC_VHT */ + +#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 /* IEEE80211_VHTCAP_RX_ANTENNA_PATTERN */ +#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 /* IEEE80211_VHTCAP_TX_ANTENNA_PATTERN */ + +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 /* IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB */ + +#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16 /* IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT */ +#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK \ + (7 << IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT) /* IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK */ + +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 /* IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT */ +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ + (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT) /* IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK */ + +#define IEEE80211_VHT_CAP_EXT_NSS_BW_MASK IEEE80211_VHTCAP_EXT_NSS_BW +#define IEEE80211_VHT_CAP_EXT_NSS_BW_SHIFT IEEE80211_VHTCAP_EXT_NSS_BW_S + +struct ieee80211_sta_vht_cap { + /* TODO FIXME */ + bool vht_supported; + uint32_t cap; + struct ieee80211_vht_mcs_info vht_mcs; +}; + +enum ieee80211_vht_opmode { + IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT = 4, +}; + +struct cfg80211_bss_ies { + uint8_t *data; + size_t len; +}; + +struct cfg80211_bss { + /* XXX TODO */ + struct cfg80211_bss_ies *ies; + struct cfg80211_bss_ies *beacon_ies; + uint64_t ts_boottime; + int32_t signal; +}; + +struct cfg80211_connect_resp_params { + /* XXX TODO */ + uint8_t *bssid; + const uint8_t *req_ie; + const uint8_t *resp_ie; + uint32_t req_ie_len; + uint32_t resp_ie_len; + int status; + struct { + const uint8_t *addr; + const uint8_t *bssid; + struct cfg80211_bss *bss; + uint16_t status; + } links[IEEE80211_MLD_MAX_NUM_LINKS]; +}; + +struct cfg80211_inform_bss { + /* XXX TODO */ + int boottime_ns, scan_width, signal; + struct linuxkpi_ieee80211_channel *chan; +}; + +struct cfg80211_roam_info { + /* XXX TODO */ + uint8_t *bssid; + const uint8_t *req_ie; + const uint8_t *resp_ie; + uint32_t req_ie_len; + uint32_t resp_ie_len; + struct linuxkpi_ieee80211_channel *channel; + struct { + const uint8_t *addr; + const uint8_t *bssid; + struct cfg80211_bss *bss; + struct linuxkpi_ieee80211_channel *channel; + } links[IEEE80211_MLD_MAX_NUM_LINKS]; +}; + +struct cfg80211_chan_def { + /* XXX TODO */ + struct linuxkpi_ieee80211_channel *chan; + enum nl80211_chan_width width; + uint32_t center_freq1; + uint32_t center_freq2; + uint16_t punctured; +}; + +struct cfg80211_ftm_responder_stats { + /* XXX TODO */ + int asap_num, failed_num, filled, non_asap_num, out_of_window_triggers_num, partial_num, reschedule_requests_num, success_num, total_duration_ms, unknown_triggers_num; +}; + +struct cfg80211_pmsr_capabilities { + /* XXX TODO */ + int max_peers, randomize_mac_addr, report_ap_tsf; + struct { + int asap, bandwidths, max_bursts_exponent, max_ftms_per_burst, non_asap, non_trigger_based, preambles, request_civicloc, request_lci, supported, trigger_based; + } ftm; +}; + +struct cfg80211_pmsr_ftm_request { + /* XXX TODO */ + int asap, burst_period, ftmr_retries, ftms_per_burst, non_trigger_based, num_bursts_exp, request_civicloc, request_lci, trigger_based; + uint8_t bss_color; + bool lmr_feedback; +}; + +struct cfg80211_pmsr_request_peer { + /* XXX TODO */ + struct cfg80211_chan_def chandef; + struct cfg80211_pmsr_ftm_request ftm; + uint8_t addr[ETH_ALEN]; + int report_ap_tsf; +}; + +struct cfg80211_pmsr_request { + /* XXX TODO */ + int cookie, n_peers, timeout; + uint8_t mac_addr[ETH_ALEN], mac_addr_mask[ETH_ALEN]; + struct cfg80211_pmsr_request_peer peers[]; +}; + +struct cfg80211_pmsr_ftm_result { + /* XXX TODO */ + int burst_index, busy_retry_time, failure_reason; + int num_ftmr_successes, rssi_avg, rssi_avg_valid, rssi_spread, rssi_spread_valid, rtt_avg, rtt_avg_valid, rtt_spread, rtt_spread_valid, rtt_variance, rtt_variance_valid; + uint8_t *lci; + uint8_t *civicloc; + int lci_len; + int civicloc_len; +}; + +struct cfg80211_pmsr_result { + /* XXX TODO */ + int ap_tsf, ap_tsf_valid, final, host_time, status, type; + uint8_t addr[ETH_ALEN]; + struct cfg80211_pmsr_ftm_result ftm; +}; + +struct cfg80211_sar_freq_ranges { + uint32_t start_freq; + uint32_t end_freq; +}; + +struct cfg80211_sar_sub_specs { + uint32_t freq_range_index; + int power; +}; + +struct cfg80211_sar_specs { + enum nl80211_sar_type type; + uint32_t num_sub_specs; + struct cfg80211_sar_sub_specs sub_specs[]; +}; + +struct cfg80211_sar_capa { + enum nl80211_sar_type type; + uint32_t num_freq_ranges; + const struct cfg80211_sar_freq_ranges *freq_ranges; +}; + +struct cfg80211_ssid { + int ssid_len; + uint8_t ssid[IEEE80211_MAX_SSID_LEN]; +}; + +struct cfg80211_scan_6ghz_params { + /* XXX TODO */ + uint8_t *bssid; + int channel_idx, psc_no_listen, short_ssid, short_ssid_valid, unsolicited_probe, psd_20; +}; + +struct cfg80211_match_set { + uint8_t bssid[ETH_ALEN]; + struct cfg80211_ssid ssid; + int rssi_thold; +}; + +struct cfg80211_scan_request { + /* XXX TODO */ + bool no_cck; + bool scan_6ghz; + bool duration_mandatory; + bool first_part; + int8_t tsf_report_link_id; + uint16_t duration; + uint32_t flags; + struct wireless_dev *wdev; + struct wiphy *wiphy; + uint64_t scan_start; + uint32_t rates[NUM_NL80211_BANDS]; + int ie_len; + uint8_t *ie; + uint8_t mac_addr[ETH_ALEN], mac_addr_mask[ETH_ALEN]; + uint8_t bssid[ETH_ALEN]; + int n_ssids; + int n_6ghz_params; + int n_channels; + struct cfg80211_ssid *ssids; + struct cfg80211_scan_6ghz_params *scan_6ghz_params; + struct linuxkpi_ieee80211_channel *channels[0]; +}; + +struct cfg80211_sched_scan_plan { + /* XXX TODO */ + int interval, iterations; +}; + +struct cfg80211_sched_scan_request { + /* XXX TODO */ + int delay, flags; + uint8_t mac_addr[ETH_ALEN], mac_addr_mask[ETH_ALEN]; + uint64_t reqid; + int n_match_sets; + int n_scan_plans; + int n_ssids; + int n_channels; + int ie_len; + uint8_t *ie; + struct cfg80211_match_set *match_sets; + struct cfg80211_sched_scan_plan *scan_plans; + struct cfg80211_ssid *ssids; + struct linuxkpi_ieee80211_channel *channels[0]; +}; + +struct cfg80211_scan_info { + uint64_t scan_start_tsf; + uint8_t tsf_bssid[ETH_ALEN]; + bool aborted; +}; + +struct cfg80211_beacon_data { + /* XXX TODO */ + const uint8_t *head; + const uint8_t *tail; + uint32_t head_len; + uint32_t tail_len; + const uint8_t *proberesp_ies; + const uint8_t *assocresp_ies; + uint32_t proberesp_ies_len; + uint32_t assocresp_ies_len; +}; + +struct cfg80211_ap_update { + /* XXX TODO */ + struct cfg80211_beacon_data beacon; +}; + +struct cfg80211_crypto_settings { + /* XXX TODO */ + enum nl80211_wpa_versions wpa_versions; + uint32_t cipher_group; /* WLAN_CIPHER_SUITE_* */ + uint32_t *akm_suites; + uint32_t *ciphers_pairwise; + const uint8_t *sae_pwd; + const uint8_t *psk; + int n_akm_suites; + int n_ciphers_pairwise; + int sae_pwd_len; +}; + +struct cfg80211_ap_settings { + /* XXX TODO */ + int auth_type, beacon_interval, dtim_period, hidden_ssid, inactivity_timeout; + const uint8_t *ssid; + size_t ssid_len; + struct cfg80211_beacon_data beacon; + struct cfg80211_chan_def chandef; + struct cfg80211_crypto_settings crypto; +}; + +struct cfg80211_bss_selection { + /* XXX TODO */ + enum nl80211_bss_select_attr behaviour; + union { + enum nl80211_band band_pref; + struct { + enum nl80211_band band; + uint8_t delta; + } adjust; + } param; +}; + +struct cfg80211_connect_params { + /* XXX TODO */ + struct linuxkpi_ieee80211_channel *channel; + struct linuxkpi_ieee80211_channel *channel_hint; + uint8_t *bssid; + uint8_t *bssid_hint; + const uint8_t *ie; + const uint8_t *ssid; + uint32_t ie_len; + uint32_t ssid_len; + const void *key; + uint32_t key_len; + int auth_type, key_idx, privacy, want_1x; + struct cfg80211_bss_selection bss_select; + struct cfg80211_crypto_settings crypto; +}; + +enum bss_param_flags { /* Used as bitflags. XXX FIXME values? */ + BSS_PARAM_FLAGS_CTS_PROT = 0x01, + BSS_PARAM_FLAGS_SHORT_PREAMBLE = 0x02, + BSS_PARAM_FLAGS_SHORT_SLOT_TIME = 0x04, +}; + +struct cfg80211_ibss_params { + /* XXX TODO */ + int basic_rates, beacon_interval; + int channel_fixed, ie, ie_len, privacy; + int dtim_period; + uint8_t *ssid; + uint8_t *bssid; + int ssid_len; + struct cfg80211_chan_def chandef; + enum bss_param_flags flags; +}; + +struct cfg80211_mgmt_tx_params { + /* XXX TODO */ + struct linuxkpi_ieee80211_channel *chan; + const uint8_t *buf; + size_t len; + int wait; +}; + +struct cfg80211_external_auth_params { + uint8_t bssid[ETH_ALEN]; + uint16_t status; + enum nl80211_external_auth_action action; + unsigned int key_mgmt_suite; + struct cfg80211_ssid ssid; +}; + +struct cfg80211_pmk_conf { + /* XXX TODO */ + const uint8_t *pmk; + uint8_t pmk_len; +}; + +struct cfg80211_pmksa { + /* XXX TODO */ + const uint8_t *bssid; + const uint8_t *pmkid; + const uint8_t *ssid; + size_t ssid_len; +}; + +struct station_del_parameters { + /* XXX TODO */ + const uint8_t *mac; + uint32_t reason_code; /* elsewhere uint16_t? */ +}; + +struct station_info { + uint64_t filled; /* enum nl80211_sta_info */ + uint32_t connected_time; + uint32_t inactive_time; + + uint64_t rx_bytes; + uint32_t rx_packets; + uint32_t rx_dropped_misc; + + uint64_t rx_duration; + uint32_t rx_beacon; + uint8_t rx_beacon_signal_avg; + + int8_t signal; + int8_t signal_avg; + int8_t ack_signal; + int8_t avg_ack_signal; + + /* gap */ + int generation; + + uint64_t tx_bytes; + uint32_t tx_packets; + uint32_t tx_failed; + uint64_t tx_duration; + uint32_t tx_retries; + + int chains; + uint8_t chain_signal[IEEE80211_MAX_CHAINS]; + uint8_t chain_signal_avg[IEEE80211_MAX_CHAINS]; + + uint8_t *assoc_req_ies; + size_t assoc_req_ies_len; + + struct rate_info rxrate; + struct rate_info txrate; + struct cfg80211_ibss_params bss_param; + struct nl80211_sta_flag_update sta_flags; +}; + +struct station_parameters { + /* XXX TODO */ + int sta_flags_mask, sta_flags_set; +}; + +struct key_params { + /* XXX TODO */ + const uint8_t *key; + const uint8_t *seq; + int key_len; + int seq_len; + uint32_t cipher; /* WLAN_CIPHER_SUITE_* */ +}; + +struct mgmt_frame_regs { + /* XXX TODO */ + int interface_stypes; +}; + +struct vif_params { + /* XXX TODO */ + uint8_t macaddr[ETH_ALEN]; +}; + +/* That the world needs so many different structs for this is amazing. */ +struct mac_address { + uint8_t addr[ETH_ALEN]; +}; + +struct ieee80211_reg_rule { + /* TODO FIXME */ + uint32_t flags; + int dfs_cac_ms; + struct freq_range { + int start_freq_khz; + int end_freq_khz; + int max_bandwidth_khz; + } freq_range; + struct power_rule { + int max_antenna_gain; + int max_eirp; + } power_rule; +}; + +struct linuxkpi_ieee80211_regdomain { + /* TODO FIXME */ + uint8_t alpha2[2]; + int dfs_region; + int n_reg_rules; + struct ieee80211_reg_rule reg_rules[]; +}; + +#define IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS 0x01 +#define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454 0x02 +#define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK 0x03 +#define IEEE80211_EHT_MAC_CAP0_OM_CONTROL 0x04 +#define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 0x05 +#define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 0x06 +#define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991 0x07 +#define IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC 0x08 + +#define IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK 0x01 + +#define IEEE80211_EHT_MCS_NSS_RX 0x01 +#define IEEE80211_EHT_MCS_NSS_TX 0x02 + +#define IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ 0x01 +#define IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ 0x02 +#define IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK 0x03 +#define IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI 0x04 +#define IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO 0x05 +#define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE 0x06 +#define IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER 0x07 + +#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK 0x01 +#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK 0x02 +#define IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK 0x03 + +#define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK 0x01 +#define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK 0x02 +#define IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK 0x03 + +#define IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK 0x01 +#define IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK 0x02 +#define IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK 0x03 +#define IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK 0x04 +#define IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK 0x05 +#define IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK 0x06 +#define IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK 0x07 +#define IEEE80211_EHT_PHY_CAP3_SOUNDING_DIM_320MHZ_MASK 0x08 + +#define IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI 0x01 +#define IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO 0x02 +#define IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP 0x03 +#define IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK 0x04 + +#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_0US 0x01 +#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US 0x02 +#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_20US 0x03 +#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_8US 0x04 +#define IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK 0x05 +#define IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK 0x06 +#define IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT 0x07 +#define IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP 0x08 +#define IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP 0x09 +#define IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK 0x0a +#define IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF 0x0b + +#define IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP 0x01 +#define IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK 0x02 +#define IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK 0x03 + +#define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ 0x01 +#define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ 0x02 +#define IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ 0x03 +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ 0x04 +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ 0x05 +#define IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ 0x06 + +#define IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA 0x01 +#define IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA 0x02 + +#define IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE 0x01 +#define IEEE80211_EHT_PPE_THRES_NSS_MASK 0x02 +#define IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK 0x03 +#define IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE 0x04 + +#define IEEE80211_EML_CAP_EMLSR_SUPP 0x01 +#define IEEE80211_EML_CAP_TRANSITION_TIMEOUT 0x02 +#define IEEE80211_EML_CAP_TRANSITION_TIMEOUT_128TU 0x04 +#define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY 0x08 +#define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_32US 0x10 +#define IEEE80211_EML_CAP_EMLSR_PADDING_DELAY_256US 0x10 +#define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY 0x20 +#define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_64US 0x40 +#define IEEE80211_EML_CAP_EMLSR_TRANSITION_DELAY_256US 0x40 + +#define VENDOR_CMD_RAW_DATA (void *)(uintptr_t)(-ENOENT) + +/* net80211::net80211_he_cap */ +struct ieee80211_sta_he_cap { + bool has_he; + struct ieee80211_he_cap_elem he_cap_elem; + struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; + uint8_t ppe_thres[IEEE80211_HE_CAP_PPE_THRES_MAX]; +}; + +struct cfg80211_he_bss_color { + int color, enabled; +}; + +struct ieee80211_he_obss_pd { + bool enable; + uint8_t min_offset; + uint8_t max_offset; + uint8_t non_srg_max_offset; + uint8_t sr_ctrl; + uint8_t bss_color_bitmap[8]; + uint8_t partial_bssid_bitmap[8]; +}; + +struct ieee80211_eht_mcs_nss_supp_20mhz_only { + union { + struct { + uint8_t rx_tx_mcs7_max_nss; + uint8_t rx_tx_mcs9_max_nss; + uint8_t rx_tx_mcs11_max_nss; + uint8_t rx_tx_mcs13_max_nss; + }; + uint8_t rx_tx_max_nss[4]; + }; +}; + +struct ieee80211_eht_mcs_nss_supp_bw { + union { + struct { + uint8_t rx_tx_mcs9_max_nss; + uint8_t rx_tx_mcs11_max_nss; + uint8_t rx_tx_mcs13_max_nss; + }; + uint8_t rx_tx_max_nss[3]; + }; +}; + +struct ieee80211_eht_cap_elem_fixed { + uint8_t mac_cap_info[2]; + uint8_t phy_cap_info[9]; +}; + +struct ieee80211_eht_mcs_nss_supp { + /* TODO FIXME */ + /* Can only have either or... */ + union { + struct ieee80211_eht_mcs_nss_supp_20mhz_only only_20mhz; + struct { + struct ieee80211_eht_mcs_nss_supp_bw _80; + struct ieee80211_eht_mcs_nss_supp_bw _160; + struct ieee80211_eht_mcs_nss_supp_bw _320; + } bw; + }; +}; + +#define IEEE80211_STA_EHT_PPE_THRES_MAX 32 +struct ieee80211_sta_eht_cap { + bool has_eht; + struct ieee80211_eht_cap_elem_fixed eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp eht_mcs_nss_supp; + uint8_t eht_ppe_thres[IEEE80211_STA_EHT_PPE_THRES_MAX]; +}; + +struct ieee80211_sband_iftype_data { + /* TODO FIXME */ + enum nl80211_iftype types_mask; + struct ieee80211_sta_he_cap he_cap; + struct ieee80211_he_6ghz_capa he_6ghz_capa; + struct ieee80211_sta_eht_cap eht_cap; + struct { + const uint8_t *data; + size_t len; + } vendor_elems; +}; + +struct ieee80211_supported_band { + /* TODO FIXME */ + struct linuxkpi_ieee80211_channel *channels; + struct ieee80211_rate *bitrates; + struct ieee80211_sband_iftype_data *iftype_data; + int n_channels; + int n_bitrates; + int n_iftype_data; + enum nl80211_band band; + struct ieee80211_sta_ht_cap ht_cap; + struct ieee80211_sta_vht_cap vht_cap; +}; + +struct cfg80211_pkt_pattern { + /* XXX TODO */ + uint8_t *mask; + uint8_t *pattern; + int pattern_len; + int pkt_offset; +}; + +struct cfg80211_wowlan_nd_match { + /* XXX TODO */ + struct cfg80211_ssid ssid; + int n_channels; + uint32_t channels[0]; /* freq! = ieee80211_channel_to_frequency() */ +}; + +struct cfg80211_wowlan_nd_info { + /* XXX TODO */ + int n_matches; + struct cfg80211_wowlan_nd_match *matches[0]; +}; + +enum wiphy_wowlan_support_flags { + WIPHY_WOWLAN_DISCONNECT, + WIPHY_WOWLAN_MAGIC_PKT, + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY, + WIPHY_WOWLAN_GTK_REKEY_FAILURE, + WIPHY_WOWLAN_EAP_IDENTITY_REQ, + WIPHY_WOWLAN_4WAY_HANDSHAKE, + WIPHY_WOWLAN_RFKILL_RELEASE, + WIPHY_WOWLAN_NET_DETECT, +}; + +struct wiphy_wowlan_support { + /* XXX TODO */ + enum wiphy_wowlan_support_flags flags; + int max_nd_match_sets, max_pkt_offset, n_patterns, pattern_max_len, pattern_min_len; +}; + +struct cfg80211_wowlan_wakeup { + /* XXX TODO */ + uint16_t pattern_idx; + bool disconnect; + bool unprot_deauth_disassoc; + bool eap_identity_req; + bool four_way_handshake; + bool gtk_rekey_failure; + bool magic_pkt; + bool rfkill_release; + bool tcp_connlost; + bool tcp_nomoretokens; + bool tcp_match; + bool packet_80211; + struct cfg80211_wowlan_nd_info *net_detect; + uint8_t *packet; + uint16_t packet_len; + uint16_t packet_present_len; +}; + +struct cfg80211_wowlan { + /* XXX TODO */ + bool any; + bool disconnect; + bool magic_pkt; + bool gtk_rekey_failure; + bool eap_identity_req; + bool four_way_handshake; + bool rfkill_release; + + /* Magic packet patterns. */ + int n_patterns; + struct cfg80211_pkt_pattern *patterns; + + /* netdetect? if not assoc? */ + struct cfg80211_sched_scan_request *nd_config; + + void *tcp; /* XXX ? */ +}; + +struct cfg80211_gtk_rekey_data { + /* XXX TODO */ + const uint8_t *kck, *kek, *replay_ctr; + uint32_t akm; + uint8_t kck_len, kek_len; +}; + +struct cfg80211_tid_cfg { + /* XXX TODO */ + int mask, noack, retry_long, rtscts, tids, amsdu, ampdu; + enum nl80211_tx_rate_setting txrate_type; + struct cfg80211_bitrate_mask txrate_mask; +}; + +struct cfg80211_tid_config { + /* XXX TODO */ + int n_tid_conf; + struct cfg80211_tid_cfg tid_conf[0]; +}; + +struct ieee80211_iface_limit { + /* TODO FIXME */ + int max, types; +}; + +struct ieee80211_iface_combination { + /* TODO FIXME */ + const struct ieee80211_iface_limit *limits; + int n_limits; + int max_interfaces, num_different_channels; + int beacon_int_infra_match, beacon_int_min_gcd; + int radar_detect_widths; +}; + +struct iface_combination_params { + int num_different_channels; + int iftype_num[NUM_NL80211_IFTYPES]; +}; + +struct regulatory_request { + /* XXX TODO */ + uint8_t alpha2[2]; + enum environment_cap country_ie_env; + int initiator, dfs_region; + int user_reg_hint_type; +}; + +struct cfg80211_set_hw_timestamp { + const uint8_t *macaddr; + bool enable; +}; + +struct survey_info { /* net80211::struct ieee80211_channel_survey */ + /* TODO FIXME */ + uint32_t filled; +#define SURVEY_INFO_TIME 0x0001 +#define SURVEY_INFO_TIME_RX 0x0002 +#define SURVEY_INFO_TIME_SCAN 0x0004 +#define SURVEY_INFO_TIME_TX 0x0008 +#define SURVEY_INFO_TIME_BSS_RX 0x0010 +#define SURVEY_INFO_TIME_BUSY 0x0020 +#define SURVEY_INFO_IN_USE 0x0040 +#define SURVEY_INFO_NOISE_DBM 0x0080 + uint32_t noise; + uint64_t time; + uint64_t time_bss_rx; + uint64_t time_busy; + uint64_t time_rx; + uint64_t time_scan; + uint64_t time_tx; + struct linuxkpi_ieee80211_channel *channel; +}; + +enum wiphy_vendor_cmd_need_flags { + WIPHY_VENDOR_CMD_NEED_NETDEV = 0x01, + WIPHY_VENDOR_CMD_NEED_RUNNING = 0x02, + WIPHY_VENDOR_CMD_NEED_WDEV = 0x04, +}; + +struct wiphy_vendor_command { + struct { + uint32_t vendor_id; + uint32_t subcmd; + }; + uint32_t flags; + void *policy; + int (*doit)(struct wiphy *, struct wireless_dev *, const void *, int); +}; + +struct wiphy_iftype_ext_capab { + /* TODO FIXME */ + enum nl80211_iftype iftype; + const uint8_t *extended_capabilities; + const uint8_t *extended_capabilities_mask; + uint8_t extended_capabilities_len; + uint16_t eml_capabilities; + uint16_t mld_capa_and_ops; +}; + +struct tid_config_support { + /* TODO FIXME */ + uint64_t vif; /* enum nl80211_tid_cfg_attr */ + uint64_t peer; /* enum nl80211_tid_cfg_attr */ +}; + +enum cfg80211_regulatory { + REGULATORY_CUSTOM_REG = BIT(0), + REGULATORY_STRICT_REG = BIT(1), + REGULATORY_DISABLE_BEACON_HINTS = BIT(2), + REGULATORY_ENABLE_RELAX_NO_IR = BIT(3), + REGULATORY_WIPHY_SELF_MANAGED = BIT(4), + REGULATORY_COUNTRY_IE_IGNORE = BIT(5), + REGULATORY_COUNTRY_IE_FOLLOW_POWER = BIT(6), +}; + +struct wiphy_radio_freq_range { + uint32_t start_freq; + uint32_t end_freq; +}; + +struct wiphy_radio { + int n_freq_range; + int n_iface_combinations; + const struct wiphy_radio_freq_range *freq_range; + const struct ieee80211_iface_combination *iface_combinations; +}; + +enum wiphy_flags { + WIPHY_FLAG_AP_UAPSD = BIT(0), + WIPHY_FLAG_HAS_CHANNEL_SWITCH = BIT(1), + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(2), + WIPHY_FLAG_HAVE_AP_SME = BIT(3), + WIPHY_FLAG_IBSS_RSN = BIT(4), + WIPHY_FLAG_NETNS_OK = BIT(5), + WIPHY_FLAG_OFFCHAN_TX = BIT(6), + WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(7), + WIPHY_FLAG_SPLIT_SCAN_6GHZ = BIT(8), + WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK = BIT(9), + WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(10), + WIPHY_FLAG_SUPPORTS_TDLS = BIT(11), + WIPHY_FLAG_TDLS_EXTERNAL_SETUP = BIT(12), + WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(13), + WIPHY_FLAG_4ADDR_AP = BIT(14), + WIPHY_FLAG_4ADDR_STATION = BIT(15), + WIPHY_FLAG_SUPPORTS_MLO = BIT(16), + WIPHY_FLAG_DISABLE_WEXT = BIT(17), +}; + +struct wiphy_work; +typedef void (*wiphy_work_fn)(struct wiphy *, struct wiphy_work *); +struct wiphy_work { + struct list_head entry; + wiphy_work_fn fn; +}; +struct wiphy_delayed_work { + struct wiphy_work work; + struct wiphy *wiphy; + struct timer_list timer; +}; + +struct wiphy { + struct mutex mtx; + struct device *dev; + struct mac_address *addresses; + int n_addresses; + uint32_t flags; + struct ieee80211_supported_band *bands[NUM_NL80211_BANDS]; + uint8_t perm_addr[ETH_ALEN]; + uint16_t max_scan_ie_len; + + /* XXX TODO */ + const struct cfg80211_pmsr_capabilities *pmsr_capa; + const struct cfg80211_sar_capa *sar_capa; + const struct wiphy_iftype_ext_capab *iftype_ext_capab; + const struct linuxkpi_ieee80211_regdomain *regd; + char fw_version[ETHTOOL_FWVERS_LEN]; + const struct ieee80211_iface_combination *iface_combinations; + const uint32_t *cipher_suites; + int n_iface_combinations; + int n_cipher_suites; + void(*reg_notifier)(struct wiphy *, struct regulatory_request *); + enum cfg80211_regulatory regulatory_flags; + int n_vendor_commands; + const struct wiphy_vendor_command *vendor_commands; + const struct ieee80211_txrx_stypes *mgmt_stypes; + uint32_t rts_threshold; + uint32_t frag_threshold; + struct tid_config_support tid_config_support; + uint8_t available_antennas_rx; + uint8_t available_antennas_tx; + + int n_radio; + const struct wiphy_radio *radio; + + int features, hw_version; + int interface_modes, max_match_sets, max_remain_on_channel_duration, max_scan_ssids, max_sched_scan_ie_len, max_sched_scan_plan_interval, max_sched_scan_plan_iterations, max_sched_scan_plans, max_sched_scan_reqs, max_sched_scan_ssids; + int num_iftype_ext_capab; + int max_ap_assoc_sta, probe_resp_offload, software_iftypes; + int bss_select_support, max_num_pmkids, retry_long, retry_short, signal_type; + int max_data_retry_count; + int tx_queue_len, rfkill; + int mbssid_max_interfaces; + int hw_timestamp_max_peers; + int ema_max_profile_periodicity; + + unsigned long ext_features[BITS_TO_LONGS(NUM_NL80211_EXT_FEATURES)]; + struct dentry *debugfsdir; + + const struct wiphy_wowlan_support *wowlan; + struct cfg80211_wowlan *wowlan_config; + /* Lower layer (driver/mac80211) specific data. */ + /* Must stay last. */ + uint8_t priv[0] __aligned(CACHE_LINE_SIZE); +}; + +#define lockdep_assert_wiphy(wiphy) \ + lockdep_assert_held(&(wiphy)->mtx) + +struct wireless_dev { + /* XXX TODO, like ic? */ + enum nl80211_iftype iftype; + uint32_t radio_mask; + uint8_t address[ETH_ALEN]; + struct net_device *netdev; + struct wiphy *wiphy; +}; + +struct cfg80211_ops { + /* XXX TODO */ + struct wireless_dev *(*add_virtual_intf)(struct wiphy *, const char *, unsigned char, enum nl80211_iftype, struct vif_params *); + int (*del_virtual_intf)(struct wiphy *, struct wireless_dev *); + int (*change_virtual_intf)(struct wiphy *, struct net_device *, enum nl80211_iftype, struct vif_params *); + int (*scan)(struct wiphy *, struct cfg80211_scan_request *); + int (*set_wiphy_params)(struct wiphy *, int, uint32_t); + int (*join_ibss)(struct wiphy *, struct net_device *, struct cfg80211_ibss_params *); + int (*leave_ibss)(struct wiphy *, struct net_device *); + int (*get_station)(struct wiphy *, struct net_device *, const uint8_t *, struct station_info *); + int (*dump_station)(struct wiphy *, struct net_device *, int, uint8_t *, struct station_info *); + int (*set_tx_power)(struct wiphy *, struct wireless_dev *, int, enum nl80211_tx_power_setting, int); + int (*get_tx_power)(struct wiphy *, struct wireless_dev *, int, unsigned int, int *); + int (*add_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, const uint8_t *, struct key_params *); + int (*del_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, const uint8_t *); + int (*get_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, const uint8_t *, void *, void(*)(void *, struct key_params *)); + int (*set_default_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, bool); + int (*set_default_mgmt_key)(struct wiphy *, struct net_device *, int, uint8_t); + int (*set_power_mgmt)(struct wiphy *, struct net_device *, bool, int); + int (*connect)(struct wiphy *, struct net_device *, struct cfg80211_connect_params *); + int (*disconnect)(struct wiphy *, struct net_device *, uint16_t); + int (*suspend)(struct wiphy *, struct cfg80211_wowlan *); + int (*resume)(struct wiphy *); + int (*set_pmksa)(struct wiphy *, struct net_device *, struct cfg80211_pmksa *); + int (*del_pmksa)(struct wiphy *, struct net_device *, struct cfg80211_pmksa *); + int (*flush_pmksa)(struct wiphy *, struct net_device *); + int (*start_ap)(struct wiphy *, struct net_device *, struct cfg80211_ap_settings *); + int (*stop_ap)(struct wiphy *, struct net_device *, unsigned int); + int (*change_beacon)(struct wiphy *, struct net_device *, struct cfg80211_ap_update *); + int (*del_station)(struct wiphy *, struct net_device *, struct station_del_parameters *); + int (*change_station)(struct wiphy *, struct net_device *, const uint8_t *, struct station_parameters *); + int (*sched_scan_start)(struct wiphy *, struct net_device *, struct cfg80211_sched_scan_request *); + int (*sched_scan_stop)(struct wiphy *, struct net_device *, uint64_t); + void (*update_mgmt_frame_registrations)(struct wiphy *, struct wireless_dev *, struct mgmt_frame_regs *); + int (*mgmt_tx)(struct wiphy *, struct wireless_dev *, struct cfg80211_mgmt_tx_params *, uint64_t *); + int (*cancel_remain_on_channel)(struct wiphy *, struct wireless_dev *, uint64_t); + int (*get_channel)(struct wiphy *, struct wireless_dev *, unsigned int, struct cfg80211_chan_def *); + int (*crit_proto_start)(struct wiphy *, struct wireless_dev *, enum nl80211_crit_proto_id, uint16_t); + void (*crit_proto_stop)(struct wiphy *, struct wireless_dev *); + int (*tdls_oper)(struct wiphy *, struct net_device *, const uint8_t *, enum nl80211_tdls_operation); + int (*update_connect_params)(struct wiphy *, struct net_device *, struct cfg80211_connect_params *, uint32_t); + int (*set_pmk)(struct wiphy *, struct net_device *, const struct cfg80211_pmk_conf *); + int (*del_pmk)(struct wiphy *, struct net_device *, const uint8_t *); + int (*remain_on_channel)(struct wiphy *, struct wireless_dev *, struct linuxkpi_ieee80211_channel *, unsigned int, uint64_t *); + int (*start_p2p_device)(struct wiphy *, struct wireless_dev *); + void (*stop_p2p_device)(struct wiphy *, struct wireless_dev *); + int (*dump_survey)(struct wiphy *, struct net_device *, int, struct survey_info *); + int (*external_auth)(struct wiphy *, struct net_device *, struct cfg80211_external_auth_params *); + int (*set_cqm_rssi_range_config)(struct wiphy *, struct net_device *, int, int); + +}; + + +/* -------------------------------------------------------------------------- */ + +/* linux_80211.c */ + +struct wiphy *linuxkpi_wiphy_new(const struct cfg80211_ops *, size_t); +void linuxkpi_wiphy_free(struct wiphy *wiphy); + +void linuxkpi_wiphy_work_queue(struct wiphy *, struct wiphy_work *); +void linuxkpi_wiphy_work_cancel(struct wiphy *, struct wiphy_work *); +void linuxkpi_wiphy_work_flush(struct wiphy *, struct wiphy_work *); +void lkpi_wiphy_delayed_work_timer(struct timer_list *); +void linuxkpi_wiphy_delayed_work_queue(struct wiphy *, + struct wiphy_delayed_work *, unsigned long); +void linuxkpi_wiphy_delayed_work_cancel(struct wiphy *, + struct wiphy_delayed_work *); +void linuxkpi_wiphy_delayed_work_flush(struct wiphy *, + struct wiphy_delayed_work *); + +int linuxkpi_regulatory_set_wiphy_regd_sync(struct wiphy *wiphy, + struct linuxkpi_ieee80211_regdomain *regd); +uint32_t linuxkpi_cfg80211_calculate_bitrate(struct rate_info *); +uint32_t linuxkpi_ieee80211_channel_to_frequency(uint32_t, enum nl80211_band); +uint32_t linuxkpi_ieee80211_frequency_to_channel(uint32_t, uint32_t); +struct linuxkpi_ieee80211_channel * + linuxkpi_ieee80211_get_channel(struct wiphy *, uint32_t); +struct cfg80211_bss *linuxkpi_cfg80211_get_bss(struct wiphy *, + struct linuxkpi_ieee80211_channel *, const uint8_t *, + const uint8_t *, size_t, enum ieee80211_bss_type, enum ieee80211_privacy); +void linuxkpi_cfg80211_put_bss(struct wiphy *, struct cfg80211_bss *); +void linuxkpi_cfg80211_bss_flush(struct wiphy *); +struct linuxkpi_ieee80211_regdomain * + lkpi_get_linuxkpi_ieee80211_regdomain(size_t); + +/* -------------------------------------------------------------------------- */ + +static __inline struct wiphy * +wiphy_new(const struct cfg80211_ops *ops, size_t priv_len) +{ + + return (linuxkpi_wiphy_new(ops, priv_len)); +} + +static __inline void +wiphy_free(struct wiphy *wiphy) +{ + + linuxkpi_wiphy_free(wiphy); +} + +static __inline void * +wiphy_priv(struct wiphy *wiphy) +{ + + return (wiphy->priv); +} + +static __inline void +set_wiphy_dev(struct wiphy *wiphy, struct device *dev) +{ + + wiphy->dev = dev; +} + +static __inline struct device * +wiphy_dev(struct wiphy *wiphy) +{ + + return (wiphy->dev); +} + +#define wiphy_dereference(_w, p) \ + rcu_dereference_check(p, lockdep_is_held(&(_w)->mtx)) + +#define wiphy_lock(_w) mutex_lock(&(_w)->mtx) +#define wiphy_unlock(_w) mutex_unlock(&(_w)->mtx) + +static __inline void +wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked, + enum rfkill_hard_block_reasons reason) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +static inline int +cfg80211_register_netdevice(struct net_device *ndev) +{ + TODO(); + return (-ENXIO); +} + +static inline void +cfg80211_unregister_netdevice(struct net_device *ndev) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +static inline struct cfg80211_bss * +cfg80211_get_bss(struct wiphy *wiphy, struct linuxkpi_ieee80211_channel *chan, + const uint8_t *bssid, const uint8_t *ssid, size_t ssid_len, + enum ieee80211_bss_type bss_type, enum ieee80211_privacy privacy) +{ + + return (linuxkpi_cfg80211_get_bss(wiphy, chan, bssid, ssid, ssid_len, + bss_type, privacy)); +} + +static inline void +cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss) +{ + + linuxkpi_cfg80211_put_bss(wiphy, bss); +} + +static inline void +cfg80211_bss_flush(struct wiphy *wiphy) +{ + + linuxkpi_cfg80211_bss_flush(wiphy); +} + +/* -------------------------------------------------------------------------- */ + +static __inline bool +rfkill_blocked(int rfkill) /* argument type? */ +{ + TODO(); + return (false); +} + +static __inline bool +rfkill_soft_blocked(int rfkill) +{ + TODO(); + return (false); +} + +static __inline void +wiphy_rfkill_start_polling(struct wiphy *wiphy) +{ + TODO(); +} + +static __inline void +wiphy_rfkill_stop_polling(struct wiphy *wiphy) +{ + TODO(); +} + +static __inline int +reg_query_regdb_wmm(uint8_t *alpha2, uint32_t center_freq, + struct ieee80211_reg_rule *rule) +{ + + IMPROVE("regdomain.xml needs to grow wmm information for at least ETSI"); + + return (-ENODATA); +} + +static __inline const uint8_t * +cfg80211_find_ie_match(uint32_t f, const uint8_t *ies, size_t ies_len, + const uint8_t *match, int x, int y) +{ + TODO(); + return (NULL); +} + +static __inline const uint8_t * +cfg80211_find_ie(uint8_t eid, const uint8_t *ie, uint32_t ielen) +{ + TODO(); + return (NULL); +} + +static __inline void +cfg80211_pmsr_complete(struct wireless_dev *wdev, + struct cfg80211_pmsr_request *req, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_pmsr_report(struct wireless_dev *wdev, + struct cfg80211_pmsr_request *req, + struct cfg80211_pmsr_result *result, gfp_t gfp) +{ + TODO(); +} + +static inline int +nl80211_chan_width_to_mhz(enum nl80211_chan_width width) +{ + switch (width) { + case NL80211_CHAN_WIDTH_5: + return (5); + break; + case NL80211_CHAN_WIDTH_10: + return (10); + break; + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + return (20); + break; + case NL80211_CHAN_WIDTH_40: + return (40); + break; + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_80P80: + return (80); + break; + case NL80211_CHAN_WIDTH_160: + return (160); + break; + case NL80211_CHAN_WIDTH_320: + return (320); + break; + } +} + +static inline void +cfg80211_chandef_create(struct cfg80211_chan_def *chandef, + struct linuxkpi_ieee80211_channel *chan, enum nl80211_channel_type chan_type) +{ + + KASSERT(chandef != NULL, ("%s: chandef is NULL\n", __func__)); + KASSERT(chan != NULL, ("%s: chan is NULL\n", __func__)); + + /* memset(chandef, 0, sizeof(*chandef)); */ + chandef->chan = chan; + chandef->center_freq1 = chan->center_freq; + /* chandef->width, center_freq2, punctured */ + + switch (chan_type) { + case NL80211_CHAN_NO_HT: + chandef->width = NL80211_CHAN_WIDTH_20_NOHT; + break; + case NL80211_CHAN_HT20: + chandef->width = NL80211_CHAN_WIDTH_20; + break; + case NL80211_CHAN_HT40MINUS: + chandef->width = NL80211_CHAN_WIDTH_40; + chandef->center_freq1 -= 10; + break; + case NL80211_CHAN_HT40PLUS: + chandef->width = NL80211_CHAN_WIDTH_40; + chandef->center_freq1 += 10; + break; + }; +} + +static __inline bool +cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) +{ + TODO(); + return (false); +} + +static inline int +cfg80211_chandef_get_width(const struct cfg80211_chan_def *chandef) +{ + return (nl80211_chan_width_to_mhz(chandef->width)); +} + +static __inline bool +cfg80211_chandef_dfs_usable(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef) +{ + TODO(); + return (false); +} + +static __inline unsigned int +cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef) +{ + TODO(); + return (0); +} + +static __inline bool +cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef_1, + const struct cfg80211_chan_def *chandef_2) +{ + TODO(); + return (false); +} + +static __inline bool +cfg80211_chandef_usable(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, uint32_t flags) +{ + TODO(); + return (false); +} + +static __inline void +cfg80211_bss_iter(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, + void (*iterfunc)(struct wiphy *, struct cfg80211_bss *, void *), void *data) +{ + TODO(); +} + +struct element { + uint8_t id; + uint8_t datalen; + uint8_t data[0]; +} __packed; + +static inline const struct element * +lkpi_cfg80211_find_elem_pattern(enum ieee80211_eid eid, + const uint8_t *data, size_t len, uint8_t *pattern, size_t plen) +{ + const struct element *elem; + const uint8_t *p; + size_t ielen; + + p = data; + elem = (const struct element *)p; + ielen = len; + while (elem != NULL && ielen > 1) { + if ((2 + elem->datalen) > ielen) + /* Element overruns our memory. */ + return (NULL); + if (elem->id == eid) { + if (pattern == NULL) + return (elem); + if (elem->datalen >= plen && + memcmp(elem->data, pattern, plen) == 0) + return (elem); + } + ielen -= 2 + elem->datalen; + p += 2 + elem->datalen; + elem = (const struct element *)p; + } + + return (NULL); +} + +static inline const struct element * +cfg80211_find_elem(enum ieee80211_eid eid, const uint8_t *data, size_t len) +{ + + return (lkpi_cfg80211_find_elem_pattern(eid, data, len, NULL, 0)); +} + +static inline const struct element * +ieee80211_bss_get_elem(struct cfg80211_bss *bss, uint32_t eid) +{ + + if (bss->ies == NULL) + return (NULL); + return (cfg80211_find_elem(eid, bss->ies->data, bss->ies->len)); +} + +static inline const uint8_t * +ieee80211_bss_get_ie(struct cfg80211_bss *bss, uint32_t eid) +{ + + return ((const uint8_t *)ieee80211_bss_get_elem(bss, eid)); +} + +static inline uint8_t * +cfg80211_find_vendor_ie(unsigned int oui, int oui_type, + uint8_t *data, size_t len) +{ + const struct element *elem; + uint8_t pattern[4] = { oui << 16, oui << 8, oui, oui_type }; + uint8_t plen = 4; /* >= 3? oui_type always part of this? */ + IMPROVE("plen currently always incl. oui_type"); + + elem = lkpi_cfg80211_find_elem_pattern(IEEE80211_ELEMID_VENDOR, + data, len, pattern, plen); + if (elem == NULL) + return (NULL); + return (__DECONST(uint8_t *, elem)); +} + +static inline uint32_t +cfg80211_calculate_bitrate(struct rate_info *rate) +{ + return (linuxkpi_cfg80211_calculate_bitrate(rate)); +} + +static __inline uint32_t +ieee80211_channel_to_frequency(uint32_t channel, enum nl80211_band band) +{ + + return (linuxkpi_ieee80211_channel_to_frequency(channel, band)); +} + +static __inline uint32_t +ieee80211_frequency_to_channel(uint32_t freq) +{ + + return (linuxkpi_ieee80211_frequency_to_channel(freq, 0)); +} + +static __inline int +regulatory_set_wiphy_regd_sync(struct wiphy *wiphy, + struct linuxkpi_ieee80211_regdomain *regd) +{ + IMPROVE(); + return (linuxkpi_regulatory_set_wiphy_regd_sync(wiphy, regd)); +} + +static __inline int +regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, + struct linuxkpi_ieee80211_regdomain *regd) +{ + + IMPROVE(); + return (linuxkpi_regulatory_set_wiphy_regd_sync(wiphy, regd)); +} + +static __inline int +regulatory_set_wiphy_regd(struct wiphy *wiphy, + struct linuxkpi_ieee80211_regdomain *regd) +{ + + IMPROVE(); + if (regd == NULL) + return (EINVAL); + + /* XXX-BZ wild guessing here based on brcmfmac. */ + if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) + wiphy->regd = regd; + else + return (EPERM); + + /* XXX FIXME, do we have to do anything with reg_notifier? */ + return (0); +} + +static __inline int +regulatory_hint(struct wiphy *wiphy, const uint8_t *alpha2) +{ + struct linuxkpi_ieee80211_regdomain *regd; + + if (wiphy->regd != NULL) + return (-EBUSY); + + regd = lkpi_get_linuxkpi_ieee80211_regdomain(0); + if (regd == NULL) + return (-ENOMEM); + + regd->alpha2[0] = alpha2[0]; + regd->alpha2[1] = alpha2[1]; + wiphy->regd = regd; + + IMPROVE("are there flags who is managing? update net8011?"); + + return (0); +} + +static __inline const char * +reg_initiator_name(enum nl80211_reg_initiator initiator) +{ + TODO(); + return (NULL); +} + +static __inline struct linuxkpi_ieee80211_regdomain * +rtnl_dereference(const struct linuxkpi_ieee80211_regdomain *regd) +{ + TODO(); + return (NULL); +} + +static __inline struct ieee80211_reg_rule * +freq_reg_info(struct wiphy *wiphy, uint32_t center_freq) +{ + TODO(); + return (NULL); +} + +static __inline void +wiphy_apply_custom_regulatory(struct wiphy *wiphy, + const struct linuxkpi_ieee80211_regdomain *regd) +{ + TODO(); +} + +static __inline char * +wiphy_name(struct wiphy *wiphy) +{ + if (wiphy != NULL && wiphy->dev != NULL) + return dev_name(wiphy->dev); + else { + IMPROVE("wlanNA"); + return ("wlanNA"); + } +} + +static __inline void +wiphy_read_of_freq_limits(struct wiphy *wiphy) +{ +#ifdef FDT + TODO(); +#endif +} + +static __inline void +wiphy_ext_feature_set(struct wiphy *wiphy, enum nl80211_ext_feature ef) +{ + + set_bit(ef, wiphy->ext_features); +} + +static inline bool +wiphy_ext_feature_isset(struct wiphy *wiphy, enum nl80211_ext_feature ef) +{ + return (test_bit(ef, wiphy->ext_features)); +} + +static __inline void * +wiphy_net(struct wiphy *wiphy) +{ + TODO(); + return (NULL); /* XXX passed to dev_net_set() */ +} + +static __inline int +wiphy_register(struct wiphy *wiphy) +{ + TODO(); + return (0); +} + +static __inline void +wiphy_unregister(struct wiphy *wiphy) +{ + TODO(); +} + +static __inline void +wiphy_warn(struct wiphy *wiphy, const char *fmt, ...) +{ + TODO(); +} + +static __inline int +cfg80211_check_combinations(struct wiphy *wiphy, + struct iface_combination_params *params) +{ + TODO(); + return (-ENOENT); +} + +static __inline uint8_t +cfg80211_classify8021d(struct sk_buff *skb, void *p) +{ + TODO(); + return (0); +} + +static __inline void +cfg80211_connect_done(struct net_device *ndev, + struct cfg80211_connect_resp_params *conn_params, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_disconnected(struct net_device *ndev, uint16_t reason, + void *p, int x, bool locally_generated, gfp_t gfp) +{ + TODO(); +} + +static __inline int +cfg80211_get_p2p_attr(const uint8_t *ie, uint32_t ie_len, + enum ieee80211_p2p_attr_ids attr, uint8_t *p, size_t p_len) +{ + TODO(); + return (-1); +} + +static __inline void +cfg80211_ibss_joined(struct net_device *ndev, const uint8_t *addr, + struct linuxkpi_ieee80211_channel *chan, gfp_t gfp) +{ + TODO(); +} + +static __inline struct cfg80211_bss * +cfg80211_inform_bss(struct wiphy *wiphy, + struct linuxkpi_ieee80211_channel *channel, + enum cfg80211_bss_frame_type bss_ftype, const uint8_t *bss, int _x, + uint16_t cap, uint16_t intvl, const uint8_t *ie, size_t ie_len, + int signal, gfp_t gfp) +{ + TODO(); + return (NULL); +} + +static __inline struct cfg80211_bss * +cfg80211_inform_bss_data(struct wiphy *wiphy, + struct cfg80211_inform_bss *bss_data, + enum cfg80211_bss_frame_type bss_ftype, const uint8_t *bss, int _x, + uint16_t cap, uint16_t intvl, const uint8_t *ie, size_t ie_len, gfp_t gfp) +{ + TODO(); + return (NULL); +} + +static __inline void +cfg80211_mgmt_tx_status(struct wireless_dev *wdev, uint64_t cookie, + const uint8_t *buf, size_t len, bool ack, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_michael_mic_failure(struct net_device *ndev, const uint8_t addr[ETH_ALEN], + enum nl80211_key_type key_type, int _x, void *p, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_new_sta(struct net_device *ndev, const uint8_t *addr, + struct station_info *sinfo, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_del_sta(struct net_device *ndev, const uint8_t *addr, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_port_authorized(struct net_device *ndev, const uint8_t *addr, + const uint8_t *bitmap, uint8_t len, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_ready_on_channel(struct wireless_dev *wdev, uint64_t cookie, + struct linuxkpi_ieee80211_channel *channel, unsigned int duration, + gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, + uint64_t cookie, struct linuxkpi_ieee80211_channel *channel, gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_report_wowlan_wakeup(void) +{ + TODO(); +} + +static __inline void +cfg80211_roamed(struct net_device *ndev, struct cfg80211_roam_info *roam_info, + gfp_t gfp) +{ + TODO(); +} + +static __inline void +cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int _x, + uint8_t *p, size_t p_len, int _x2) +{ + TODO(); +} + +static __inline void +cfg80211_scan_done(struct cfg80211_scan_request *scan_request, + struct cfg80211_scan_info *info) +{ + TODO(); +} + +static __inline void +cfg80211_sched_scan_results(struct wiphy *wiphy, uint64_t reqid) +{ + TODO(); +} + +static __inline void +cfg80211_sched_scan_stopped(struct wiphy *wiphy, int _x) +{ + TODO(); +} + +static __inline void +cfg80211_unregister_wdev(struct wireless_dev *wdev) +{ + TODO(); +} + +static __inline struct sk_buff * +cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, unsigned int len) +{ + TODO(); + return (NULL); +} + +static __inline int +cfg80211_vendor_cmd_reply(struct sk_buff *skb) +{ + TODO(); + return (-ENXIO); +} + +static __inline struct linuxkpi_ieee80211_channel * +ieee80211_get_channel(struct wiphy *wiphy, uint32_t freq) +{ + + return (linuxkpi_ieee80211_get_channel(wiphy, freq)); +} + +static inline size_t +ieee80211_get_hdrlen_from_skb(struct sk_buff *skb) +{ + const struct ieee80211_hdr *hdr; + size_t len; + + if (skb->len < 10) /* sizeof(ieee80211_frame_[ack,cts]) */ + return (0); + + hdr = (const struct ieee80211_hdr *)skb->data; + len = ieee80211_hdrlen(hdr->frame_control); + + /* If larger than what is in the skb return. */ + if (len > skb->len) + return (0); + + return (len); +} + +static __inline bool +cfg80211_channel_is_psc(struct linuxkpi_ieee80211_channel *channel) +{ + + /* Only 6Ghz. */ + if (channel->band != NL80211_BAND_6GHZ) + return (false); + + TODO(); + return (false); +} + +static inline int +cfg80211_get_ies_channel_number(const uint8_t *ie, size_t len, + enum nl80211_band band) +{ + const struct element *elem; + + switch (band) { + case NL80211_BAND_6GHZ: + TODO(); + break; + case NL80211_BAND_5GHZ: + case NL80211_BAND_2GHZ: + /* DSPARAMS has the channel number. */ + elem = cfg80211_find_elem(IEEE80211_ELEMID_DSPARMS, ie, len); + if (elem != NULL && elem->datalen == 1) + return (elem->data[0]); + /* HTINFO has the primary center channel. */ + elem = cfg80211_find_elem(IEEE80211_ELEMID_HTINFO, ie, len); + if (elem != NULL && + elem->datalen >= (sizeof(struct ieee80211_ie_htinfo) - 2)) { + const struct ieee80211_ie_htinfo *htinfo; + htinfo = (const struct ieee80211_ie_htinfo *)elem; + return (htinfo->hi_ctrlchannel); + } + /* What else? */ + break; + default: + IMPROVE("Unsupported"); + break; + } + return (-1); +} + +/* Used for scanning at least. */ +static __inline void +get_random_mask_addr(uint8_t *dst, const uint8_t *addr, const uint8_t *mask) +{ + int i; + + /* Get a completely random address and then overlay what we want. */ + get_random_bytes(dst, ETH_ALEN); + for (i = 0; i < ETH_ALEN; i++) + dst[i] = (dst[i] & ~(mask[i])) | (addr[i] & mask[i]); +} + +static __inline void +cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) +{ + TODO(); +} + +static __inline bool +cfg80211_reg_can_beacon(struct wiphy *wiphy, struct cfg80211_chan_def *chandef, + enum nl80211_iftype iftype) +{ + TODO(); + return (false); +} + +static __inline void +cfg80211_background_radar_event(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef, gfp_t gfp) +{ + TODO(); +} + +static __inline const uint8_t * +cfg80211_find_ext_ie(uint8_t eid, const uint8_t *p, size_t len) +{ + TODO(); + return (NULL); +} + +static inline void +_ieee80211_set_sband_iftype_data(struct ieee80211_supported_band *band, + struct ieee80211_sband_iftype_data *iftype_data, size_t nitems) +{ + band->iftype_data = iftype_data; + band->n_iftype_data = nitems; +} + +static inline const struct ieee80211_sband_iftype_data * +ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *band, + enum nl80211_iftype iftype) +{ + const struct ieee80211_sband_iftype_data *iftype_data; + int i; + + for (i = 0; i < band->n_iftype_data; i++) { + iftype_data = (const void *)&band->iftype_data[i]; + if (iftype_data->types_mask & BIT(iftype)) + return (iftype_data); + } + + return (NULL); +} + +static inline const struct ieee80211_sta_he_cap * +ieee80211_get_he_iftype_cap(const struct ieee80211_supported_band *band, + enum nl80211_iftype iftype) +{ + const struct ieee80211_sband_iftype_data *iftype_data; + const struct ieee80211_sta_he_cap *he_cap; + + iftype_data = ieee80211_get_sband_iftype_data(band, iftype); + if (iftype_data == NULL) + return (NULL); + + he_cap = NULL; + if (iftype_data->he_cap.has_he) + he_cap = &iftype_data->he_cap; + + return (he_cap); +} + +static inline const struct ieee80211_sta_eht_cap * +ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *band, + enum nl80211_iftype iftype) +{ + const struct ieee80211_sband_iftype_data *iftype_data; + const struct ieee80211_sta_eht_cap *eht_cap; + + iftype_data = ieee80211_get_sband_iftype_data(band, iftype); + if (iftype_data == NULL) + return (NULL); + + eht_cap = NULL; + if (iftype_data->eht_cap.has_eht) + eht_cap = &iftype_data->eht_cap; + + return (eht_cap); +} + +static inline bool +cfg80211_ssid_eq(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2) +{ + int error; + + if (ssid1 == NULL || ssid2 == NULL) /* Can we KASSERT this? */ + return (false); + + if (ssid1->ssid_len != ssid2->ssid_len) + return (false); + error = memcmp(ssid1->ssid, ssid2->ssid, ssid2->ssid_len); + if (error != 0) + return (false); + return (true); +} + +static inline void +cfg80211_rx_unprot_mlme_mgmt(struct net_device *ndev, const uint8_t *hdr, + uint32_t len) +{ + TODO(); +} + +static inline const struct wiphy_iftype_ext_capab * +cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype iftype) +{ + + TODO(); + return (NULL); +} + +static inline int +cfg80211_external_auth_request(struct net_device *ndev, + struct cfg80211_external_auth_params *params, gfp_t gfp) +{ + TODO(); + return (-ENXIO); +} + +static inline uint16_t +ieee80211_get_he_6ghz_capa(const struct ieee80211_supported_band *sband, + enum nl80211_iftype iftype) +{ + TODO(); + return (0); +} + +static __inline ssize_t +wiphy_locked_debugfs_read(struct wiphy *wiphy, struct file *file, + char *buf, size_t bufsize, const char __user *userbuf, size_t count, + loff_t *ppos, + ssize_t (*handler)(struct wiphy *, struct file *, char *, size_t, void *), + void *data) +{ + TODO(); + return (-ENXIO); +} + + +static __inline ssize_t +wiphy_locked_debugfs_write(struct wiphy *wiphy, struct file *file, + char *buf, size_t bufsize, const char __user *userbuf, size_t count, + ssize_t (*handler)(struct wiphy *, struct file *, char *, size_t, void *), + void *data) +{ + TODO(); + return (-ENXIO); +} + +static inline void +cfg80211_cqm_rssi_notify(struct net_device *dev, + enum nl80211_cqm_rssi_threshold_event rssi_te, int32_t rssi, gfp_t gfp) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +static inline void +wiphy_work_init(struct wiphy_work *wwk, wiphy_work_fn fn) +{ + INIT_LIST_HEAD(&wwk->entry); + wwk->fn = fn; +} + +static inline void +wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + linuxkpi_wiphy_work_queue(wiphy, wwk); +} + +static inline void +wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + linuxkpi_wiphy_work_cancel(wiphy, wwk); +} + +static inline void +wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + linuxkpi_wiphy_work_flush(wiphy, wwk); +} + +static inline void +wiphy_delayed_work_init(struct wiphy_delayed_work *wdwk, wiphy_work_fn fn) +{ + wiphy_work_init(&wdwk->work, fn); + timer_setup(&wdwk->timer, lkpi_wiphy_delayed_work_timer, 0); +} + +static inline void +wiphy_delayed_work_queue(struct wiphy *wiphy, struct wiphy_delayed_work *wdwk, + unsigned long delay) +{ + linuxkpi_wiphy_delayed_work_queue(wiphy, wdwk, delay); +} + +static inline void +wiphy_delayed_work_cancel(struct wiphy *wiphy, struct wiphy_delayed_work *wdwk) +{ + linuxkpi_wiphy_delayed_work_cancel(wiphy, wdwk); +} + +static inline void +wiphy_delayed_work_flush(struct wiphy *wiphy, struct wiphy_delayed_work *wdwk) +{ + linuxkpi_wiphy_delayed_work_flush(wiphy, wdwk); +} + +/* -------------------------------------------------------------------------- */ + +#define wiphy_err(_wiphy, _fmt, ...) \ + dev_err((_wiphy)->dev, _fmt, __VA_ARGS__) +#define wiphy_info(wiphy, fmt, ...) \ + dev_info((wiphy)->dev, fmt, ##__VA_ARGS__) +#define wiphy_info_once(wiphy, fmt, ...) \ + dev_info_once((wiphy)->dev, fmt, ##__VA_ARGS__) + +#ifndef LINUXKPI_NET80211 +#define ieee80211_channel linuxkpi_ieee80211_channel +#define ieee80211_regdomain linuxkpi_ieee80211_regdomain +#endif + +#include <net/mac80211.h> + +#endif /* _LINUXKPI_NET_CFG80211_H */ diff --git a/sys/compat/linuxkpi/common/include/net/ieee80211_radiotap.h b/sys/compat/linuxkpi/common/include/net/ieee80211_radiotap.h index 9c22e3e06988..82e554f6b96e 100644 --- a/sys/compat/linuxkpi/common/include/net/ieee80211_radiotap.h +++ b/sys/compat/linuxkpi/common/include/net/ieee80211_radiotap.h @@ -1,6 +1,4 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause - * * Copyright (c) 2020-2021 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from @@ -26,12 +24,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef __LKPI_NET_IEEE80211_RADIOTAP_H -#define __LKPI_NET_IEEE80211_RADIOTAP_H +#ifndef _LINUXKPI_NET_IEEE80211_RADIOTAP_H +#define _LINUXKPI_NET_IEEE80211_RADIOTAP_H /* Any possibly duplicate content is only maintained in one place now. */ #include <net80211/ieee80211_radiotap.h> @@ -52,4 +48,4 @@ struct ieee80211_vendor_radiotap { u8 data[0]; }; -#endif /* __LKPI_NET_IEEE80211_RADIOTAP_H */ +#endif /* _LINUXKPI_NET_IEEE80211_RADIOTAP_H */ diff --git a/sys/compat/linuxkpi/common/include/net/if_inet6.h b/sys/compat/linuxkpi/common/include/net/if_inet6.h index 16f3a9965675..c340909d7098 100644 --- a/sys/compat/linuxkpi/common/include/net/if_inet6.h +++ b/sys/compat/linuxkpi/common/include/net/if_inet6.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _NET_IF_INET6_H_ -#define _NET_IF_INET6_H_ +#ifndef _LINUXKPI_NET_IF_INET6_H_ +#define _LINUXKPI_NET_IF_INET6_H_ #include <sys/types.h> #include <netinet/in.h> @@ -54,4 +52,4 @@ static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf) memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32)); } -#endif /* _NET_IF_INET6_H_ */ +#endif /* _LINUXKPI_NET_IF_INET6_H_ */ diff --git a/sys/compat/linuxkpi/common/include/net/ip.h b/sys/compat/linuxkpi/common/include/net/ip.h index 1cfc568db323..3e7baab6cc0b 100644 --- a/sys/compat/linuxkpi/common/include/net/ip.h +++ b/sys/compat/linuxkpi/common/include/net/ip.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NET_IP_H_ -#define _LINUX_NET_IP_H_ +#ifndef _LINUXKPI_NET_IP_H_ +#define _LINUXKPI_NET_IP_H_ #include "opt_inet.h" @@ -100,4 +98,4 @@ ip_ib_mc_map(uint32_t addr, const unsigned char *bcast, char *buf) buf[19] = addr & 0xff; } -#endif /* _LINUX_NET_IP_H_ */ +#endif /* _LINUXKPI_NET_IP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/net/ipv6.h b/sys/compat/linuxkpi/common/include/net/ipv6.h index dfe77ef1c6ed..3a85781e3a49 100644 --- a/sys/compat/linuxkpi/common/include/net/ipv6.h +++ b/sys/compat/linuxkpi/common/include/net/ipv6.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NET_IPV6_H_ -#define _LINUX_NET_IPV6_H_ +#ifndef _LINUXKPI_NET_IPV6_H_ +#define _LINUXKPI_NET_IPV6_H_ #include <sys/types.h> #include <netinet/in.h> @@ -116,4 +114,4 @@ static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr return memcmp(a1, a2, sizeof(struct in6_addr)); } -#endif /* _LINUX_NET_IPV6_H_ */ +#endif /* _LINUXKPI_NET_IPV6_H_ */ diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h new file mode 100644 index 000000000000..ee1ace3684de --- /dev/null +++ b/sys/compat/linuxkpi/common/include/net/mac80211.h @@ -0,0 +1,2681 @@ +/*- + * Copyright (c) 2020-2025 The FreeBSD Foundation + * Copyright (c) 2020-2025 Bjoern A. Zeeb + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_NET_MAC80211_H +#define _LINUXKPI_NET_MAC80211_H + +#include <sys/types.h> + +#include <asm/atomic64.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/workqueue.h> +#include <linux/dcache.h> +#include <linux/ieee80211.h> +#include <net/cfg80211.h> +#include <net/if_inet6.h> + +#define ARPHRD_IEEE80211_RADIOTAP __LINE__ /* XXX TODO brcmfmac */ + +#define WLAN_OUI_MICROSOFT (0x0050F2) +#define WLAN_OUI_TYPE_MICROSOFT_WPA (1) +#define WLAN_OUI_TYPE_MICROSOFT_TPC (8) +#define WLAN_OUI_TYPE_WFA_P2P (9) +#define WLAN_OUI_WFA (0x506F9A) + +#define IEEE80211_LINK_UNSPECIFIED 0x0f + +/* hw->conf.flags */ +enum ieee80211_hw_conf_flags { + IEEE80211_CONF_IDLE = BIT(0), + IEEE80211_CONF_PS = BIT(1), + IEEE80211_CONF_MONITOR = BIT(2), + IEEE80211_CONF_OFFCHANNEL = BIT(3), +}; + +/* (*ops->config()) */ +enum ieee80211_hw_conf_changed_flags { + IEEE80211_CONF_CHANGE_CHANNEL = BIT(0), + IEEE80211_CONF_CHANGE_IDLE = BIT(1), + IEEE80211_CONF_CHANGE_PS = BIT(2), + IEEE80211_CONF_CHANGE_MONITOR = BIT(3), + IEEE80211_CONF_CHANGE_POWER = BIT(4), +}; + +#define CFG80211_TESTMODE_CMD(_x) /* XXX TODO */ +#define CFG80211_TESTMODE_DUMP(_x) /* XXX TODO */ + +#define FCS_LEN 4 + +/* ops.configure_filter() */ +enum mcast_filter_flags { + FIF_ALLMULTI = BIT(0), + FIF_PROBE_REQ = BIT(1), + FIF_BCN_PRBRESP_PROMISC = BIT(2), + FIF_FCSFAIL = BIT(3), + FIF_OTHER_BSS = BIT(4), + FIF_PSPOLL = BIT(5), + FIF_CONTROL = BIT(6), + FIF_MCAST_ACTION = BIT(7), + + /* Must stay last. */ + FIF_FLAGS_MASK = BIT(8)-1, +}; + +enum ieee80211_bss_changed { + BSS_CHANGED_ARP_FILTER = BIT(0), + BSS_CHANGED_ASSOC = BIT(1), + BSS_CHANGED_BANDWIDTH = BIT(2), + BSS_CHANGED_BEACON = BIT(3), + BSS_CHANGED_BEACON_ENABLED = BIT(4), + BSS_CHANGED_BEACON_INFO = BIT(5), + BSS_CHANGED_BEACON_INT = BIT(6), + BSS_CHANGED_BSSID = BIT(7), + BSS_CHANGED_CQM = BIT(8), + BSS_CHANGED_ERP_CTS_PROT = BIT(9), + BSS_CHANGED_ERP_SLOT = BIT(10), + BSS_CHANGED_FTM_RESPONDER = BIT(11), + BSS_CHANGED_HT = BIT(12), + BSS_CHANGED_IDLE = BIT(13), + BSS_CHANGED_MU_GROUPS = BIT(14), + BSS_CHANGED_P2P_PS = BIT(15), + BSS_CHANGED_PS = BIT(16), + BSS_CHANGED_QOS = BIT(17), + BSS_CHANGED_TXPOWER = BIT(18), + BSS_CHANGED_HE_BSS_COLOR = BIT(19), + BSS_CHANGED_AP_PROBE_RESP = BIT(20), + BSS_CHANGED_BASIC_RATES = BIT(21), + BSS_CHANGED_ERP_PREAMBLE = BIT(22), + BSS_CHANGED_IBSS = BIT(23), + BSS_CHANGED_MCAST_RATE = BIT(24), + BSS_CHANGED_SSID = BIT(25), + BSS_CHANGED_FILS_DISCOVERY = BIT(26), + BSS_CHANGED_HE_OBSS_PD = BIT(27), + BSS_CHANGED_TWT = BIT(28), + BSS_CHANGED_UNSOL_BCAST_PROBE_RESP = BIT(30), + BSS_CHANGED_EHT_PUNCTURING = BIT(31), + BSS_CHANGED_MLD_VALID_LINKS = BIT_ULL(32), + BSS_CHANGED_MLD_TTLM = BIT_ULL(33), + BSS_CHANGED_TPE = BIT_ULL(34), +}; + +/* 802.11 Figure 9-256 Suite selector format. [OUI(3), SUITE TYPE(1)] */ +#define WLAN_CIPHER_SUITE_OUI(_oui, _x) (((_oui) << 8) | ((_x) & 0xff)) + +/* 802.11 Table 9-131 Cipher suite selectors. */ +/* 802.1x suite B 11 */ +#define WLAN_CIPHER_SUITE(_x) WLAN_CIPHER_SUITE_OUI(0x000fac, _x) +/* Use group 0 */ +#define WLAN_CIPHER_SUITE_WEP40 WLAN_CIPHER_SUITE(1) +#define WLAN_CIPHER_SUITE_TKIP WLAN_CIPHER_SUITE(2) +/* Reserved 3 */ +#define WLAN_CIPHER_SUITE_CCMP WLAN_CIPHER_SUITE(4) /* CCMP-128 */ +#define WLAN_CIPHER_SUITE_WEP104 WLAN_CIPHER_SUITE(5) +#define WLAN_CIPHER_SUITE_AES_CMAC WLAN_CIPHER_SUITE(6) /* BIP-CMAC-128 */ +/* Group addressed traffic not allowed 7 */ +#define WLAN_CIPHER_SUITE_GCMP WLAN_CIPHER_SUITE(8) +#define WLAN_CIPHER_SUITE_GCMP_256 WLAN_CIPHER_SUITE(9) +#define WLAN_CIPHER_SUITE_CCMP_256 WLAN_CIPHER_SUITE(10) +#define WLAN_CIPHER_SUITE_BIP_GMAC_128 WLAN_CIPHER_SUITE(11) +#define WLAN_CIPHER_SUITE_BIP_GMAC_256 WLAN_CIPHER_SUITE(12) +#define WLAN_CIPHER_SUITE_BIP_CMAC_256 WLAN_CIPHER_SUITE(13) +/* Reserved 14-255 */ + +/* See ISO/IEC JTC 1 N 9880 Table 11 */ +#define WLAN_CIPHER_SUITE_SMS4 WLAN_CIPHER_SUITE_OUI(0x001472, 1) + + +/* 802.11 Table 9-133 AKM suite selectors. */ +#define WLAN_AKM_SUITE(_x) WLAN_CIPHER_SUITE_OUI(0x000fac, _x) +/* Reserved 0 */ +#define WLAN_AKM_SUITE_8021X WLAN_AKM_SUITE(1) +#define WLAN_AKM_SUITE_PSK WLAN_AKM_SUITE(2) +#define WLAN_AKM_SUITE_FT_8021X WLAN_AKM_SUITE(3) +#define WLAN_AKM_SUITE_FT_PSK WLAN_AKM_SUITE(4) +#define WLAN_AKM_SUITE_8021X_SHA256 WLAN_AKM_SUITE(5) +#define WLAN_AKM_SUITE_PSK_SHA256 WLAN_AKM_SUITE(6) +/* TDLS 7 */ +#define WLAN_AKM_SUITE_SAE WLAN_AKM_SUITE(8) +#define WLAN_AKM_SUITE_FT_OVER_SAE WLAN_AKM_SUITE(9) +/* AP peer key 10 */ +/* 802.1x suite B 11 */ +/* 802.1x suite B 384 12 */ +/* FTo802.1x 384 13 */ +/* Reserved 14-255 */ +/* Apparently 11ax defines more. Seen (19,20) mentioned. */ + +#define TKIP_PN_TO_IV16(_x) ((uint16_t)(_x & 0xffff)) +#define TKIP_PN_TO_IV32(_x) ((uint32_t)((_x >> 16) & 0xffffffff)) + +enum ieee80211_neg_ttlm_res { + NEG_TTLM_RES_ACCEPT, + NEG_TTLM_RES_REJECT, +}; + +#define IEEE80211_TTLM_NUM_TIDS 8 +struct ieee80211_neg_ttlm { + uint16_t downlink[IEEE80211_TTLM_NUM_TIDS]; + uint16_t uplink[IEEE80211_TTLM_NUM_TIDS]; +}; + +/* 802.11-2020 9.4.2.55.3 A-MPDU Parameters field */ +#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x3 +#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 +#define IEEE80211_HT_AMPDU_PARM_DENSITY (0x7 << IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) + +struct ieee80211_sta; + +struct ieee80211_ampdu_params { + struct ieee80211_sta *sta; + enum ieee80211_ampdu_mlme_action action; + uint16_t buf_size; + uint16_t timeout; + uint16_t ssn; + uint8_t tid; + bool amsdu; +}; + +struct ieee80211_bar { + /* TODO FIXME */ + int control, start_seq_num; + uint8_t *ra; + uint16_t frame_control; +}; + +struct ieee80211_mutable_offsets { + /* TODO FIXME */ + uint16_t tim_offset; + uint16_t cntdwn_counter_offs[2]; + + int mbssid_off; +}; + +struct mac80211_fils_discovery { + uint32_t max_interval; +}; + +struct ieee80211_chanctx_conf { + struct cfg80211_chan_def def; + struct cfg80211_chan_def min_def; + struct cfg80211_chan_def ap; + + uint8_t rx_chains_dynamic; + uint8_t rx_chains_static; + bool radar_enabled; + + /* Must stay last. */ + uint8_t drv_priv[0] __aligned(CACHE_LINE_SIZE); +}; + +struct ieee80211_rate_status { + struct rate_info rate_idx; + uint8_t try_count; +}; + +struct ieee80211_ema_beacons { + uint8_t cnt; + struct { + struct sk_buff *skb; + struct ieee80211_mutable_offsets offs; + } bcn[0]; +}; + +struct ieee80211_chanreq { + struct cfg80211_chan_def oper; +}; + +#define WLAN_MEMBERSHIP_LEN (8) +#define WLAN_USER_POSITION_LEN (16) + +/* + * 802.11ac-2013, 8.4.2.164 VHT Transmit Power Envelope element + * 802.11-???? ? + */ +struct ieee80211_parsed_tpe_eirp { + int8_t power[5]; + uint8_t count; + bool valid; +}; +struct ieee80211_parsed_tpe_psd { + int8_t power[16]; + uint8_t count; + bool valid; +}; +struct ieee80211_parsed_tpe { + /* We see access to [0] so assume at least 2. */ + struct ieee80211_parsed_tpe_eirp max_local[2]; + struct ieee80211_parsed_tpe_eirp max_reg_client[2]; + struct ieee80211_parsed_tpe_psd psd_local[2]; + struct ieee80211_parsed_tpe_psd psd_reg_client[2]; +}; + +struct ieee80211_bss_conf { + /* TODO FIXME */ + struct ieee80211_vif *vif; + struct cfg80211_bss *bss; + const uint8_t *bssid; + uint8_t addr[ETH_ALEN]; + uint8_t link_id; + uint8_t _pad0; + uint8_t transmitter_bssid[ETH_ALEN]; + struct ieee80211_ftm_responder_params *ftmr_params; + struct ieee80211_p2p_noa_attr p2p_noa_attr; + struct ieee80211_chanreq chanreq; + __be32 arp_addr_list[1]; /* XXX TODO */ + struct ieee80211_rate *beacon_rate; + struct { + uint8_t membership[WLAN_MEMBERSHIP_LEN]; + uint8_t position[WLAN_USER_POSITION_LEN]; + } mu_group; + struct { + uint32_t params; + /* single field struct? */ + } he_oper; + struct cfg80211_he_bss_color he_bss_color; + struct ieee80211_he_obss_pd he_obss_pd; + + bool ht_ldpc; + bool vht_ldpc; + bool he_ldpc; + bool vht_mu_beamformee; + bool vht_mu_beamformer; + bool vht_su_beamformee; + bool vht_su_beamformer; + bool he_mu_beamformer; + bool he_su_beamformee; + bool he_su_beamformer; + bool he_full_ul_mumimo; + bool eht_su_beamformee; + bool eht_su_beamformer; + bool eht_mu_beamformer; + + uint16_t ht_operation_mode; + int arp_addr_cnt; + uint16_t eht_puncturing; + + uint8_t dtim_period; + uint8_t sync_dtim_count; + uint8_t bss_param_ch_cnt_link_id; + bool qos; + bool twt_broadcast; + bool use_cts_prot; + bool use_short_preamble; + bool use_short_slot; + bool he_support; + bool eht_support; + bool csa_active; + bool mu_mimo_owner; + bool color_change_active; + uint32_t sync_device_ts; + uint64_t sync_tsf; + uint16_t beacon_int; + int16_t txpower; + uint32_t basic_rates; + int mcast_rate[NUM_NL80211_BANDS]; + enum ieee80211_ap_reg_power power_type; + struct cfg80211_bitrate_mask beacon_tx_rate; + struct mac80211_fils_discovery fils_discovery; + struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_vif *mbssid_tx_vif; + struct ieee80211_parsed_tpe tpe; + + int ack_enabled, bssid_index, bssid_indicator, cqm_rssi_hyst, cqm_rssi_thold, ema_ap, frame_time_rts_th, ftm_responder; + int htc_trig_based_pkt_ext; + int multi_sta_back_32bit, nontransmitted; + int profile_periodicity; + int twt_requester, uora_exists, uora_ocw_range; + int assoc_capability, enable_beacon, hidden_ssid, ibss_joined, twt_protected; + int twt_responder, unsol_bcast_probe_resp_interval; +}; + +struct ieee80211_channel_switch { + /* TODO FIXME */ + int block_tx, count, delay, device_timestamp, timestamp; + uint8_t link_id; + struct cfg80211_chan_def chandef; +}; + +enum ieee80211_event_type { + BA_FRAME_TIMEOUT, + BAR_RX_EVENT, + MLME_EVENT, + RSSI_EVENT, +}; + +enum ieee80211_rssi_event_data { + RSSI_EVENT_LOW, + RSSI_EVENT_HIGH, +}; + +enum ieee80211_mlme_event_data { + ASSOC_EVENT, + AUTH_EVENT, + DEAUTH_RX_EVENT, + DEAUTH_TX_EVENT, +}; + +enum ieee80211_mlme_event_status { + MLME_DENIED, + MLME_TIMEOUT, +}; + +struct ieee80211_mlme_event { + enum ieee80211_mlme_event_data data; + enum ieee80211_mlme_event_status status; + int reason; +}; + +struct ieee80211_event { + /* TODO FIXME */ + enum ieee80211_event_type type; + union { + struct { + int ssn; + struct ieee80211_sta *sta; + uint8_t tid; + } ba; + struct ieee80211_mlme_event mlme; + } u; +}; + +struct ieee80211_ftm_responder_params { + /* TODO FIXME */ + uint8_t *lci; + uint8_t *civicloc; + int lci_len; + int civicloc_len; +}; + +struct ieee80211_conf { + int dynamic_ps_timeout; + int power_level; + uint32_t listen_interval; + bool radar_enabled; + enum ieee80211_hw_conf_flags flags; + struct cfg80211_chan_def chandef; +}; + +enum ieee80211_hw_flags { + IEEE80211_HW_AMPDU_AGGREGATION, + IEEE80211_HW_AP_LINK_PS, + IEEE80211_HW_BUFF_MMPDU_TXQ, + IEEE80211_HW_CHANCTX_STA_CSA, + IEEE80211_HW_CONNECTION_MONITOR, + IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP, + IEEE80211_HW_HAS_RATE_CONTROL, + IEEE80211_HW_MFP_CAPABLE, + IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR, + IEEE80211_HW_REPORTS_TX_ACK_STATUS, + IEEE80211_HW_RX_INCLUDES_FCS, + IEEE80211_HW_SIGNAL_DBM, + IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS, + IEEE80211_HW_SPECTRUM_MGMT, + IEEE80211_HW_STA_MMPDU_TXQ, + IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU, + IEEE80211_HW_SUPPORTS_CLONED_SKBS, + IEEE80211_HW_SUPPORTS_DYNAMIC_PS, + IEEE80211_HW_SUPPORTS_MULTI_BSSID, + IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID, + IEEE80211_HW_SUPPORTS_PS, + IEEE80211_HW_SUPPORTS_REORDERING_BUFFER, + IEEE80211_HW_SUPPORTS_VHT_EXT_NSS_BW, + IEEE80211_HW_SUPPORT_FAST_XMIT, + IEEE80211_HW_TDLS_WIDER_BW, + IEEE80211_HW_TIMING_BEACON_ONLY, + IEEE80211_HW_TX_AMPDU_SETUP_IN_HW, + IEEE80211_HW_TX_AMSDU, + IEEE80211_HW_TX_FRAG_LIST, + IEEE80211_HW_USES_RSS, + IEEE80211_HW_WANT_MONITOR_VIF, + IEEE80211_HW_SW_CRYPTO_CONTROL, + IEEE80211_HW_SUPPORTS_TX_FRAG, + IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA, + IEEE80211_HW_SUPPORTS_PER_STA_GTK, + IEEE80211_HW_REPORTS_LOW_ACK, + IEEE80211_HW_QUEUE_CONTROL, + IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD, + IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, + IEEE80211_HW_SUPPORTS_RC_TABLE, + IEEE80211_HW_DETECTS_COLOR_COLLISION, + IEEE80211_HW_DISALLOW_PUNCTURING, + IEEE80211_HW_DISALLOW_PUNCTURING_5GHZ, + IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN, + IEEE80211_HW_HANDLES_QUIET_CSA, + IEEE80211_HW_NO_VIRTUAL_MONITOR, + + /* Keep last. */ + NUM_IEEE80211_HW_FLAGS +}; + +struct ieee80211_hw { + + struct wiphy *wiphy; + + /* TODO FIXME */ + int extra_tx_headroom, weight_multiplier; + int max_rate_tries, max_rates, max_report_rates; + const char *rate_control_algorithm; + struct { + uint16_t units_pos; /* radiotap "spec" is .. inconsistent. */ + uint16_t accuracy; + } radiotap_timestamp; + size_t sta_data_size; + size_t vif_data_size; + size_t chanctx_data_size; + size_t txq_data_size; + uint16_t radiotap_mcs_details; + uint16_t radiotap_vht_details; + uint16_t queues; + uint16_t offchannel_tx_hw_queue; + uint16_t uapsd_max_sp_len; + uint16_t uapsd_queues; + uint16_t max_rx_aggregation_subframes; + uint16_t max_tx_aggregation_subframes; + uint16_t max_tx_fragments; + uint16_t max_listen_interval; + uint32_t extra_beacon_tailroom; + netdev_features_t netdev_features; + unsigned long flags[BITS_TO_LONGS(NUM_IEEE80211_HW_FLAGS)]; + struct ieee80211_conf conf; + +#if 0 /* leave here for documentation purposes. This does NOT work. */ + /* Must stay last. */ + uint8_t priv[0] __aligned(CACHE_LINE_SIZE); +#else + void *priv; +#endif +}; + +enum ieee802111_key_flag { + IEEE80211_KEY_FLAG_GENERATE_IV = BIT(0), + IEEE80211_KEY_FLAG_GENERATE_MMIC = BIT(1), + IEEE80211_KEY_FLAG_PAIRWISE = BIT(2), + IEEE80211_KEY_FLAG_PUT_IV_SPACE = BIT(3), + IEEE80211_KEY_FLAG_PUT_MIC_SPACE = BIT(4), + IEEE80211_KEY_FLAG_SW_MGMT_TX = BIT(5), + IEEE80211_KEY_FLAG_GENERATE_IV_MGMT = BIT(6), + IEEE80211_KEY_FLAG_GENERATE_MMIE = BIT(7), + IEEE80211_KEY_FLAG_RESERVE_TAILROOM = BIT(8), + IEEE80211_KEY_FLAG_SPP_AMSDU = BIT(9), +}; + +#define IEEE80211_KEY_FLAG_BITS \ + "\20\1GENERATE_IV\2GENERATE_MMIC\3PAIRWISE\4PUT_IV_SPACE" \ + "\5PUT_MIC_SPACE\6SW_MGMT_TX\7GENERATE_IV_MGMT\10GENERATE_MMIE" \ + "\11RESERVE_TAILROOM\12SPP_AMSDU" + +struct ieee80211_key_conf { +#if defined(__FreeBSD__) + const struct ieee80211_key *_k; /* backpointer to net80211 */ +#endif + atomic64_t tx_pn; + uint32_t cipher; + uint8_t icv_len; /* __unused nowadays? */ + uint8_t iv_len; + uint8_t hw_key_idx; /* Set by drv. */ + uint8_t keyidx; + uint16_t flags; + int8_t link_id; /* signed! */ + uint8_t keylen; + uint8_t key[0]; /* Must stay last! */ +}; + +struct ieee80211_key_seq { + /* TODO FIXME */ + union { + struct { + uint8_t seq[IEEE80211_MAX_PN_LEN]; + uint8_t seq_len; + } hw; + struct { + uint8_t pn[IEEE80211_CCMP_PN_LEN]; + } ccmp; + struct { + uint8_t pn[IEEE80211_GCMP_PN_LEN]; + } gcmp; + struct { + uint8_t pn[IEEE80211_CMAC_PN_LEN]; + } aes_cmac; + struct { + uint8_t pn[IEEE80211_GMAC_PN_LEN]; + } aes_gmac; + struct { + uint32_t iv32; + uint16_t iv16; + } tkip; + }; +}; + + +enum ieee80211_rx_status_flags { + RX_FLAG_ALLOW_SAME_PN = BIT(0), + RX_FLAG_AMPDU_DETAILS = BIT(1), + RX_FLAG_AMPDU_EOF_BIT = BIT(2), + RX_FLAG_AMPDU_EOF_BIT_KNOWN = BIT(3), + RX_FLAG_DECRYPTED = BIT(4), + RX_FLAG_DUP_VALIDATED = BIT(5), + RX_FLAG_FAILED_FCS_CRC = BIT(6), + RX_FLAG_ICV_STRIPPED = BIT(7), + RX_FLAG_MACTIME = BIT(8) | BIT(9), + RX_FLAG_MACTIME_PLCP_START = 1 << 8, + RX_FLAG_MACTIME_START = 2 << 8, + RX_FLAG_MACTIME_END = 3 << 8, + RX_FLAG_MIC_STRIPPED = BIT(10), + RX_FLAG_MMIC_ERROR = BIT(11), + RX_FLAG_MMIC_STRIPPED = BIT(12), + RX_FLAG_NO_PSDU = BIT(13), + RX_FLAG_PN_VALIDATED = BIT(14), + RX_FLAG_RADIOTAP_HE = BIT(15), + RX_FLAG_RADIOTAP_HE_MU = BIT(16), + RX_FLAG_RADIOTAP_LSIG = BIT(17), + RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(18), + RX_FLAG_NO_SIGNAL_VAL = BIT(19), + RX_FLAG_IV_STRIPPED = BIT(20), + RX_FLAG_AMPDU_IS_LAST = BIT(21), + RX_FLAG_AMPDU_LAST_KNOWN = BIT(22), + RX_FLAG_AMSDU_MORE = BIT(23), + /* = BIT(24), */ + RX_FLAG_ONLY_MONITOR = BIT(25), + RX_FLAG_SKIP_MONITOR = BIT(26), + RX_FLAG_8023 = BIT(27), + RX_FLAG_RADIOTAP_TLV_AT_END = BIT(28), + /* = BIT(29), */ + RX_FLAG_MACTIME_IS_RTAP_TS64 = BIT(30), + RX_FLAG_FAILED_PLCP_CRC = BIT(31), +}; + +#define IEEE80211_RX_STATUS_FLAGS_BITS \ + "\20\1ALLOW_SAME_PN\2AMPDU_DETAILS\3AMPDU_EOF_BIT\4AMPDU_EOF_BIT_KNOWN" \ + "\5DECRYPTED\6DUP_VALIDATED\7FAILED_FCS_CRC\10ICV_STRIPPED" \ + "\11MACTIME_PLCP_START\12MACTIME_START\13MIC_STRIPPED" \ + "\14MMIC_ERROR\15MMIC_STRIPPED\16NO_PSDU\17PN_VALIDATED" \ + "\20RADIOTAP_HE\21RADIOTAP_HE_MU\22RADIOTAP_LSIG\23RADIOTAP_VENDOR_DATA" \ + "\24NO_SIGNAL_VAL\25IV_STRIPPED\26AMPDU_IS_LAST\27AMPDU_LAST_KNOWN" \ + "\30AMSDU_MORE\31MACTIME_END\32ONLY_MONITOR\33SKIP_MONITOR" \ + "\348023\35RADIOTAP_TLV_AT_END\36MACTIME\37MACTIME_IS_RTAP_TS64" \ + "\40FAILED_PLCP_CRC" + +enum mac80211_rx_encoding { + RX_ENC_LEGACY = 0, + RX_ENC_HT, + RX_ENC_VHT, + RX_ENC_HE, + RX_ENC_EHT, +}; + +struct ieee80211_rx_status { + /* TODO FIXME, this is too large. Over-reduce types to u8 where possible. */ + union { + uint64_t boottime_ns; + int64_t ack_tx_hwtstamp; + }; + uint64_t mactime; + uint32_t device_timestamp; + enum ieee80211_rx_status_flags flag; + uint16_t freq; + uint8_t encoding:3, bw:4; /* enum mac80211_rx_encoding, rate_info_bw */ /* See mt76.h */ + uint8_t ampdu_reference; + uint8_t band; + uint8_t chains; + int8_t chain_signal[IEEE80211_MAX_CHAINS]; + int8_t signal; + uint8_t enc_flags; + union { + struct { + uint8_t he_ru:3; /* nl80211::enum nl80211_he_ru_alloc */ + uint8_t he_gi:2; /* nl80211::enum nl80211_he_gi */ + uint8_t he_dcm:1; + }; + struct { + uint8_t ru:4; /* nl80211::enum nl80211_eht_ru_alloc */ + uint8_t gi:2; /* nl80211::enum nl80211_eht_gi */ + } eht; + }; + bool link_valid; + uint8_t link_id; /* very incosistent sizes? */ + uint8_t zero_length_psdu_type; + uint8_t nss; + uint8_t rate_idx; +}; + +struct ieee80211_tx_status { + struct ieee80211_sta *sta; + struct ieee80211_tx_info *info; + int64_t ack_hwtstamp; + + u8 n_rates; + struct ieee80211_rate_status *rates; + + struct sk_buff *skb; + struct list_head *free_list; +}; + +struct ieee80211_scan_ies { + /* TODO FIXME */ + int common_ie_len; + int len[NUM_NL80211_BANDS]; + uint8_t *common_ies; + uint8_t *ies[NUM_NL80211_BANDS]; +}; + +struct ieee80211_scan_request { + struct ieee80211_scan_ies ies; + struct cfg80211_scan_request req; +}; + +struct ieee80211_txq { + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; + int ac; + uint8_t tid; + + /* Must stay last. */ + uint8_t drv_priv[0] __aligned(CACHE_LINE_SIZE); +}; + +struct ieee80211_sta_rates { + /* XXX TODO */ + /* XXX some _rcu thing */ + struct { + uint8_t idx; + uint8_t count; + uint16_t flags; + } rate[4]; /* XXX what is the real number? */ +}; + +struct ieee80211_sta_txpwr { + /* XXX TODO */ + enum nl80211_tx_power_setting type; + short power; +}; + +#define IEEE80211_NUM_TIDS 16 /* net80211::WME_NUM_TID */ +struct ieee80211_sta_agg { + uint16_t max_amsdu_len; + uint16_t max_rc_amsdu_len; + uint16_t max_tid_amsdu_len[IEEE80211_NUM_TIDS]; +}; + +struct ieee80211_link_sta { + struct ieee80211_sta *sta; + uint8_t addr[ETH_ALEN]; + uint8_t link_id; + uint32_t supp_rates[NUM_NL80211_BANDS]; + struct ieee80211_sta_ht_cap ht_cap; + struct ieee80211_sta_vht_cap vht_cap; + struct ieee80211_sta_he_cap he_cap; + struct ieee80211_he_6ghz_capa he_6ghz_capa; + struct ieee80211_sta_eht_cap eht_cap; + uint8_t rx_nss; + enum ieee80211_sta_rx_bandwidth bandwidth; + enum ieee80211_smps_mode smps_mode; + struct ieee80211_sta_agg agg; + struct ieee80211_sta_txpwr txpwr; +}; + +struct ieee80211_sta { + /* TODO FIXME */ + int max_amsdu_subframes; + int mfp, smps_mode, tdls, tdls_initiator; + struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1]; /* iwlwifi: 8 and adds +1 to tid_data, net80211::IEEE80211_TID_SIZE */ + struct ieee80211_sta_rates *rates; /* some rcu thing? */ + uint8_t addr[ETH_ALEN]; + uint16_t aid; + bool wme; + bool mlo; + uint8_t max_sp; + uint8_t uapsd_queues; + uint16_t valid_links; + + struct ieee80211_link_sta deflink; + struct ieee80211_link_sta *link[IEEE80211_MLD_MAX_NUM_LINKS]; /* rcu? */ + + /* Must stay last. */ + uint8_t drv_priv[0] __aligned(CACHE_LINE_SIZE); +}; + +struct ieee80211_tdls_ch_sw_params { + /* TODO FIXME */ + int action_code, ch_sw_tm_ie, status, switch_time, switch_timeout, timestamp; + struct ieee80211_sta *sta; + struct cfg80211_chan_def *chandef; + struct sk_buff *tmpl_skb; +}; + +struct ieee80211_tx_control { + /* TODO FIXME */ + struct ieee80211_sta *sta; +}; + +struct ieee80211_tx_queue_params { + /* These types are based on iwlwifi FW structs. */ + uint16_t cw_min; + uint16_t cw_max; + uint16_t txop; + uint8_t aifs; + + /* TODO FIXME */ + int acm, mu_edca, uapsd; + struct ieee80211_he_mu_edca_param_ac_rec mu_edca_param_rec; +}; + +struct ieee80211_tx_rate { + uint8_t idx; + uint16_t count:5, + flags:11; +}; + +enum ieee80211_vif_driver_flags { + IEEE80211_VIF_BEACON_FILTER = BIT(0), + IEEE80211_VIF_SUPPORTS_CQM_RSSI = BIT(1), + IEEE80211_VIF_SUPPORTS_UAPSD = BIT(2), +#if defined(LINUXKPI_VERSION) && (LINUXKPI_VERSION < 60600) /* v6.6 */ + IEEE80211_VIF_DISABLE_SMPS_OVERRIDE = BIT(3), /* Renamed to IEEE80211_VIF_EML_ACTIVE. */ +#endif + IEEE80211_VIF_EML_ACTIVE = BIT(4), + IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW = BIT(5), + IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC = BIT(6), +}; + +#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4 + +struct ieee80211_vif_cfg { + uint16_t aid; + uint16_t eml_cap; + uint16_t eml_med_sync_delay; + bool assoc; + bool ps; + bool idle; + bool ibss_joined; + int arp_addr_cnt; + size_t ssid_len; + uint32_t arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; /* big endian */ + uint8_t ssid[IEEE80211_NWID_LEN]; + uint8_t ap_addr[ETH_ALEN]; +}; + +struct ieee80211_vif { + /* TODO FIXME */ + enum nl80211_iftype type; + int cab_queue; + int offload_flags; + enum ieee80211_vif_driver_flags driver_flags; + bool p2p; + bool probe_req_reg; + uint8_t addr[ETH_ALEN]; + struct ieee80211_vif_cfg cfg; + struct ieee80211_txq *txq; + struct ieee80211_bss_conf bss_conf; + struct ieee80211_bss_conf *link_conf[IEEE80211_MLD_MAX_NUM_LINKS]; /* rcu? */ + uint8_t hw_queue[IEEE80211_NUM_ACS]; + uint16_t active_links; + uint16_t valid_links; + struct ieee80211_vif *mbssid_tx_vif; + +/* #ifdef CONFIG_MAC80211_DEBUGFS */ /* Do not change structure depending on compile-time option. */ + struct dentry *debugfs_dir; +/* #endif */ + + /* Must stay last. */ + uint8_t drv_priv[0] __aligned(CACHE_LINE_SIZE); +}; + +struct ieee80211_vif_chanctx_switch { + struct ieee80211_chanctx_conf *old_ctx, *new_ctx; + struct ieee80211_vif *vif; + struct ieee80211_bss_conf *link_conf; +}; + +struct ieee80211_prep_tx_info { + uint16_t duration; + uint16_t subtype; + bool success; + bool was_assoc; + int link_id; +}; + +/* XXX-BZ too big, over-reduce size to u8, and array sizes to minuimum to fit in skb->cb. */ +/* Also warning: some sizes change by pointer size! This is 64bit only. */ +struct ieee80211_tx_info { + enum ieee80211_tx_info_flags flags; /* 32 bits */ + /* TODO FIXME */ + enum nl80211_band band; /* 3 bits */ + uint16_t hw_queue:4, /* 4 bits */ + tx_time_est:10; /* 10 bits */ + union { + struct { + struct ieee80211_tx_rate rates[4]; + bool use_rts; + uint8_t antennas:2; + struct ieee80211_vif *vif; + struct ieee80211_key_conf *hw_key; + enum ieee80211_tx_control_flags flags; + } control; + struct { + struct ieee80211_tx_rate rates[4]; + uint32_t ack_signal; + uint8_t ampdu_ack_len; + uint8_t ampdu_len; + uint8_t antenna; + uint16_t tx_time; + uint8_t flags; + void *status_driver_data[16 / sizeof(void *)]; /* XXX TODO */ + } status; +#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40 + void *driver_data[IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)]; + }; +}; + +/* net80211 conflict */ +struct linuxkpi_ieee80211_tim_ie { + uint8_t dtim_count; + uint8_t dtim_period; + uint8_t bitmap_ctrl; + uint8_t *virtual_map; +}; +#define ieee80211_tim_ie linuxkpi_ieee80211_tim_ie + +enum ieee80211_iface_iter { + IEEE80211_IFACE_ITER_NORMAL = BIT(0), + IEEE80211_IFACE_ITER_RESUME_ALL = BIT(1), + IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER = BIT(2), /* seems to be an iter flag */ + IEEE80211_IFACE_ITER_ACTIVE = BIT(3), + + /* Internal flags only. */ + IEEE80211_IFACE_ITER__ATOMIC = BIT(6), + IEEE80211_IFACE_ITER__MTX = BIT(8), +}; + +enum set_key_cmd { + SET_KEY, + DISABLE_KEY, +}; + +/* 802.11-2020, 9.4.2.55.2 HT Capability Information field. */ +enum rx_enc_flags { + RX_ENC_FLAG_SHORTPRE = BIT(0), + RX_ENC_FLAG_SHORT_GI = BIT(2), + RX_ENC_FLAG_HT_GF = BIT(3), + RX_ENC_FLAG_STBC_MASK = BIT(4) | BIT(5), +#define RX_ENC_FLAG_STBC_SHIFT 4 + RX_ENC_FLAG_LDPC = BIT(6), + RX_ENC_FLAG_BF = BIT(7), +}; + +enum sta_notify_cmd { + STA_NOTIFY_AWAKE, + STA_NOTIFY_SLEEP, +}; + +struct ieee80211_low_level_stats { + /* Can we make them uint64_t? */ + uint32_t dot11ACKFailureCount; + uint32_t dot11FCSErrorCount; + uint32_t dot11RTSFailureCount; + uint32_t dot11RTSSuccessCount; +}; + +enum ieee80211_offload_flags { + IEEE80211_OFFLOAD_ENCAP_4ADDR, + IEEE80211_OFFLOAD_ENCAP_ENABLED, + IEEE80211_OFFLOAD_DECAP_ENABLED, +}; + +struct ieee80211_ops { + /* TODO FIXME */ + int (*start)(struct ieee80211_hw *); + void (*stop)(struct ieee80211_hw *, bool); + + int (*config)(struct ieee80211_hw *, int, u32); + void (*reconfig_complete)(struct ieee80211_hw *, enum ieee80211_reconfig_type); + + void (*prep_add_interface)(struct ieee80211_hw *, enum nl80211_iftype); + int (*add_interface)(struct ieee80211_hw *, struct ieee80211_vif *); + void (*remove_interface)(struct ieee80211_hw *, struct ieee80211_vif *); + int (*change_interface)(struct ieee80211_hw *, struct ieee80211_vif *, enum nl80211_iftype, bool); + + void (*sw_scan_start)(struct ieee80211_hw *, struct ieee80211_vif *, const u8 *); + void (*sw_scan_complete)(struct ieee80211_hw *, struct ieee80211_vif *); + int (*sched_scan_start)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_sched_scan_request *, struct ieee80211_scan_ies *); + int (*sched_scan_stop)(struct ieee80211_hw *, struct ieee80211_vif *); + int (*hw_scan)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_scan_request *); + void (*cancel_hw_scan)(struct ieee80211_hw *, struct ieee80211_vif *); + + int (*conf_tx)(struct ieee80211_hw *, struct ieee80211_vif *, u32, u16, const struct ieee80211_tx_queue_params *); + void (*tx)(struct ieee80211_hw *, struct ieee80211_tx_control *, struct sk_buff *); + int (*tx_last_beacon)(struct ieee80211_hw *); + void (*wake_tx_queue)(struct ieee80211_hw *, struct ieee80211_txq *); + + void (*mgd_prepare_tx)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_prep_tx_info *); + void (*mgd_complete_tx)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_prep_tx_info *); + void (*mgd_protect_tdls_discover)(struct ieee80211_hw *, struct ieee80211_vif *, unsigned int); + + void (*flush)(struct ieee80211_hw *, struct ieee80211_vif *, u32, bool); + void (*flush_sta)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *); + + int (*set_frag_threshold)(struct ieee80211_hw *, int, u32); + + void (*sync_rx_queues)(struct ieee80211_hw *); + + void (*allow_buffered_frames)(struct ieee80211_hw *, struct ieee80211_sta *, u16, int, enum ieee80211_frame_release_type, bool); + void (*release_buffered_frames)(struct ieee80211_hw *, struct ieee80211_sta *, u16, int, enum ieee80211_frame_release_type, bool); + + int (*sta_add)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *); + int (*sta_remove)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *); + int (*sta_set_txpwr)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *); + void (*sta_statistics)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, struct station_info *); + void (*sta_pre_rcu_remove)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *); + int (*sta_state)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, enum ieee80211_sta_state, enum ieee80211_sta_state); + void (*sta_notify)(struct ieee80211_hw *, struct ieee80211_vif *, enum sta_notify_cmd, struct ieee80211_sta *); + void (*sta_rc_update)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, u32); + void (*link_sta_rc_update)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_link_sta *, u32); + void (*sta_rate_tbl_update)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *); + void (*sta_set_4addr)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, bool); + void (*sta_set_decap_offload)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, bool); + + u64 (*prepare_multicast)(struct ieee80211_hw *, struct netdev_hw_addr_list *); + + int (*ampdu_action)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_ampdu_params *); + + bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *, struct sk_buff *, struct sk_buff *); + + int (*pre_channel_switch)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_channel_switch *); + int (*post_channel_switch)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *); + void (*channel_switch)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_channel_switch *); + void (*channel_switch_beacon)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_chan_def *); + void (*abort_channel_switch)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *); + void (*channel_switch_rx_beacon)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_channel_switch *); + int (*tdls_channel_switch)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, u8, struct cfg80211_chan_def *, struct sk_buff *, u32); + void (*tdls_cancel_channel_switch)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *); + void (*tdls_recv_channel_switch)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_tdls_ch_sw_params *); + + int (*add_chanctx)(struct ieee80211_hw *, struct ieee80211_chanctx_conf *); + void (*remove_chanctx)(struct ieee80211_hw *, struct ieee80211_chanctx_conf *); + void (*change_chanctx)(struct ieee80211_hw *, struct ieee80211_chanctx_conf *, u32); + int (*assign_vif_chanctx)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, struct ieee80211_chanctx_conf *); + void (*unassign_vif_chanctx)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, struct ieee80211_chanctx_conf *); + int (*switch_vif_chanctx)(struct ieee80211_hw *, struct ieee80211_vif_chanctx_switch *, int, enum ieee80211_chanctx_switch_mode); + + int (*get_antenna)(struct ieee80211_hw *, int, u32 *, u32 *); + int (*set_antenna)(struct ieee80211_hw *, int, u32, u32); + + int (*remain_on_channel)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_channel *, int, enum ieee80211_roc_type); + int (*cancel_remain_on_channel)(struct ieee80211_hw *, struct ieee80211_vif *); + + void (*configure_filter)(struct ieee80211_hw *, unsigned int, unsigned int *, u64); + void (*config_iface_filter)(struct ieee80211_hw *, struct ieee80211_vif *, unsigned int, unsigned int); + + void (*bss_info_changed)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, u64); + void (*link_info_changed)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, u64); + + int (*set_rts_threshold)(struct ieee80211_hw *, int, u32); + void (*event_callback)(struct ieee80211_hw *, struct ieee80211_vif *, const struct ieee80211_event *); + int (*get_survey)(struct ieee80211_hw *, int, struct survey_info *); + int (*get_ftm_responder_stats)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_ftm_responder_stats *); + + uint64_t (*get_tsf)(struct ieee80211_hw *, struct ieee80211_vif *); + void (*set_tsf)(struct ieee80211_hw *, struct ieee80211_vif *, uint64_t); + void (*offset_tsf)(struct ieee80211_hw *, struct ieee80211_vif *, s64); + + int (*set_bitrate_mask)(struct ieee80211_hw *, struct ieee80211_vif *, const struct cfg80211_bitrate_mask *); + void (*set_coverage_class)(struct ieee80211_hw *, int, s16); + int (*set_tim)(struct ieee80211_hw *, struct ieee80211_sta *, bool); + + int (*set_key)(struct ieee80211_hw *, enum set_key_cmd, struct ieee80211_vif *, struct ieee80211_sta *, struct ieee80211_key_conf *); + void (*update_tkip_key)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_key_conf *, struct ieee80211_sta *, u32, u16 *); + + int (*start_pmsr)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_pmsr_request *); + void (*abort_pmsr)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_pmsr_request *); + + int (*start_ap)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *link_conf); + void (*stop_ap)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *link_conf); + int (*join_ibss)(struct ieee80211_hw *, struct ieee80211_vif *); + void (*leave_ibss)(struct ieee80211_hw *, struct ieee80211_vif *); + + int (*set_sar_specs)(struct ieee80211_hw *, const struct cfg80211_sar_specs *); + + int (*set_tid_config)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, struct cfg80211_tid_config *); + int (*reset_tid_config)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, u8); + + int (*get_et_sset_count)(struct ieee80211_hw *, struct ieee80211_vif *, int); + void (*get_et_stats)(struct ieee80211_hw *, struct ieee80211_vif *, struct ethtool_stats *, u64 *); + void (*get_et_strings)(struct ieee80211_hw *, struct ieee80211_vif *, u32, u8 *); + + void (*update_vif_offload)(struct ieee80211_hw *, struct ieee80211_vif *); + + int (*get_txpower)(struct ieee80211_hw *, struct ieee80211_vif *, unsigned int, int *); + int (*get_stats)(struct ieee80211_hw *, struct ieee80211_low_level_stats *); + + int (*set_radar_background)(struct ieee80211_hw *, struct cfg80211_chan_def *); + + void (*add_twt_setup)(struct ieee80211_hw *, struct ieee80211_sta *, struct ieee80211_twt_setup *); + void (*twt_teardown_request)(struct ieee80211_hw *, struct ieee80211_sta *, u8); + + int (*set_hw_timestamp)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_set_hw_timestamp *); + + void (*vif_cfg_changed)(struct ieee80211_hw *, struct ieee80211_vif *, u64); + + int (*change_vif_links)(struct ieee80211_hw *, struct ieee80211_vif *, u16, u16, struct ieee80211_bss_conf *[IEEE80211_MLD_MAX_NUM_LINKS]); + int (*change_sta_links)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, u16, u16); + bool (*can_activate_links)(struct ieee80211_hw *, struct ieee80211_vif *, u16); + enum ieee80211_neg_ttlm_res (*can_neg_ttlm)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_neg_ttlm *); + + void (*rfkill_poll)(struct ieee80211_hw *); + +/* #ifdef CONFIG_MAC80211_DEBUGFS */ /* Do not change depending on compile-time option. */ + void (*sta_add_debugfs)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, struct dentry *); + void (*vif_add_debugfs)(struct ieee80211_hw *, struct ieee80211_vif *); + void (*link_sta_add_debugfs)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_link_sta *, struct dentry *); + void (*link_add_debugfs)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, struct dentry *); +/* #endif */ +/* #ifdef CONFIG_PM_SLEEP */ /* Do not change depending on compile-time option. */ + int (*suspend)(struct ieee80211_hw *, struct cfg80211_wowlan *); + int (*resume)(struct ieee80211_hw *); + void (*set_wakeup)(struct ieee80211_hw *, bool); + void (*set_rekey_data)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_gtk_rekey_data *); + void (*set_default_unicast_key)(struct ieee80211_hw *, struct ieee80211_vif *, int); +/* #if IS_ENABLED(CONFIG_IPV6) */ + void (*ipv6_addr_change)(struct ieee80211_hw *, struct ieee80211_vif *, struct inet6_dev *); +/* #endif */ +/* #endif CONFIG_PM_SLEEP */ +}; + +/* -------------------------------------------------------------------------- */ + +/* linux_80211.c */ +extern const struct cfg80211_ops linuxkpi_mac80211cfgops; + +struct ieee80211_hw *linuxkpi_ieee80211_alloc_hw(size_t, + const struct ieee80211_ops *); +void linuxkpi_ieee80211_iffree(struct ieee80211_hw *); +void linuxkpi_set_ieee80211_dev(struct ieee80211_hw *); +int linuxkpi_ieee80211_ifattach(struct ieee80211_hw *); +void linuxkpi_ieee80211_ifdetach(struct ieee80211_hw *); +void linuxkpi_ieee80211_unregister_hw(struct ieee80211_hw *); +struct ieee80211_hw * linuxkpi_wiphy_to_ieee80211_hw(struct wiphy *); +void linuxkpi_ieee80211_restart_hw(struct ieee80211_hw *); +void linuxkpi_ieee80211_iterate_interfaces( + struct ieee80211_hw *hw, enum ieee80211_iface_iter flags, + void(*iterfunc)(void *, uint8_t *, struct ieee80211_vif *), + void *); +void linuxkpi_ieee80211_iterate_keys(struct ieee80211_hw *, + struct ieee80211_vif *, + void(*iterfunc)(struct ieee80211_hw *, struct ieee80211_vif *, + struct ieee80211_sta *, struct ieee80211_key_conf *, void *), + void *, bool); +void linuxkpi_ieee80211_iterate_chan_contexts(struct ieee80211_hw *, + void(*iterfunc)(struct ieee80211_hw *, + struct ieee80211_chanctx_conf *, void *), + void *); +void linuxkpi_ieee80211_iterate_stations_atomic(struct ieee80211_hw *, + void (*iterfunc)(void *, struct ieee80211_sta *), void *); +void linuxkpi_ieee80211_scan_completed(struct ieee80211_hw *, + struct cfg80211_scan_info *); +void linuxkpi_ieee80211_rx(struct ieee80211_hw *, struct sk_buff *, + struct ieee80211_sta *, struct napi_struct *, struct list_head *); +uint8_t linuxkpi_ieee80211_get_tid(struct ieee80211_hdr *, bool); +struct ieee80211_sta *linuxkpi_ieee80211_find_sta(struct ieee80211_vif *, + const u8 *); +struct ieee80211_sta *linuxkpi_ieee80211_find_sta_by_ifaddr( + struct ieee80211_hw *, const uint8_t *, const uint8_t *); +struct sk_buff *linuxkpi_ieee80211_tx_dequeue(struct ieee80211_hw *, + struct ieee80211_txq *); +bool linuxkpi_ieee80211_is_ie_id_in_ie_buf(const u8, const u8 *, size_t); +bool linuxkpi_ieee80211_ie_advance(size_t *, const u8 *, size_t); +void linuxkpi_ieee80211_free_txskb(struct ieee80211_hw *, struct sk_buff *, + int); +void linuxkpi_ieee80211_queue_delayed_work(struct ieee80211_hw *, + struct delayed_work *, int); +void linuxkpi_ieee80211_queue_work(struct ieee80211_hw *, struct work_struct *); +struct sk_buff *linuxkpi_ieee80211_pspoll_get(struct ieee80211_hw *, + struct ieee80211_vif *); +struct sk_buff *linuxkpi_ieee80211_nullfunc_get(struct ieee80211_hw *, + struct ieee80211_vif *, int, bool); +void linuxkpi_ieee80211_txq_get_depth(struct ieee80211_txq *, unsigned long *, + unsigned long *); +struct wireless_dev *linuxkpi_ieee80211_vif_to_wdev(struct ieee80211_vif *); +void linuxkpi_ieee80211_connection_loss(struct ieee80211_vif *); +void linuxkpi_ieee80211_beacon_loss(struct ieee80211_vif *); +struct sk_buff *linuxkpi_ieee80211_probereq_get(struct ieee80211_hw *, + const uint8_t *, const uint8_t *, size_t, size_t); +void linuxkpi_ieee80211_tx_status(struct ieee80211_hw *, struct sk_buff *); +void linuxkpi_ieee80211_tx_status_ext(struct ieee80211_hw *, + struct ieee80211_tx_status *); +void linuxkpi_ieee80211_stop_queues(struct ieee80211_hw *); +void linuxkpi_ieee80211_wake_queues(struct ieee80211_hw *); +void linuxkpi_ieee80211_stop_queue(struct ieee80211_hw *, int); +void linuxkpi_ieee80211_wake_queue(struct ieee80211_hw *, int); +void linuxkpi_ieee80211_txq_schedule_start(struct ieee80211_hw *, uint8_t); +struct ieee80211_txq *linuxkpi_ieee80211_next_txq(struct ieee80211_hw *, uint8_t); +void linuxkpi_ieee80211_schedule_txq(struct ieee80211_hw *, + struct ieee80211_txq *, bool); +void linuxkpi_ieee80211_handle_wake_tx_queue(struct ieee80211_hw *, + struct ieee80211_txq *); + +/* -------------------------------------------------------------------------- */ + +static __inline void +_ieee80211_hw_set(struct ieee80211_hw *hw, enum ieee80211_hw_flags flag) +{ + + set_bit(flag, hw->flags); +} + +static __inline bool +__ieee80211_hw_check(struct ieee80211_hw *hw, enum ieee80211_hw_flags flag) +{ + + return (test_bit(flag, hw->flags)); +} + +/* They pass in shortened flag names; how confusingly inconsistent. */ +#define ieee80211_hw_set(_hw, _flag) \ + _ieee80211_hw_set(_hw, IEEE80211_HW_ ## _flag) +#define ieee80211_hw_check(_hw, _flag) \ + __ieee80211_hw_check(_hw, IEEE80211_HW_ ## _flag) + +/* XXX-BZ add CTASSERTS that size of struct is <= sizeof skb->cb. */ +CTASSERT(sizeof(struct ieee80211_tx_info) <= sizeof(((struct sk_buff *)0)->cb)); +#define IEEE80211_SKB_CB(_skb) \ + ((struct ieee80211_tx_info *)((_skb)->cb)) + +CTASSERT(sizeof(struct ieee80211_rx_status) <= sizeof(((struct sk_buff *)0)->cb)); +#define IEEE80211_SKB_RXCB(_skb) \ + ((struct ieee80211_rx_status *)((_skb)->cb)) + +static __inline void +ieee80211_free_hw(struct ieee80211_hw *hw) +{ + + linuxkpi_ieee80211_iffree(hw); + + if (hw->wiphy != NULL) + wiphy_free(hw->wiphy); + /* Note that *hw is not valid any longer after this. */ + + IMPROVE(); +} + +static __inline struct ieee80211_hw * +ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops) +{ + + return (linuxkpi_ieee80211_alloc_hw(priv_len, ops)); +} + +static __inline void +SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev) +{ + + set_wiphy_dev(hw->wiphy, dev); + linuxkpi_set_ieee80211_dev(hw); + + IMPROVE(); +} + +static __inline int +ieee80211_register_hw(struct ieee80211_hw *hw) +{ + int error; + + error = wiphy_register(hw->wiphy); + if (error != 0) + return (error); + + /* + * At this point the driver has set all the options, flags, bands, + * ciphers, hw address(es), ... basically mac80211/cfg80211 hw/wiphy + * setup is done. + * We need to replicate a lot of information from here into net80211. + */ + error = linuxkpi_ieee80211_ifattach(hw); + + IMPROVE(); + + return (error); +} + +static inline void +ieee80211_unregister_hw(struct ieee80211_hw *hw) +{ + + linuxkpi_ieee80211_unregister_hw(hw); +} + +static __inline struct ieee80211_hw * +wiphy_to_ieee80211_hw(struct wiphy *wiphy) +{ + + return (linuxkpi_wiphy_to_ieee80211_hw(wiphy)); +} + +static inline void +ieee80211_restart_hw(struct ieee80211_hw *hw) +{ + linuxkpi_ieee80211_restart_hw(hw); +} + +static inline void +ieee80211_hw_restart_disconnect(struct ieee80211_vif *vif) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +#define link_conf_dereference_check(_vif, _linkid) \ + rcu_dereference_check((_vif)->link_conf[_linkid], true) + +#define link_conf_dereference_protected(_vif, _linkid) \ + rcu_dereference_protected((_vif)->link_conf[_linkid], true) + +#define link_sta_dereference_check(_sta, _linkid) \ + rcu_dereference_check((_sta)->link[_linkid], true) + +#define link_sta_dereference_protected(_sta, _linkid) \ + rcu_dereference_protected((_sta)->link[_linkid], true) + +#define for_each_vif_active_link(_vif, _link, _linkid) \ + for (_linkid = 0; _linkid < nitems((_vif)->link_conf); _linkid++) \ + if ( ((_vif)->active_links == 0 /* no MLO */ || \ + ((_vif)->active_links & BIT(_linkid)) != 0) && \ + (_link = rcu_dereference((_vif)->link_conf[_linkid])) ) + +#define for_each_sta_active_link(_vif, _sta, _linksta, _linkid) \ + for (_linkid = 0; _linkid < nitems((_sta)->link); _linkid++) \ + if ( ((_vif)->active_links == 0 /* no MLO */ || \ + ((_vif)->active_links & BIT(_linkid)) != 0) && \ + (_linksta = link_sta_dereference_protected((_sta), (_linkid))) ) + +/* -------------------------------------------------------------------------- */ + +static __inline bool +ieee80211_vif_is_mesh(struct ieee80211_vif *vif) +{ + TODO(); + return (false); +} + + +/* -------------------------------------------------------------------------- */ +/* Receive functions (air/driver to mac80211/net80211). */ + + +static __inline void +ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + struct sk_buff *skb, struct napi_struct *napi) +{ + + linuxkpi_ieee80211_rx(hw, skb, sta, napi, NULL); +} + +static __inline void +ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + struct sk_buff *skb, struct list_head *list) +{ + + linuxkpi_ieee80211_rx(hw, skb, sta, NULL, list); +} + +static __inline void +ieee80211_rx_ni(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + + linuxkpi_ieee80211_rx(hw, skb, NULL, NULL, NULL); +} + +static __inline void +ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + + linuxkpi_ieee80211_rx(hw, skb, NULL, NULL, NULL); +} + +static __inline void +ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + + linuxkpi_ieee80211_rx(hw, skb, NULL, NULL, NULL); +} + +/* -------------------------------------------------------------------------- */ + +static inline void +ieee80211_stop_queues(struct ieee80211_hw *hw) +{ + linuxkpi_ieee80211_stop_queues(hw); +} + +static inline void +ieee80211_wake_queues(struct ieee80211_hw *hw) +{ + linuxkpi_ieee80211_wake_queues(hw); +} + +static inline void +ieee80211_stop_queue(struct ieee80211_hw *hw, int qnum) +{ + linuxkpi_ieee80211_stop_queue(hw, qnum); +} + +static inline void +ieee80211_wake_queue(struct ieee80211_hw *hw, int qnum) +{ + linuxkpi_ieee80211_wake_queue(hw, qnum); +} + +static inline void +ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq) +{ + linuxkpi_ieee80211_schedule_txq(hw, txq, true); +} + +static inline void +ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq, + bool withoutpkts) +{ + linuxkpi_ieee80211_schedule_txq(hw, txq, withoutpkts); +} + +static inline void +ieee80211_txq_schedule_start(struct ieee80211_hw *hw, uint8_t ac) +{ + linuxkpi_ieee80211_txq_schedule_start(hw, ac); +} + +static inline void +ieee80211_txq_schedule_end(struct ieee80211_hw *hw, uint8_t ac) +{ + /* DO_NADA; */ +} + +static inline struct ieee80211_txq * +ieee80211_next_txq(struct ieee80211_hw *hw, uint8_t ac) +{ + return (linuxkpi_ieee80211_next_txq(hw, ac)); +} + +static inline void +ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + linuxkpi_ieee80211_handle_wake_tx_queue(hw, txq); +} + +static inline void +ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +static __inline uint8_t +ieee80211_get_tid(struct ieee80211_hdr *hdr) +{ + + return (linuxkpi_ieee80211_get_tid(hdr, false)); +} + +static __inline struct sk_buff * +ieee80211_beacon_get_tim(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + uint16_t *tim_offset, uint16_t *tim_len, uint32_t link_id) +{ + + if (tim_offset != NULL) + *tim_offset = 0; + if (tim_len != NULL) + *tim_len = 0; + TODO(); + return (NULL); +} + +static __inline void +ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, + enum ieee80211_iface_iter flags, + void(*iterfunc)(void *, uint8_t *, struct ieee80211_vif *), + void *arg) +{ + + flags |= IEEE80211_IFACE_ITER__ATOMIC; + flags |= IEEE80211_IFACE_ITER_ACTIVE; + linuxkpi_ieee80211_iterate_interfaces(hw, flags, iterfunc, arg); +} + +static __inline void +ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, + enum ieee80211_iface_iter flags, + void(*iterfunc)(void *, uint8_t *, struct ieee80211_vif *), + void *arg) +{ + + flags |= IEEE80211_IFACE_ITER_ACTIVE; + linuxkpi_ieee80211_iterate_interfaces(hw, flags, iterfunc, arg); +} + +static __inline void +ieee80211_iterate_active_interfaces_mtx(struct ieee80211_hw *hw, + enum ieee80211_iface_iter flags, + void(*iterfunc)(void *, uint8_t *, struct ieee80211_vif *), + void *arg) +{ + flags |= IEEE80211_IFACE_ITER_ACTIVE; + flags |= IEEE80211_IFACE_ITER__MTX; + linuxkpi_ieee80211_iterate_interfaces(hw, flags, iterfunc, arg); +} + +static __inline void +ieee80211_iterate_interfaces(struct ieee80211_hw *hw, + enum ieee80211_iface_iter flags, + void (*iterfunc)(void *, uint8_t *, struct ieee80211_vif *), + void *arg) +{ + + linuxkpi_ieee80211_iterate_interfaces(hw, flags, iterfunc, arg); +} + +static inline void +ieee80211_iter_keys(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void(*iterfunc)(struct ieee80211_hw *, struct ieee80211_vif *, + struct ieee80211_sta *, struct ieee80211_key_conf *, void *), + void *arg) +{ + linuxkpi_ieee80211_iterate_keys(hw, vif, iterfunc, arg, false); +} + +static inline void +ieee80211_iter_keys_rcu(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void(*iterfunc)(struct ieee80211_hw *, struct ieee80211_vif *, + struct ieee80211_sta *, struct ieee80211_key_conf *, void *), + void *arg) +{ + linuxkpi_ieee80211_iterate_keys(hw, vif, iterfunc, arg, true); +} + +static __inline void +ieee80211_iter_chan_contexts_atomic(struct ieee80211_hw *hw, + void(*iterfunc)(struct ieee80211_hw *, struct ieee80211_chanctx_conf *, void *), + void *arg) +{ + + linuxkpi_ieee80211_iterate_chan_contexts(hw, iterfunc, arg); +} + +static __inline void +ieee80211_iter_chan_contexts_mtx(struct ieee80211_hw *hw, + void (*iterfunc)(struct ieee80211_hw *, struct ieee80211_chanctx_conf *, void *), + void *arg) +{ + IMPROVE("XXX LKPI80211 TODO MTX\n"); + linuxkpi_ieee80211_iterate_chan_contexts(hw, iterfunc, arg); +} + +static __inline void +ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw, + void (*iterfunc)(void *, struct ieee80211_sta *), void *arg) +{ + + linuxkpi_ieee80211_iterate_stations_atomic(hw, iterfunc, arg); +} + +static __inline struct wireless_dev * +ieee80211_vif_to_wdev(struct ieee80211_vif *vif) +{ + + return (linuxkpi_ieee80211_vif_to_wdev(vif)); +} + +static __inline struct sk_buff * +ieee80211_beacon_get_template(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct ieee80211_mutable_offsets *offs, + uint32_t link_id) +{ + TODO(); + return (NULL); +} + +static __inline void +ieee80211_beacon_loss(struct ieee80211_vif *vif) +{ + linuxkpi_ieee80211_beacon_loss(vif); +} + +static __inline void +ieee80211_chswitch_done(struct ieee80211_vif *vif, bool t, uint32_t link_id) +{ + TODO(); +} + +static __inline bool +ieee80211_csa_is_complete(struct ieee80211_vif *vif) +{ + TODO(); + return (false); +} + +static __inline void +ieee80211_csa_set_counter(struct ieee80211_vif *vif, uint8_t counter) +{ + TODO(); +} + +static __inline int +ieee80211_csa_update_counter(struct ieee80211_vif *vif) +{ + TODO(); + return (-1); +} + +static __inline void +ieee80211_csa_finish(struct ieee80211_vif *vif, uint32_t link_id) +{ + TODO(); +} + +static inline enum nl80211_iftype +ieee80211_vif_type_p2p(struct ieee80211_vif *vif) +{ + + /* If we are not p2p enabled, just return the type. */ + if (!vif->p2p) + return (vif->type); + + /* If we are p2p, depending on side, return type. */ + switch (vif->type) { + case NL80211_IFTYPE_AP: + return (NL80211_IFTYPE_P2P_GO); + case NL80211_IFTYPE_STATION: + return (NL80211_IFTYPE_P2P_CLIENT); + default: + fallthrough; + } + return (vif->type); +} + +static __inline unsigned long +ieee80211_tu_to_usec(unsigned long tu) +{ + + return (tu * IEEE80211_DUR_TU); +} + +/* + * Below we assume that the two values from different emums are the same. + * Make sure this does not accidentally change. + */ +CTASSERT((int)IEEE80211_ACTION_SM_TPCREP == (int)IEEE80211_ACTION_RADIO_MEASUREMENT_LMREP); + +static __inline bool +ieee80211_action_contains_tpc(struct sk_buff *skb) +{ + struct ieee80211_mgmt *mgmt; + + mgmt = (struct ieee80211_mgmt *)skb->data; + + /* Check that this is a mgmt/action frame? */ + if (!ieee80211_is_action(mgmt->frame_control)) + return (false); + + /* + * This is a bit convoluted but according to docs both actions + * are checked for this. Kind-of makes sense for the only consumer + * (iwlwifi) I am aware off given the txpower fields are at the + * same location so firmware can update the value. + */ + /* 80211-2020 9.6.2 Spectrum Management Action frames */ + /* 80211-2020 9.6.2.5 TPC Report frame format */ + /* 80211-2020 9.6.6 Radio Measurement action details */ + /* 80211-2020 9.6.6.4 Link Measurement Report frame format */ + /* Check that it is Spectrum Management or Radio Measurement? */ + if (mgmt->u.action.category != IEEE80211_ACTION_CAT_SM && + mgmt->u.action.category != IEEE80211_ACTION_CAT_RADIO_MEASUREMENT) + return (false); + + /* + * Check that it is TPC Report or Link Measurement Report? + * The values of each are the same (see CTASSERT above function). + */ + if (mgmt->u.action.u.tpc_report.spec_mgmt != IEEE80211_ACTION_SM_TPCREP) + return (false); + + /* 80211-2020 9.4.2.16 TPC Report element */ + /* Check that the ELEMID and length are correct? */ + if (mgmt->u.action.u.tpc_report.tpc_elem_id != IEEE80211_ELEMID_TPCREP || + mgmt->u.action.u.tpc_report.tpc_elem_length != 4) + return (false); + + /* All the right fields in the right place. */ + return (true); +} + +static __inline void +ieee80211_connection_loss(struct ieee80211_vif *vif) +{ + + linuxkpi_ieee80211_connection_loss(vif); +} + +static __inline struct ieee80211_sta * +ieee80211_find_sta(struct ieee80211_vif *vif, const u8 *peer) +{ + + return (linuxkpi_ieee80211_find_sta(vif, peer)); +} + +static __inline struct ieee80211_sta * +ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw, const uint8_t *addr, + const uint8_t *ourvifaddr) +{ + + return (linuxkpi_ieee80211_find_sta_by_ifaddr(hw, addr, ourvifaddr)); +} + +static __inline size_t +ieee80211_ie_split(const u8 *ies, size_t ies_len, + const u8 *ie_ids, size_t ie_ids_len, size_t start) +{ + size_t x; + + x = start; + + /* XXX FIXME, we need to deal with "Element ID Extension" */ + while (x < ies_len) { + + /* Is this IE[s] one of the ie_ids? */ + if (!linuxkpi_ieee80211_is_ie_id_in_ie_buf(ies[x], + ie_ids, ie_ids_len)) + break; + + if (!linuxkpi_ieee80211_ie_advance(&x, ies, ies_len)) + break; + } + + return (x); +} + +static __inline void +ieee80211_request_smps(struct ieee80211_vif *vif, u_int link_id, + enum ieee80211_smps_mode smps) +{ + static const char *smps_mode_name[] = { + "SMPS_OFF", + "SMPS_STATIC", + "SMPS_DYNAMIC", + "SMPS_AUTOMATIC", + }; + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + if (smps >= nitems(smps_mode_name)) + panic("%s: unsupported smps value: %d\n", __func__, smps); + + IMPROVE("XXX LKPI80211 TODO smps %d %s\n", smps, smps_mode_name[smps]); +} + +static __inline void +ieee80211_tdls_oper_request(struct ieee80211_vif *vif, uint8_t *addr, + enum nl80211_tdls_operation oper, enum ieee80211_reason_code code, + gfp_t gfp) +{ + TODO(); +} + +static __inline void +wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool state) +{ + TODO(); +} + +static __inline void +ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + IMPROVE(); + + /* + * This is called on transmit failure. + * Use a not-so-random random high status error so we can distinguish + * it from normal low values flying around in net80211 ("ETX"). + */ + linuxkpi_ieee80211_free_txskb(hw, skb, 0x455458); +} + +static __inline void +ieee80211_ready_on_channel(struct ieee80211_hw *hw) +{ + TODO(); +/* XXX-BZ We need to see that. */ +} + +static __inline void +ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw) +{ + TODO(); +} + +static __inline void +ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, + enum nl80211_cqm_rssi_threshold_event crte, int sig, gfp_t gfp) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +static inline bool +ieee80211_sn_less(uint16_t sn1, uint16_t sn2) +{ + return (IEEE80211_SEQ_BA_BEFORE(sn1, sn2)); +} + +static inline uint16_t +ieee80211_sn_inc(uint16_t sn) +{ + return (IEEE80211_SEQ_INC(sn)); +} + +static inline uint16_t +ieee80211_sn_add(uint16_t sn, uint16_t a) +{ + return (IEEE80211_SEQ_ADD(sn, a)); +} + +static inline uint16_t +ieee80211_sn_sub(uint16_t sa, uint16_t sb) +{ + return (IEEE80211_SEQ_SUB(sa, sb)); +} + +static __inline void +ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *sta, uint8_t tid, + uint32_t ssn, uint64_t bitmap, uint16_t received_mpdu) +{ + TODO(); +} + +static __inline void +ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, uint32_t x, uint8_t *addr) +{ + TODO(); +} + +static __inline void +ieee80211_rx_ba_timer_expired(struct ieee80211_vif *vif, uint8_t *addr, + uint8_t tid) +{ + TODO(); +} + +static __inline void +ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, uint8_t *addr, + uint8_t tid) +{ + TODO(); +} + +static __inline void +ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, uint8_t *addr, + uint8_t tid) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +static inline void +ieee80211_rate_set_vht(struct ieee80211_tx_rate *r, uint8_t mcs, uint8_t nss) +{ + + /* XXX-BZ make it KASSERTS? */ + if (((mcs & 0xF0) != 0) || (((nss - 1) & 0xf8) != 0)) { + printf("%s:%d: mcs %#04x nss %#04x invalid\n", + __func__, __LINE__, mcs, nss); + return; + } + + r->idx = mcs; + r->idx |= ((nss - 1) << 4); +} + +static inline uint8_t +ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *r) +{ + return (((r->idx >> 4) & 0x07) + 1); +} + +static inline uint8_t +ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *r) +{ + return (r->idx & 0x0f); +} + +static inline int +ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *vht_cap, + enum ieee80211_vht_chanwidth chanwidth, /* defined in net80211. */ + int mcs /* always 0 */, bool ext_nss_bw_cap /* always true */, int max_nss) +{ + enum ieee80211_vht_mcs_support mcs_s; + uint32_t supp_cw, ext_nss_bw; + + switch (mcs) { + case 0 ... 7: + mcs_s = IEEE80211_VHT_MCS_SUPPORT_0_7; + break; + case 8: + mcs_s = IEEE80211_VHT_MCS_SUPPORT_0_8; + break; + case 9: + mcs_s = IEEE80211_VHT_MCS_SUPPORT_0_9; + break; + default: + printf("%s: unsupported mcs value %d\n", __func__, mcs); + return (0); + } + + if (max_nss == 0) { + uint16_t map; + + map = le16toh(vht_cap->supp_mcs.rx_mcs_map); + for (int i = 7; i >= 0; i--) { + uint8_t val; + + val = (map >> (2 * i)) & 0x03; + if (val == IEEE80211_VHT_MCS_NOT_SUPPORTED) + continue; + if (val >= mcs_s) { + max_nss = i + 1; + break; + } + } + } + + if (max_nss == 0) + return (0); + + if ((le16toh(vht_cap->supp_mcs.tx_mcs_map) & + IEEE80211_VHT_EXT_NSS_BW_CAPABLE) == 0) + return (max_nss); + + supp_cw = le32_get_bits(vht_cap->vht_cap_info, + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK); + ext_nss_bw = le32_get_bits(vht_cap->vht_cap_info, + IEEE80211_VHT_CAP_EXT_NSS_BW_MASK); + + /* If requested as ext nss not supported assume ext_nss_bw 0. */ + if (!ext_nss_bw_cap) + ext_nss_bw = 0; + + /* + * Cover 802.11-2016, Table 9-250. + */ + + /* Unsupported settings. */ + if (supp_cw == 3) + return (0); + if (supp_cw == 2 && (ext_nss_bw == 1 || ext_nss_bw == 2)) + return (0); + + /* Settings with factor != 1 or unsupported. */ + switch (chanwidth) { + case IEEE80211_VHT_CHANWIDTH_80P80MHZ: + if (supp_cw == 0 && (ext_nss_bw == 0 || ext_nss_bw == 1)) + return (0); + if (supp_cw == 1 && ext_nss_bw == 0) + return (0); + if ((supp_cw == 0 || supp_cw == 1) && ext_nss_bw == 2) + return (max_nss / 2); + if ((supp_cw == 0 || supp_cw == 1) && ext_nss_bw == 3) + return (3 * max_nss / 4); + break; + case IEEE80211_VHT_CHANWIDTH_160MHZ: + if (supp_cw == 0 && ext_nss_bw == 0) + return (0); + if (supp_cw == 0 && (ext_nss_bw == 1 || ext_nss_bw == 2)) + return (max_nss / 2); + if (supp_cw == 0 && ext_nss_bw == 3) + return (3 * max_nss / 4); + if (supp_cw == 1 && ext_nss_bw == 3) + return (2 * max_nss); + break; + case IEEE80211_VHT_CHANWIDTH_80MHZ: + case IEEE80211_VHT_CHANWIDTH_USE_HT: + if ((supp_cw == 1 || supp_cw == 2) && ext_nss_bw == 3) + return (2 * max_nss); + break; + } + + /* Everything else has a factor of 1. */ + return (max_nss); +} + + +static __inline void +ieee80211_reserve_tid(struct ieee80211_sta *sta, uint8_t tid) +{ + TODO(); +} + +static __inline void +ieee80211_unreserve_tid(struct ieee80211_sta *sta, uint8_t tid) +{ + TODO(); +} + +static __inline void +ieee80211_send_eosp_nullfunc(struct ieee80211_sta *sta, uint8_t tid) +{ + TODO(); +} + +static __inline void +ieee80211_sta_block_awake(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool disable) +{ + TODO(); +} + +static __inline void +ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool sleeping) +{ + TODO(); +} + +static __inline void +ieee80211_sta_pspoll(struct ieee80211_sta *sta) +{ + TODO(); +} + +static inline void +ieee80211_sta_recalc_aggregates(struct ieee80211_sta *sta) +{ + if (sta->valid_links) { + TODO(); + } +} + +static __inline void +ieee80211_sta_uapsd_trigger(struct ieee80211_sta *sta, int ntids) +{ + TODO(); +} + +static inline struct sk_buff * +ieee80211_tx_dequeue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) +{ + + return (linuxkpi_ieee80211_tx_dequeue(hw, txq)); +} + +static inline struct sk_buff * +ieee80211_tx_dequeue_ni(struct ieee80211_hw *hw, struct ieee80211_txq *txq) +{ + struct sk_buff *skb; + + local_bh_disable(); + skb = linuxkpi_ieee80211_tx_dequeue(hw, txq); + local_bh_enable(); + + return (skb); +} + +static __inline void +ieee80211_update_mu_groups(struct ieee80211_vif *vif, + u_int link_id, const uint8_t *ms, const uint8_t *up) +{ + TODO(); +} + +static __inline void +ieee80211_sta_set_buffered(struct ieee80211_sta *sta, uint8_t tid, bool t) +{ + TODO(); +} + +static __inline void +ieee80211_sched_scan_results(struct ieee80211_hw *hw) +{ + TODO(); +} + +static __inline void +ieee80211_sta_eosp(struct ieee80211_sta *sta) +{ + TODO(); +} + +static __inline int +ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, uint8_t tid, int x) +{ + TODO("rtw8x"); + return (-EINVAL); +} + +static __inline int +ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, uint8_t tid) +{ + TODO("rtw89"); + return (-EINVAL); +} + +static __inline void +ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, uint8_t *addr, + uint8_t tid) +{ + TODO("iwlwifi"); +} + +static __inline void +ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, uint8_t *addr, + uint8_t tid) +{ + TODO("iwlwifi/rtw8x/..."); +} + +static __inline void +ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) +{ + TODO(); +} + +static __inline void +ieee80211_scan_completed(struct ieee80211_hw *hw, + struct cfg80211_scan_info *info) +{ + + linuxkpi_ieee80211_scan_completed(hw, info); +} + +static __inline struct sk_buff * +ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + uint32_t link_id) +{ + TODO(); + return (NULL); +} + +static __inline struct sk_buff * +ieee80211_pspoll_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + + /* Only STA needs this. Otherwise return NULL and panic bad drivers. */ + if (vif->type != NL80211_IFTYPE_STATION) + return (NULL); + + return (linuxkpi_ieee80211_pspoll_get(hw, vif)); +} + +static __inline struct sk_buff * +ieee80211_proberesp_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + TODO(); + return (NULL); +} + +static __inline struct sk_buff * +ieee80211_nullfunc_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int linkid, bool qos) +{ + + /* Only STA needs this. Otherwise return NULL and panic bad drivers. */ + if (vif->type != NL80211_IFTYPE_STATION) + return (NULL); + + return (linuxkpi_ieee80211_nullfunc_get(hw, vif, linkid, qos)); +} + +static __inline struct sk_buff * +ieee80211_probereq_get(struct ieee80211_hw *hw, const uint8_t *addr, + const uint8_t *ssid, size_t ssid_len, size_t tailroom) +{ + + return (linuxkpi_ieee80211_probereq_get(hw, addr, ssid, ssid_len, + tailroom)); +} + +static __inline void +ieee80211_queue_delayed_work(struct ieee80211_hw *hw, struct delayed_work *w, + int delay) +{ + + linuxkpi_ieee80211_queue_delayed_work(hw, w, delay); +} + +static __inline void +ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *w) +{ + + linuxkpi_ieee80211_queue_work(hw, w); +} + +static __inline bool +ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct sk_buff *skb, enum nl80211_band band, struct ieee80211_sta **sta) +{ + TODO(); + return (false); +} + +static __inline void +ieee80211_tx_status_skb(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + linuxkpi_ieee80211_tx_status(hw, skb); +} + +static inline void +ieee80211_tx_status_noskb(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + struct ieee80211_tx_info *info) +{ + TODO(); +} + +static __inline void +ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + IMPROVE(); + linuxkpi_ieee80211_tx_status(hw, skb); +} + +static __inline void +ieee80211_tx_status_ni(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + IMPROVE(); + linuxkpi_ieee80211_tx_status(hw, skb); +} + +static __inline void +ieee80211_tx_status_ext(struct ieee80211_hw *hw, + struct ieee80211_tx_status *txstat) +{ + + linuxkpi_ieee80211_tx_status_ext(hw, txstat); +} + +static __inline void +ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) +{ + int i; + + /* + * Apparently clearing flags and some other fields is not right. + * Given the function is called "status" we work on that part of + * the union. + */ + for (i = 0; i < nitems(info->status.rates); i++) + info->status.rates[i].count = 0; + /* + * Unclear if ack_signal should be included or not but we clear the + * "valid" bool so this field is no longer valid. + */ + memset(&info->status.ack_signal, 0, sizeof(*info) - + offsetof(struct ieee80211_tx_info, status.ack_signal)); +} + +static __inline void +ieee80211_txq_get_depth(struct ieee80211_txq *txq, unsigned long *frame_cnt, + unsigned long *byte_cnt) +{ + + if (frame_cnt == NULL && byte_cnt == NULL) + return; + + linuxkpi_ieee80211_txq_get_depth(txq, frame_cnt, byte_cnt); +} + +static __inline void +SET_IEEE80211_PERM_ADDR (struct ieee80211_hw *hw, uint8_t *addr) +{ + + ether_addr_copy(hw->wiphy->perm_addr, addr); +} + +static __inline void +ieee80211_report_low_ack(struct ieee80211_sta *sta, int x) +{ + TODO(); +} + +static __inline void +ieee80211_tx_rate_update(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + struct ieee80211_tx_info *info) +{ + TODO(); +} + +static __inline bool +ieee80211_txq_may_transmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) +{ + TODO(); + return (false); +} + +static __inline void +ieee80211_radar_detected(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *chanctx_conf) +{ + TODO(); +} + +static __inline void +ieee80211_sta_register_airtime(struct ieee80211_sta *sta, + uint8_t tid, uint32_t duration, int x) +{ + TODO(); +} + +static __inline void +ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter) +{ + TODO(); +} + +static __inline int +ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif, uint32_t link_id) +{ + TODO(); + return (-1); +} + +static __inline bool +ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif, uint32_t link_id) +{ + TODO(); + return (true); +} + +static __inline void +ieee80211_disconnect(struct ieee80211_vif *vif, bool _x) +{ + TODO(); +} + +static __inline void +ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif) +{ + TODO(); +} + +static __inline uint32_t +ieee80211_calc_rx_airtime(struct ieee80211_hw *hw, + struct ieee80211_rx_status *rxstat, int len) +{ + TODO(); + return (0); +} + +static __inline void +ieee80211_get_tx_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct sk_buff *skb, struct ieee80211_tx_rate *txrate, int nrates) +{ + TODO(); +} + +static __inline void +ieee80211_color_change_finish(struct ieee80211_vif *vif, uint8_t link_id) +{ + TODO(); +} + +static __inline struct sk_buff * +ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + TODO(); + return (NULL); +} + +static __inline struct sk_buff * +ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + TODO(); + return (NULL); +} + +static __inline void +linuxkpi_ieee80211_send_bar(struct ieee80211_vif *vif, uint8_t *ra, uint16_t tid, + uint16_t ssn) +{ + TODO(); +} + +static __inline void +ieee80211_resume_disconnect(struct ieee80211_vif *vif) +{ + TODO(); +} + +static __inline int +ieee80211_data_to_8023(struct sk_buff *skb, const uint8_t *addr, + enum nl80211_iftype iftype) +{ + TODO(); + return (-1); +} + +/* -------------------------------------------------------------------------- */ + +static __inline void +ieee80211_key_mic_failure(struct ieee80211_key_conf *key) +{ + TODO(); +} + +static __inline void +ieee80211_key_replay(struct ieee80211_key_conf *key) +{ + TODO(); +} + +static __inline void +ieee80211_remove_key(struct ieee80211_key_conf *key) +{ + TODO(); +} + +static __inline struct ieee80211_key_conf * +ieee80211_gtk_rekey_add(struct ieee80211_vif *vif, + uint16_t keyidx, uint8_t *key, size_t keylen, int link_id) +{ + TODO(); + return (NULL); +} + +static __inline void +ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const uint8_t *bssid, + const uint8_t *replay_ctr, gfp_t gfp) +{ + TODO(); +} + +static __inline void +ieee80211_tkip_add_iv(u8 *crypto_hdr, struct ieee80211_key_conf *keyconf, + uint64_t pn) +{ + TODO(); +} + +static __inline void +ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf, + const u8 *addr, uint32_t iv32, u16 *p1k) +{ + + KASSERT(keyconf != NULL && addr != NULL && p1k != NULL, + ("%s: keyconf %p addr %p p1k %p\n", __func__, keyconf, addr, p1k)); + + TODO(); + memset(p1k, 0xfa, 5 * sizeof(*p1k)); /* Just initializing. */ +} + +static __inline void +ieee80211_get_tkip_p1k_iv(struct ieee80211_key_conf *key, + uint32_t iv32, uint16_t *p1k) +{ + TODO(); +} + +static __inline void +ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, + struct sk_buff *skb_frag, u8 *key) +{ + TODO(); +} + +static inline void +ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, int8_t tid, + struct ieee80211_key_seq *seq) +{ + const struct ieee80211_key *k; + const uint8_t *p; + + KASSERT(keyconf != NULL && seq != NULL, ("%s: keyconf %p seq %p\n", + __func__, keyconf, seq)); + k = keyconf->_k; + KASSERT(k != NULL, ("%s: keyconf %p ieee80211_key is NULL\n", __func__, keyconf)); + + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + if (tid < 0 || tid >= IEEE80211_NUM_TIDS) + return; + /* See net80211::tkip_decrypt() */ + seq->tkip.iv32 = TKIP_PN_TO_IV32(k->wk_keyrsc[tid]); + seq->tkip.iv16 = TKIP_PN_TO_IV16(k->wk_keyrsc[tid]); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + if (tid < -1 || tid >= IEEE80211_NUM_TIDS) + return; + if (tid == -1) + p = (const uint8_t *)&k->wk_keyrsc[IEEE80211_NUM_TIDS]; /* IEEE80211_NONQOS_TID */ + else + p = (const uint8_t *)&k->wk_keyrsc[tid]; + memcpy(seq->ccmp.pn, p, sizeof(seq->ccmp.pn)); + break; + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: + if (tid < -1 || tid >= IEEE80211_NUM_TIDS) + return; + if (tid == -1) + p = (const uint8_t *)&k->wk_keyrsc[IEEE80211_NUM_TIDS]; /* IEEE80211_NONQOS_TID */ + else + p = (const uint8_t *)&k->wk_keyrsc[tid]; + memcpy(seq->gcmp.pn, p, sizeof(seq->gcmp.pn)); + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + TODO(); + memset(seq->aes_cmac.pn, 0xfa, sizeof(seq->aes_cmac.pn)); /* XXX TODO */ + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + TODO(); + memset(seq->aes_gmac.pn, 0xfa, sizeof(seq->aes_gmac.pn)); /* XXX TODO */ + break; + default: + pr_debug("%s: unsupported cipher suite %d\n", __func__, keyconf->cipher); + break; + } +} + +static __inline void +ieee80211_set_key_rx_seq(struct ieee80211_key_conf *key, int tid, + struct ieee80211_key_seq *seq) +{ + TODO(); +} + +/* -------------------------------------------------------------------------- */ + +static __inline void +ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, + struct cfg80211_wowlan_wakeup *wakeup, gfp_t gfp) +{ + TODO(); +} + +static __inline void +ieee80211_obss_color_collision_notify(struct ieee80211_vif *vif, + uint64_t obss_color_bitmap, gfp_t gfp) +{ + TODO(); +} + +static __inline void +ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta, + uint8_t tid) +{ + TODO(); +} + +static __inline struct ieee80211_ema_beacons * +ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, uint32_t link_id) +{ + TODO(); + return (NULL); +} + +static __inline void +ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *bcns) +{ + TODO(); +} + +static inline bool +ieee80211_vif_is_mld(const struct ieee80211_vif *vif) +{ + + /* If valid_links is non-zero, the vif is an MLD. */ + return (vif->valid_links != 0); +} + +static inline const struct ieee80211_sta_he_cap * +ieee80211_get_he_iftype_cap_vif(const struct ieee80211_supported_band *band, + struct ieee80211_vif *vif) +{ + enum nl80211_iftype iftype; + + iftype = ieee80211_vif_type_p2p(vif); + return (ieee80211_get_he_iftype_cap(band, iftype)); +} + +static inline const struct ieee80211_sta_eht_cap * +ieee80211_get_eht_iftype_cap_vif(const struct ieee80211_supported_band *band, + struct ieee80211_vif *vif) +{ + enum nl80211_iftype iftype; + + iftype = ieee80211_vif_type_p2p(vif); + return (ieee80211_get_eht_iftype_cap(band, iftype)); +} + +static inline uint32_t +ieee80211_vif_usable_links(const struct ieee80211_vif *vif) +{ + IMPROVE("MLO usable links likely are not just valid"); + return (vif->valid_links); +} + +static inline bool +ieee80211_vif_link_active(const struct ieee80211_vif *vif, uint8_t link_id) +{ + if (ieee80211_vif_is_mld(vif)) + return (vif->active_links & BIT(link_id)); + return (link_id == 0); +} + +static inline void +ieee80211_set_active_links_async(struct ieee80211_vif *vif, + uint32_t new_active_links) +{ + TODO(); +} + +static inline int +ieee80211_set_active_links(struct ieee80211_vif *vif, + uint32_t active_links) +{ + TODO(); + return (-ENXIO); +} + +static inline void +ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp __unused) +{ + IMPROVE("we notify user space by a vap state change eventually"); + linuxkpi_ieee80211_beacon_loss(vif); +} + +#define ieee80211_send_bar(_v, _r, _t, _s) \ + linuxkpi_ieee80211_send_bar(_v, _r, _t, _s) + +/* -------------------------------------------------------------------------- */ + +int lkpi_80211_update_chandef(struct ieee80211_hw *, + struct ieee80211_chanctx_conf *); + +static inline int +ieee80211_emulate_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *chanctx_conf) +{ + int error; + + hw->conf.radar_enabled = chanctx_conf->radar_enabled; + error = lkpi_80211_update_chandef(hw, chanctx_conf); + return (error); +} + +static inline void +ieee80211_emulate_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *chanctx_conf __unused) +{ + hw->conf.radar_enabled = false; + lkpi_80211_update_chandef(hw, NULL); +} + +static inline void +ieee80211_emulate_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *chanctx_conf, uint32_t changed __unused) +{ + hw->conf.radar_enabled = chanctx_conf->radar_enabled; + lkpi_80211_update_chandef(hw, chanctx_conf); +} + +static inline int +ieee80211_emulate_switch_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif_chanctx_switch *vifs, int n_vifs, + enum ieee80211_chanctx_switch_mode mode __unused) +{ + struct ieee80211_chanctx_conf *chanctx_conf; + int error; + + /* Sanity check. */ + if (n_vifs <= 0) + return (-EINVAL); + if (vifs == NULL || vifs[0].new_ctx == NULL) + return (-EINVAL); + + /* + * What to do if n_vifs > 1? + * Does that make sense for drivers not supporting chanctx? + */ + hw->conf.radar_enabled = vifs[0].new_ctx->radar_enabled; + chanctx_conf = vifs[0].new_ctx; + error = lkpi_80211_update_chandef(hw, chanctx_conf); + return (error); +} + +/* -------------------------------------------------------------------------- */ + +#endif /* _LINUXKPI_NET_MAC80211_H */ diff --git a/sys/compat/linuxkpi/common/include/net/netevent.h b/sys/compat/linuxkpi/common/include/net/netevent.h index 3c6fba2f28d6..c1c39af3a772 100644 --- a/sys/compat/linuxkpi/common/include/net/netevent.h +++ b/sys/compat/linuxkpi/common/include/net/netevent.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NET_NETEVENT_H_ -#define _LINUX_NET_NETEVENT_H_ +#ifndef _LINUXKPI_NET_NETEVENT_H_ +#define _LINUXKPI_NET_NETEVENT_H_ #include <sys/types.h> #include <sys/eventhandler.h> @@ -72,4 +70,4 @@ unregister_netevent_notifier(struct notifier_block *nb) return (0); } -#endif /* _LINUX_NET_NETEVENT_H_ */ +#endif /* _LINUXKPI_NET_NETEVENT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/net/netlink.h b/sys/compat/linuxkpi/common/include/net/netlink.h new file mode 100644 index 000000000000..ae250177d18b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/net/netlink.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2020,2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_NET_NETLINK_H +#define _LINUXKPI_NET_NETLINK_H + +#include <netlink/netlink.h> + +struct nla_policy { +}; + +struct netlink_callback { + int args[8]; +}; + +static __inline int +nla_put(struct sk_buff *skb, int attr, size_t len, void *data) +{ + + pr_debug("%s: TODO -- now native?\n", __func__); + return (-ENXIO); +} + +static __inline int +nla_put_u16(struct sk_buff *skb, int attr, uint32_t val) +{ + + return (nla_put(skb, attr, sizeof(uint32_t), &val)); +} + +#endif /* _LINUXKPI_NET_NETLINK_H */ diff --git a/sys/compat/linuxkpi/common/include/net/netmem.h b/sys/compat/linuxkpi/common/include/net/netmem.h new file mode 100644 index 000000000000..c8de09a2e8c2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/net/netmem.h @@ -0,0 +1,21 @@ +/*- + * Copyright (c) 2023-2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_NET_NETMEM_H +#define _LINUXKPI_NET_NETMEM_H + +struct page_pool; + +struct netmem_desc { + struct page_pool *pp; +}; + +#define pp_page_to_nmdesc(page) \ + (_Generic((page), \ + const struct page *: (const struct netmem_desc *)(page), \ + struct page *: (struct netmem_desc *)(page))) + +#endif /* _LINUXKPI_NET_NETMEM_H */ diff --git a/sys/compat/linuxkpi/common/include/net/page_pool/helpers.h b/sys/compat/linuxkpi/common/include/net/page_pool/helpers.h new file mode 100644 index 000000000000..3469c39c7757 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/net/page_pool/helpers.h @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2023-2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_NET_PAGE_POOL_HELPERS_H +#define _LINUXKPI_NET_PAGE_POOL_HELPERS_H + +#include <linux/kernel.h> /* pr_debug */ +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <net/page_pool/types.h> + +static inline struct page_pool * +page_pool_create(const struct page_pool_params *ppparams) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline void +page_pool_destroy(struct page_pool *ppool) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static inline struct page * +page_pool_dev_alloc_frag(struct page_pool *ppool, uint32_t *offset, + size_t size) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline dma_addr_t +page_pool_get_dma_addr(struct page *page) +{ + + pr_debug("%s: TODO\n", __func__); + return (0); +} + +static inline enum dma_data_direction +page_pool_get_dma_dir(const struct page_pool *ppool) +{ + + pr_debug("%s: TODO\n", __func__); + return (DMA_BIDIRECTIONAL); +} + +static inline void +page_pool_put_full_page(struct page_pool *ppool, struct page *page, + bool allow_direct) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static inline int +page_pool_ethtool_stats_get_count(void) +{ + + pr_debug("%s: TODO\n", __func__); + return (0); +} + +static inline uint8_t * +page_pool_ethtool_stats_get_strings(uint8_t *x) +{ + + pr_debug("%s: TODO\n", __func__); + return (x); +} + +#endif /* _LINUXKPI_NET_PAGE_POOL_HELPERS_H */ diff --git a/sys/compat/linuxkpi/common/include/net/page_pool/types.h b/sys/compat/linuxkpi/common/include/net/page_pool/types.h new file mode 100644 index 000000000000..6747be50b9b2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/net/page_pool/types.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2023-2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_NET_PAGE_POOL_TYPES_H +#define _LINUXKPI_NET_PAGE_POOL_TYPES_H + +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <net/netmem.h> + +struct device; +struct napi_struct; + +struct page_pool_params { + struct device *dev; + uint32_t flags; + uint32_t order; + uint32_t pool_size; + uint32_t max_len; + uint32_t offset; + int nid; /* NUMA */ + enum dma_data_direction dma_dir; + struct napi_struct *napi; +}; + +struct page_pool { +}; + +#define PP_FLAG_DMA_MAP BIT(0) +#define PP_FLAG_DMA_SYNC_DEV BIT(1) +#define PP_FLAG_PAGE_FRAG BIT(2) + +#endif /* _LINUXKPI_NET_PAGE_POOL_TYPES_H */ diff --git a/sys/compat/linuxkpi/common/include/net/regulatory.h b/sys/compat/linuxkpi/common/include/net/regulatory.h new file mode 100644 index 000000000000..0a538f1531f9 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/net/regulatory.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2021-2022 Bjoern A. Zeeb + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_NET_REGULATORY_H +#define _LINUXKPI_NET_REGULATORY_H + +enum environment_cap { + ENVIRON_INDOOR = 1, /* keep != 0 */ +}; + +#define REG_RULE(_begin, _end, _bw, _mag, _meirp, _flags) \ +{ \ + .flags = (_flags), \ + .freq_range.start_freq_khz = MHZ_TO_KHZ(_begin), \ + .freq_range.end_freq_khz = MHZ_TO_KHZ(_end), \ + .freq_range.max_bandwidth_khz = MHZ_TO_KHZ(_bw), \ + .power_rule.max_antenna_gain = DBI_TO_MBI(_mag), \ + .power_rule.max_eirp = DBI_TO_MBI(_meirp), \ +} + +#endif /* _LINUXKPI_NET_REGULATORY_H */ diff --git a/sys/compat/linuxkpi/common/include/net/tcp.h b/sys/compat/linuxkpi/common/include/net/tcp.h index 3f156196aaaf..4804a2b09b9d 100644 --- a/sys/compat/linuxkpi/common/include/net/tcp.h +++ b/sys/compat/linuxkpi/common/include/net/tcp.h @@ -25,11 +25,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -#ifndef _LINUX_NET_TCP_H_ -#define _LINUX_NET_TCP_H_ +#ifndef _LINUXKPI_NET_TCP_H_ +#define _LINUXKPI_NET_TCP_H_ #include <linux/list.h> #include <linux/slab.h> @@ -37,4 +35,4 @@ #include <net/ip.h> -#endif /* _LINUX_NET_TCP_H_ */ +#endif /* _LINUXKPI_NET_TCP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/stdarg.h b/sys/compat/linuxkpi/common/include/stdarg.h new file mode 100644 index 000000000000..698ac45e9198 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/stdarg.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_STDARG_H_ +#define _LINUXKPI_STDARG_H_ + +#include <sys/stdarg.h> + +#endif /* _LINUXKPI_STDARG_H_ */ diff --git a/sys/compat/linuxkpi/common/include/video/cmdline.h b/sys/compat/linuxkpi/common/include/video/cmdline.h new file mode 100644 index 000000000000..eaa9a998fda2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/video/cmdline.h @@ -0,0 +1,44 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _VIDEO_CMDLINE_H_ +#define _VIDEO_CMDLINE_H_ + +#include <linux/types.h> + +#define CONFIG_VIDEO_CMDLINE + +#if defined(CONFIG_VIDEO_CMDLINE) +const char *video_get_options(const char *name); +#else +static inline const char * +video_get_options(const char *name) +{ + return (NULL); +} +#endif +#endif /* _VIDEO_CMDLINE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/video/mipi_display.h b/sys/compat/linuxkpi/common/include/video/mipi_display.h new file mode 100644 index 000000000000..ea079a57d39f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/video/mipi_display.h @@ -0,0 +1,64 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_VIDEO_MIPI_DISPLAY_H_ +#define _LINUXKPI_VIDEO_MIPI_DISPLAY_H_ + +#define MIPI_DSI_V_SYNC_START 0x01 +#define MIPI_DSI_V_SYNC_END 0x11 +#define MIPI_DSI_H_SYNC_START 0x21 +#define MIPI_DSI_H_SYNC_END 0x31 +#define MIPI_DSI_COMPRESSION_MODE 0x07 +#define MIPI_DSI_END_OF_TRANSMISSION 0x08 +#define MIPI_DSI_COLOR_MODE_OFF 0x02 +#define MIPI_DSI_COLOR_MODE_ON 0x12 +#define MIPI_DSI_SHUTDOWN_PERIPHERAL 0x22 +#define MIPI_DSI_TURN_ON_PERIPHERAL 0x32 +#define MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM 0x03 +#define MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM 0x13 +#define MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23 +#define MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM 0x04 +#define MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM 0x14 +#define MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM 0x24 +#define MIPI_DSI_DCS_SHORT_WRITE 0x05 +#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15 +#define MIPI_DSI_DCS_READ 0x06 +#define MIPI_DSI_EXECUTE_QUEUE 0x16 +#define MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE 0x37 +#define MIPI_DSI_NULL_PACKET 0x09 +#define MIPI_DSI_BLANKING_PACKET 0x19 +#define MIPI_DSI_GENERIC_LONG_WRITE 0x29 +#define MIPI_DSI_DCS_LONG_WRITE 0x39 +#define MIPI_DSI_PICTURE_PARAMETER_SET 0x0a +#define MIPI_DSI_COMPRESSED_PIXEL_STREAM 0x0b +#define MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 0x0c +#define MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 0x1c +#define MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 0x2c +#define MIPI_DSI_PACKED_PIXEL_STREAM_30 0x0d +#define MIPI_DSI_PACKED_PIXEL_STREAM_36 0x1d +#define MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12 0x3d +#define MIPI_DSI_PACKED_PIXEL_STREAM_16 0x0e +#define MIPI_DSI_PACKED_PIXEL_STREAM_18 0x1e +#define MIPI_DSI_PIXEL_STREAM_3BYTE_18 0x2e +#define MIPI_DSI_PACKED_PIXEL_STREAM_24 0x3e + +#define MIPI_DCS_NOP 0x00 +#define MIPI_DCS_SOFT_RESET 0x01 +#define MIPI_DCS_GET_POWER_MODE 0x0a +#define MIPI_DCS_GET_PIXEL_FORMAT 0x0c +#define MIPI_DCS_ENTER_SLEEP_MODE 0x10 +#define MIPI_DCS_EXIT_SLEEP_MODE 0x11 +#define MIPI_DCS_SET_DISPLAY_OFF 0x28 +#define MIPI_DCS_SET_DISPLAY_ON 0x29 +#define MIPI_DCS_SET_COLUMN_ADDRESS 0x2a +#define MIPI_DCS_SET_PAGE_ADDRESS 0x2b +#define MIPI_DCS_SET_TEAR_OFF 0x34 +#define MIPI_DCS_SET_TEAR_ON 0x35 +#define MIPI_DCS_SET_PIXEL_FORMAT 0x3a +#define MIPI_DCS_SET_TEAR_SCANLINE 0x44 +#define MIPI_DCS_SET_DISPLAY_BRIGHTNESS 0x51 +#define MIPI_DCS_GET_DISPLAY_BRIGHTNESS 0x52 +#define MIPI_DCS_WRITE_CONTROL_DISPLAY 0x53 +#define MIPI_DCS_GET_CONTROL_DISPLAY 0x54 +#define MIPI_DCS_WRITE_POWER_SAVE 0x55 + +#endif /* _LINUXKPI_VIDEO_MIPI_DISPLAY_H_ */ diff --git a/sys/compat/linuxkpi/common/include/video/vga.h b/sys/compat/linuxkpi/common/include/video/vga.h new file mode 100644 index 000000000000..a5012d9e2f3f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/video/vga.h @@ -0,0 +1,19 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_VIDEO_VGA_H +#define _LINUXKPI_VIDEO_VGA_H + +#include <linux/types.h> +#include <linux/io.h> + +#define VGA_MIS_W 0x3c2 +#define VGA_SEQ_I 0x3c4 +#define VGA_SEQ_D 0x3c5 +#define VGA_MIS_R 0x3cc + +#define VGA_SR01_SCREEN_OFF (1 << 5) + +#define VGA_FB_PHYS_BASE 0xA0000 +#define VGA_FB_PHYS_SIZE 65536 + +#endif diff --git a/sys/compat/linuxkpi/common/include/xen/xen.h b/sys/compat/linuxkpi/common/include/xen/xen.h new file mode 100644 index 000000000000..16e77724111d --- /dev/null +++ b/sys/compat/linuxkpi/common/include/xen/xen.h @@ -0,0 +1,37 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_XEN_XEN_H_ +#define _LINUXKPI_XEN_XEN_H_ + +#define xen_initial_domain() lkpi_xen_initial_domain() +#define xen_pv_domain() lkpi_xen_pv_domain() + +bool lkpi_xen_initial_domain(void); +bool lkpi_xen_pv_domain(void); + +#endif /* _LINUXKPI_XEN_XEN_H_ */ |
