diff options
Diffstat (limited to 'sys/compat/linuxkpi/common/include/linux')
67 files changed, 1961 insertions, 271 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/acpi.h b/sys/compat/linuxkpi/common/include/linux/acpi.h index 3e1ec1b20626..a764a975c983 100644 --- a/sys/compat/linuxkpi/common/include/linux/acpi.h +++ b/sys/compat/linuxkpi/common/include/linux/acpi.h @@ -32,7 +32,7 @@ #include <linux/device.h> #include <linux/uuid.h> -#if defined(__aarch64__) || defined(__amd64__) || defined(__i386__) +#if defined(__aarch64__) || defined(__amd64__) || defined(__i386__) || defined(__riscv) #include <acpi/acpi.h> #include <acpi/acpi_bus.h> diff --git a/sys/compat/linuxkpi/common/include/linux/ascii85.h b/sys/compat/linuxkpi/common/include/linux/ascii85.h new file mode 100644 index 000000000000..06777a130e41 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ascii85.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 The FreeBSD Foundation + */ + +#ifndef _LINUXKPI_LINUX_ASCII85_H_ +#define _LINUXKPI_LINUX_ASCII85_H_ + +#include <sys/param.h> + +#define ASCII85_BUFSZ 6 + +static inline long +ascii85_encode_len(long in_len) +{ + long out_len; + + out_len = howmany(in_len, 4); + + return (out_len); +} + +static inline const char * +ascii85_encode(uint32_t in, char *out) +{ + int i; + + if (in == 0) { + out[0] = 'z'; + out[1] = '\0'; + return (out); + } + + for (i = ASCII85_BUFSZ - 2; i >= 0; i--) { + out[i] = in % 85; + out[i] += 33; + + in /= 85; + } + out[ASCII85_BUFSZ - 1] = '\0'; + + return (out); +} + +#endif /* _LINUXKPI_LINUX_ASCII85_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/bcm47xx_nvram.h b/sys/compat/linuxkpi/common/include/linux/bcm47xx_nvram.h new file mode 100644 index 000000000000..744101a2f8b1 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/bcm47xx_nvram.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_BCM47XX_NVRAM_H +#define _LINUXKPI_LINUX_BCM47XX_NVRAM_H + +static inline char * +bcm47xx_nvram_get_contents(size_t *x __unused) +{ + return (NULL); +}; + +static inline void +bcm47xx_nvram_release_contents(const char *x __unused) +{ +}; + +#endif /* _LINUXKPI_LINUX_BCM47XX_NVRAM_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/bcma/bcma.h b/sys/compat/linuxkpi/common/include/linux/bcma/bcma.h new file mode 100644 index 000000000000..3840c3a420e5 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/bcma/bcma.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_BCMA_BCMA_H +#define _LINUXKPI_LINUX_BCMA_BCMA_H + +#define BCMA_CORE_80211 0x812 +#define BCMA_CORE_ARM_CA7 0x847 +#define BCMA_CORE_ARM_CM3 0x82A +#define BCMA_CORE_ARM_CR4 0x83E +#define BCMA_CORE_CHIPCOMMON 0x800 +#define BCMA_CORE_GCI 0x840 +#define BCMA_CORE_INTERNAL_MEM 0x80E +#define BCMA_CORE_PCIE2 0x83C +#define BCMA_CORE_PMU 0x827 +#define BCMA_CORE_SDIO_DEV 0x829 +#define BCMA_CORE_SYS_MEM 0x849 + +/* XXX not sure where these belong. */ +#define BCMA_CC_CAP_EXT_AOB_PRESENT 0x00000040 +#define BCMA_CC_PMU_CTL_RES_SHIFT 13 +#define BCMA_CC_PMU_CTL_RES_RELOAD 0x2 +#define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010 +#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020 + +#endif /* _LINUXKPI_LINUX_BCMA_BCMA_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/bcma/bcma_regs.h b/sys/compat/linuxkpi/common/include/linux/bcma/bcma_regs.h new file mode 100644 index 000000000000..0a4cdddf7a73 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/bcma/bcma_regs.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_BCMA_BCMA_REGS_H +#define _LINUXKPI_LINUX_BCMA_BCMA_REGS_H + +#define BCMA_IOCTL 0x0408 +#define BCMA_IOCTL_CLK 0x0001 +#define BCMA_IOCTL_FGC 0x0002 + +#define BCMA_RESET_CTL 0x0800 +#define BCMA_RESET_CTL_RESET 0x0001 + +#endif /* _LINUXKPI_LINUX_BCMA_BCMA_REGS_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/bitops.h b/sys/compat/linuxkpi/common/include/linux/bitops.h index 8fac80820f30..125081ab5b74 100644 --- a/sys/compat/linuxkpi/common/include/linux/bitops.h +++ b/sys/compat/linuxkpi/common/include/linux/bitops.h @@ -51,12 +51,6 @@ #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) -#define hweight32(x) bitcount32(x) -#define hweight64(x) bitcount64(x) -#define hweight_long(x) bitcountl(x) - #if __has_builtin(__builtin_popcountg) #define HWEIGHT8(x) (__builtin_popcountg((uint8_t)(x))) #define HWEIGHT16(x) (__builtin_popcountg((uint16_t)(x))) @@ -70,6 +64,12 @@ #define HWEIGHT64(x) (__const_bitcount64((uint64_t)(x))) #endif +#define hweight8(x) (__builtin_constant_p(x) ? HWEIGHT8(x) : bitcount((uint8_t)(x))) +#define hweight16(x) (__builtin_constant_p(x) ? HWEIGHT16(x) : bitcount16(x)) +#define hweight32(x) (__builtin_constant_p(x) ? HWEIGHT32(x) : bitcount32(x)) +#define hweight64(x) (__builtin_constant_p(x) ? HWEIGHT64(x) : bitcount64(x)) +#define hweight_long(x) bitcountl(x) + static inline int __ffs(int mask) { @@ -437,4 +437,16 @@ sign_extend32(uint32_t value, int index) return ((int32_t)(value << shift) >> shift); } +static inline uint64_t +rol64(uint64_t word, unsigned int shift) +{ + return ((word << (shift & 63)) | (word >> ((-shift) & 63))); +} + +static inline uint32_t +rol32(uint32_t word, unsigned int shift) +{ + return ((word << (shift & 31)) | (word >> ((-shift) & 31))); +} + #endif /* _LINUXKPI_LINUX_BITOPS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cec-funcs.h b/sys/compat/linuxkpi/common/include/linux/cec-funcs.h new file mode 100644 index 000000000000..1107b04e4e08 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cec-funcs.h @@ -0,0 +1,16 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025-2026 The FreeBSD Foundation + * Copyright (c) 2025-2026 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + */ + +#ifndef _LINUXKPI_LINUX_CEC_FUNCS_H_ +#define _LINUXKPI_LINUX_CEC_FUNCS_H_ + +#include <linux/cec.h> + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/cec.h b/sys/compat/linuxkpi/common/include/linux/cec.h index e0854d87d85c..b08d891537a9 100644 --- a/sys/compat/linuxkpi/common/include/linux/cec.h +++ b/sys/compat/linuxkpi/common/include/linux/cec.h @@ -3,6 +3,9 @@ #ifndef _LINUXKPI_LINUX_CEC_H_ #define _LINUXKPI_LINUX_CEC_H_ +#include <linux/types.h> +#include <linux/string.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 index a9dd22fd0f4c..c75404fd6cf3 100644 --- a/sys/compat/linuxkpi/common/include/linux/cgroup.h +++ b/sys/compat/linuxkpi/common/include/linux/cgroup.h @@ -29,6 +29,15 @@ #ifndef _LINUXKPI_LINUX_CGROUP_H_ #define _LINUXKPI_LINUX_CGROUP_H_ +#include <linux/sched.h> +#include <linux/nodemask.h> +#include <linux/list.h> +#include <linux/rculist.h> +#include <linux/fs.h> +#include <linux/seq_file.h> +#include <linux/jump_label.h> +#include <linux/types.h> +#include <linux/refcount.h> #include <linux/kernel_stat.h> #endif /* _LINUXKPI_LINUX_CGROUP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cleanup.h b/sys/compat/linuxkpi/common/include/linux/cleanup.h index 5bb146f082ed..fb21a81f121b 100644 --- a/sys/compat/linuxkpi/common/include/linux/cleanup.h +++ b/sys/compat/linuxkpi/common/include/linux/cleanup.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2024-2025 The FreeBSD Foundation + * Copyright (c) 2024-2026 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -10,18 +10,26 @@ #ifndef _LINUXKPI_LINUX_CLEANUP_H #define _LINUXKPI_LINUX_CLEANUP_H +#include <linux/err.h> + +#define CLEANUP_NAME(_n, _s) __CONCAT(__CONCAT(cleanup_, _n), _s) + #define __cleanup(_f) __attribute__((__cleanup__(_f))) +#define DECLARE(_n, _x) \ + CLEANUP_NAME(_n, _t) _x __cleanup(CLEANUP_NAME(_n, _destroy)) = \ + CLEANUP_NAME(_n, _create) + /* * 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; \ + typedef _dt CLEANUP_NAME(_n, _t); \ \ static inline _dt \ - guard_ ## _n ## _create( _dt _T) \ + CLEANUP_NAME(_n, _create)( _dt _T) \ { \ _dt c; \ \ @@ -30,7 +38,7 @@ } \ \ static inline void \ - guard_ ## _n ## _destroy(_dt *t) \ + CLEANUP_NAME(_n, _destroy)(_dt *t) \ { \ _dt _T; \ \ @@ -39,9 +47,10 @@ } /* We need to keep these calls unique. */ +#define _guard(_n, _x) \ + DECLARE(_n, _x) #define guard(_n) \ - guard_ ## _n ## _t guard_ ## _n ## _ ## __COUNTER__ \ - __cleanup(guard_ ## _n ## _destroy) = guard_ ## _n ## _create + _guard(_n, guard_ ## _n ## _ ## __COUNTER__) #define DEFINE_FREE(_n, _t, _f) \ static inline void \ @@ -56,38 +65,100 @@ #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). + * Our initial version go broken up. Some simplifications like using + * "bool" for the lock had to be changed to a more general type. + * _T is still special and, like other bits, may not always be used, + * so tag with __unused (or better the LinuxKPI __maybe_unused). */ -#define DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...) \ +#define _DEFINE_LOCK_GUARD_0(_n, _lock) \ + static inline CLEANUP_NAME(_n, _t) \ + CLEANUP_NAME(_n, _create)(void) \ + { \ + CLEANUP_NAME(_n, _t) _tmp; \ + CLEANUP_NAME(_n, _t) *_T __maybe_unused; \ + \ + _tmp.lock = (void *)1; \ + _T = &_tmp; \ + _lock; \ + return (_tmp); \ + } + +#define _DEFINE_LOCK_GUARD_1(_n, _type, _lock) \ + static inline CLEANUP_NAME(_n, _t) \ + CLEANUP_NAME(_n, _create)(_type *l) \ + { \ + CLEANUP_NAME(_n, _t) _tmp; \ + CLEANUP_NAME(_n, _t) *_T __maybe_unused; \ \ + _tmp.lock = l; \ + _T = &_tmp; \ + _lock; \ + return (_tmp); \ + } + +#define _GUARD_IS_ERR(_v) \ + ({ \ + uintptr_t x = (uintptr_t)(void *)(_v); \ + IS_ERR_VALUE(x); \ + }) + +#define __is_cond_ptr(_n) \ + CLEANUP_NAME(_n, _is_cond) +#define __guard_ptr(_n) \ + CLEANUP_NAME(_n, _ptr) + +#define _DEFINE_CLEANUP_IS_CONDITIONAL(_n, _b) \ + static const bool CLEANUP_NAME(_n, _is_cond) __maybe_unused = _b + +#define _DEFINE_GUARD_LOCK_PTR(_n, _lp) \ + static inline void * \ + CLEANUP_NAME(_n, _lock_ptr)(CLEANUP_NAME(_n, _t) *_T) \ + { \ + void *_p; \ + \ + _p = (void *)(uintptr_t)*(_lp); \ + if (IS_ERR(_p)) \ + _p = NULL; \ + return (_p); \ + } + +#define _DEFINE_UNLOCK_GUARD(_n, _type, _unlock, ...) \ typedef struct { \ - bool lock; \ + _type *lock; \ __VA_ARGS__; \ - } guard_ ## _n ## _t; \ + } CLEANUP_NAME(_n, _t); \ \ static inline void \ - guard_ ## _n ## _destroy(guard_ ## _n ## _t *_T) \ + CLEANUP_NAME(_n, _destroy)(CLEANUP_NAME(_n, _t) *_T) \ { \ - if (_T->lock) { \ + if (!_GUARD_IS_ERR(_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); \ - } + _DEFINE_GUARD_LOCK_PTR(_n, &_T->lock) + +#define DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...) \ + _DEFINE_CLEANUP_IS_CONDITIONAL(_n, false); \ + _DEFINE_UNLOCK_GUARD(_n, void, _unlock, __VA_ARGS__) \ + _DEFINE_LOCK_GUARD_0(_n, _lock) + +/* This allows the type to be set. */ +#define DEFINE_LOCK_GUARD_1(_n, _t, _lock, _unlock, ...) \ + _DEFINE_CLEANUP_IS_CONDITIONAL(_n, false); \ + _DEFINE_UNLOCK_GUARD(_n, _t, _unlock, __VA_ARGS__) \ + _DEFINE_LOCK_GUARD_1(_n, _t, _lock) + +#define _scoped_guard(_n, _l, ...) \ + for (DECLARE(_n, _scoped)(__VA_ARGS__); \ + 1 /*__guard_ptr(_n)(&_scoped) || !__is_cond_ptr(_n) */; \ + ({ goto _l; })) \ + if (0) { \ +_l: \ + break; \ + } else + +#define scoped_guard(_n, ...) \ + _scoped_guard(_n, ___label_ ## __COUNTER__, ##__VA_ARGS__) #endif /* _LINUXKPI_LINUX_CLEANUP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/compiler.h b/sys/compat/linuxkpi/common/include/linux/compiler.h index 4146c829b936..90d907dd4d45 100644 --- a/sys/compat/linuxkpi/common/include/linux/compiler.h +++ b/sys/compat/linuxkpi/common/include/linux/compiler.h @@ -33,48 +33,18 @@ #include <sys/cdefs.h> #include <sys/endian.h> -#define __user -#define __kernel -#define __safe -#define __force -#define __nocast -#define __iomem -#define __chk_user_ptr(x) ((void)0) -#define __chk_io_ptr(x) ((void)0) -#define __builtin_warning(x, y...) (1) -#define __acquires(x) -#define __releases(x) -#define __acquire(x) do { } while (0) -#define __release(x) do { } while (0) -#define __cond_lock(x,c) (c) +#include <compat/linuxkpi/common/include/linux/compiler_types.h> + #define __bitwise #define __devinitdata -#ifndef __deprecated -#define __deprecated -#endif #define __init #define __initconst #define __devinit #define __devexit #define __exit -#define __rcu -#define __percpu -#define __weak __weak_symbol -#define __malloc -#define __attribute_const__ __attribute__((__const__)) -#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 @@ -93,24 +63,12 @@ #define typeof(x) __typeof(x) #define uninitialized_var(x) x = x -#define __maybe_unused __unused -#define __always_unused __unused -#define __must_check __result_use_check - -#define __printf(a,b) __printflike(a,b) - -#define __diag_push() -#define __diag_pop() -#define __diag_ignore_all(...) #define barrier() __asm__ __volatile__("": : :"memory") #define lower_32_bits(n) ((u32)(n)) #define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) -#define ___PASTE(a,b) a##b -#define __PASTE(a,b) ___PASTE(a,b) - #define WRITE_ONCE(x,v) do { \ barrier(); \ (*(volatile __typeof(x) *)(uintptr_t)&(x)) = (v); \ @@ -129,8 +87,6 @@ #define lockless_dereference(p) READ_ONCE(p) #define _AT(T,X) ((T)(X)) - -#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define __must_be_array(a) __same_type(a, &(a)[0]) #define sizeof_field(_s, _m) sizeof(((_s *)0)->_m) diff --git a/sys/compat/linuxkpi/common/include/linux/compiler_attributes.h b/sys/compat/linuxkpi/common/include/linux/compiler_attributes.h new file mode 100644 index 000000000000..42908bb6c2b5 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/compiler_attributes.h @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. + * Copyright (c) 2015 François Tigeot + * All rights reserved. + */ + +#ifndef _LINUXKPI_LINUX_COMPILER_ATTRIBUTES_H_ +#define _LINUXKPI_LINUX_COMPILER_ATTRIBUTES_H_ + +#include <sys/cdefs.h> + +#define __attribute_const__ __attribute__((__const__)) + +#ifndef __deprecated +#define __deprecated +#endif + +#define fallthrough /* FALLTHROUGH */ do { } while(0) + +#undef __always_inline +#define __always_inline inline + +#define __printf(a,b) __printflike(a,b) + +#define __malloc + +#define noinline __noinline + +#if __has_attribute(__nonstring__) +#define __nonstring __attribute__((__nonstring__)) +#else +#define __nonstring +#endif + +#define noinline_for_stack __noinline + +#define __maybe_unused __unused +#define __always_unused __unused + +#define __must_check __result_use_check + +#define __weak __weak_symbol + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/compiler_types.h b/sys/compat/linuxkpi/common/include/linux/compiler_types.h new file mode 100644 index 000000000000..25e69f5afd8e --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/compiler_types.h @@ -0,0 +1,58 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. + * Copyright (c) 2015 François Tigeot + * All rights reserved. + */ + +#ifndef _LINUXKPI_LINUX_COMPILER_TYPES_H_ +#define _LINUXKPI_LINUX_COMPILER_TYPES_H_ + +#include <sys/cdefs.h> + +#include <compat/linuxkpi/common/include/linux/compiler_attributes.h> + +#define __kernel +#define __user +#define __iomem +#define __percpu +#define __rcu +#define __chk_user_ptr(x) ((void)0) +#define __chk_io_ptr(x) ((void)0) +#define __acquires(x) +#define __releases(x) +#define __acquire(x) do { } while (0) +#define __release(x) do { } while (0) +#define __cond_lock(x,c) (c) +#define __force +#define __nocast +#define __safe +#define __builtin_warning(x, y...) (1) + +#define ___PASTE(a,b) a##b +#define __PASTE(a,b) ___PASTE(a,b) + +#define __diag_push() +#define __diag_pop() +#define __diag_ignore_all(...) + +#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) + +/* + * __builtin_counted_by_ref was introduced to + * - gcc in e7380688fa59 with a first release tag of gcc-15.1.0, + * - llvm in 7475156d49406 with a first release tag of llvmorg-20.1.0-rc1 + * but cannot be used before 23 (22.x.y possibly) (see 09a3d830a888). + */ +#if (__has_builtin(__builtin_counted_by_ref)) && \ + (!defined(__clang__) || (__clang_major__ >= 23)) +#define __flex_counter(_field) __builtin_counted_by_ref(_field) +#else +#define __flex_counter(_field) ((void *)NULL) +#endif + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h index 8834f1799e61..2913810923f1 100644 --- a/sys/compat/linuxkpi/common/include/linux/device.h +++ b/sys/compat/linuxkpi/common/include/linux/device.h @@ -267,6 +267,30 @@ show_class_attr_string(struct class *class, dev_dbg(dev, __VA_ARGS__); \ } while (0) +static inline int +dev_err_probe(const struct device *dev, int err, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + /* + * On Linux, they look at the error code to determine if the message + * should be logged (not logged if -ENOMEM) and at which log level. + */ + device_printf(dev->bsddev, fmt, args); + + va_end(args); + + return (err); +} + +#define dev_err_ptr_probe(dev, err, fmt, ...) \ + ERR_PTR(dev_err_probe((dev), (err), fmt, ##__VA_ARGS__) + +#define dev_err_cast_probe(dev, err, fmt, ...) \ + ERR_PTR(dev_err_probe((dev), PTR_ERR(err), fmt, ##__VA_ARGS__) + /* 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 *); @@ -701,6 +725,13 @@ devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp) return (dst); } +static inline void * +devm_kmemdup_array(struct device *dev, const void *src, size_t n, size_t len, + gfp_t gfp) +{ + return (devm_kmemdup(dev, src, size_mul(n, len), gfp)); +} + #define devm_kzalloc(_dev, _size, _gfp) \ devm_kmalloc((_dev), (_size), (_gfp) | __GFP_ZERO) diff --git a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h index 2d8e1196d3d3..5e5d40ef8339 100644 --- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h +++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h @@ -96,6 +96,8 @@ void *linux_dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag); void *linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag); +void linuxkpi_dmam_free_coherent(struct device *dev, size_t size, + void *addr, dma_addr_t dma_handle); 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); @@ -104,10 +106,10 @@ 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 direction, - unsigned long attrs __unused); + unsigned long attrs); void linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents __unused, enum dma_data_direction direction, - unsigned long attrs __unused); + unsigned long attrs); void linuxkpi_dma_sync(struct device *, dma_addr_t, size_t, bus_dmasync_op_t); static inline int @@ -181,6 +183,13 @@ dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, kmem_free(cpu_addr, size); } +static inline void +dmam_free_coherent(struct device *dev, size_t size, void *addr, + dma_addr_t dma_handle) +{ + linuxkpi_dmam_free_coherent(dev, size, addr, dma_handle); +} + 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 direction, unsigned long attrs) @@ -192,10 +201,10 @@ dma_map_page_attrs(struct device *dev, struct page *page, size_t offset, /* linux_dma_(un)map_sg_attrs does not support attrs yet */ #define dma_map_sg_attrs(dev, sgl, nents, dir, attrs) \ - linux_dma_map_sg_attrs(dev, sgl, nents, dir, 0) + linux_dma_map_sg_attrs(dev, sgl, nents, dir, attrs) #define dma_unmap_sg_attrs(dev, sg, nents, dir, attrs) \ - linux_dma_unmap_sg_attrs(dev, sg, nents, dir, 0) + linux_dma_unmap_sg_attrs(dev, sg, nents, dir, attrs) static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, @@ -352,10 +361,10 @@ dma_max_mapping_size(struct device *dev) } #define dma_map_single_attrs(dev, ptr, size, dir, attrs) \ - _dma_map_single_attrs(dev, ptr, size, dir, 0) + _dma_map_single_attrs(dev, ptr, size, dir, attrs) #define dma_unmap_single_attrs(dev, dma_addr, size, dir, attrs) \ - _dma_unmap_single_attrs(dev, dma_addr, size, dir, 0) + _dma_unmap_single_attrs(dev, dma_addr, size, dir, attrs) #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) diff --git a/sys/compat/linuxkpi/common/include/linux/eventfd.h b/sys/compat/linuxkpi/common/include/linux/eventfd.h new file mode 100644 index 000000000000..d167d4b7d189 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/eventfd.h @@ -0,0 +1,54 @@ +/*- + * 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_EVENTFD_H_ +#define _LINUXKPI_LINUX_EVENTFD_H_ + +#include <sys/eventfd.h> + +#include <linux/wait.h> +#include <linux/err.h> +#include <linux/percpu-defs.h> +#include <linux/percpu.h> +#include <linux/sched.h> + +/* + * Linux uses `struct eventfd_ctx`, but FreeBSD defines `struct eventfd`. Here, + * we define a synonym to the FreeBSD structure. This allows to keep Linux code + * unmodified. + */ +#define eventfd_ctx eventfd + +#define eventfd_ctx_fdget lkpi_eventfd_ctx_fdget +struct eventfd_ctx *lkpi_eventfd_ctx_fdget(int fd); + +#define eventfd_ctx_put lkpi_eventfd_ctx_put +void lkpi_eventfd_ctx_put(struct eventfd_ctx *ctx); + +#endif /* _LINUXKPI_LINUX_EVENTFD_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/file.h b/sys/compat/linuxkpi/common/include/linux/file.h index f6e988c2d88e..be12d5f1bccf 100644 --- a/sys/compat/linuxkpi/common/include/linux/file.h +++ b/sys/compat/linuxkpi/common/include/linux/file.h @@ -39,6 +39,11 @@ #include <linux/fs.h> #include <linux/slab.h> +#include <linux/compiler.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/cleanup.h> + struct linux_file; #undef file diff --git a/sys/compat/linuxkpi/common/include/linux/font.h b/sys/compat/linuxkpi/common/include/linux/font.h new file mode 100644 index 000000000000..45daa00b61f0 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/font.h @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025-2026 The FreeBSD Foundation + * Copyright (c) 2025-2026 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + */ + +#ifndef _LINUXKPI_LINUX_FONT_H_ +#define _LINUXKPI_LINUX_FONT_H_ + +#include <linux/types.h> + +struct font_desc { + const char *name; + const void *data; + int idx; + unsigned int width; + unsigned int height; + unsigned int charcount; + int pref; +}; + +static inline const struct font_desc * +get_default_font(int xres, int yres, unsigned long *font_w, + unsigned long *font_h) +{ + return (NULL); +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h index f1568ad6282d..749a9fd22d3d 100644 --- a/sys/compat/linuxkpi/common/include/linux/fs.h +++ b/sys/compat/linuxkpi/common/include/linux/fs.h @@ -133,8 +133,11 @@ do { \ typedef int (*filldir_t)(void *, const char *, int, off_t, u64, unsigned); +typedef unsigned int fop_flags_t; + struct file_operations { struct module *owner; + fop_flags_t fop_flags; /* Unused on FreeBSD. */ ssize_t (*read)(struct linux_file *, char __user *, size_t, off_t *); ssize_t (*write)(struct linux_file *, const char __user *, size_t, off_t *); unsigned int (*poll) (struct linux_file *, struct poll_table_struct *); @@ -182,6 +185,14 @@ struct file_operations { int (*setlease)(struct file *, long, struct file_lock **); #endif }; + +#define FOP_BUFFER_RASYNC (1 << 0) +#define FOP_BUFFER_WASYNC (1 << 1) +#define FOP_MMAP_SYNC (1 << 2) +#define FOP_DIO_PARALLEL_WRITE (1 << 3) +#define FOP_HUGE_PAGES (1 << 4) +#define FOP_UNSIGNED_OFFSET (1 << 5) + #define fops_get(fops) (fops) #define replace_fops(f, fops) ((f)->f_op = (fops)) @@ -364,27 +375,23 @@ 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; + void *read_pos = ((char *) orig) + *ppos; size_t buf_remain = buf_size - *ppos; + ssize_t num_read; - if (buf_remain < 0 || buf_remain > buf_size) - return -EINVAL; + if (*ppos >= buf_size || read_size == 0) + return (0); 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); + /* copy_to_user returns number of bytes NOT read */ + num_read = read_size - copy_to_user(dest, read_pos, read_size); + if (num_read == 0) + return -EFAULT; + *ppos += num_read; + + return (num_read); } MALLOC_DECLARE(M_LSATTR); @@ -415,11 +422,13 @@ int simple_attr_open(struct inode *inode, struct file *filp, 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_read(struct file *filp, char __user *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(struct file *filp, const char __user *buf, + size_t write_size, loff_t *ppos); -ssize_t simple_attr_write_signed(struct file *filp, const char *buf, +ssize_t simple_attr_write_signed(struct file *filp, const char __user *buf, size_t write_size, loff_t *ppos); #endif /* _LINUXKPI_LINUX_FS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/gfp.h b/sys/compat/linuxkpi/common/include/linux/gfp.h index 7a32e7862338..e8380e326eda 100644 --- a/sys/compat/linuxkpi/common/include/linux/gfp.h +++ b/sys/compat/linuxkpi/common/include/linux/gfp.h @@ -58,7 +58,8 @@ #define __GFP_WAIT M_WAITOK #define __GFP_DMA32 (1U << 24) /* LinuxKPI only */ #define __GFP_NORETRY (1U << 25) /* LinuxKPI only */ -#define __GFP_BITS_SHIFT 26 +#define __GFP_THISNODE (1U << 26) /* Unimplemented */ +#define __GFP_BITS_SHIFT 27 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1) #define __GFP_NOFAIL M_WAITOK @@ -80,6 +81,9 @@ CTASSERT((__GFP_DMA32 & GFP_NATIVE_MASK) == 0); CTASSERT((__GFP_BITS_MASK & GFP_NATIVE_MASK) == GFP_NATIVE_MASK); +#define __default_gfp(_discard, _arg_or_default, ...) _arg_or_default +#define default_gfp(...) __default_gfp(, ##__VA_ARGS__, GFP_KERNEL) + struct page_frag_cache { void *va; int pagecnt_bias; diff --git a/sys/compat/linuxkpi/common/include/linux/hardirq.h b/sys/compat/linuxkpi/common/include/linux/hardirq.h index f79451dd0d35..c6cbf1a34f14 100644 --- a/sys/compat/linuxkpi/common/include/linux/hardirq.h +++ b/sys/compat/linuxkpi/common/include/linux/hardirq.h @@ -31,6 +31,7 @@ #include <linux/types.h> #include <linux/lockdep.h> +#include <linux/preempt.h> #include <sys/param.h> #include <sys/bus.h> diff --git a/sys/compat/linuxkpi/common/include/linux/hex.h b/sys/compat/linuxkpi/common/include/linux/hex.h new file mode 100644 index 000000000000..7e9f499cfb1b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/hex.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022-2026 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_HEX_H_ +#define _LINUXKPI_LINUX_HEX_H_ + +#include <linux/types.h> +#include <linux/errno.h> + +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); +} + +#endif /* _LINUXKPI_LINUX_HEX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/highmem.h b/sys/compat/linuxkpi/common/include/linux/highmem.h index 58a9cdcdf60f..dc1c4fe2f299 100644 --- a/sys/compat/linuxkpi/common/include/linux/highmem.h +++ b/sys/compat/linuxkpi/common/include/linux/highmem.h @@ -45,6 +45,7 @@ #include <linux/mm.h> #include <linux/page.h> +#include <linux/hardirq.h> #define PageHighMem(p) (0) diff --git a/sys/compat/linuxkpi/common/include/linux/i2c.h b/sys/compat/linuxkpi/common/include/linux/i2c.h index f24d282586f6..a6a4ee85d584 100644 --- a/sys/compat/linuxkpi/common/include/linux/i2c.h +++ b/sys/compat/linuxkpi/common/include/linux/i2c.h @@ -31,7 +31,14 @@ #include <sys/errno.h> #include <sys/systm.h> +#include <linux/bits.h> +#include <linux/mod_devicetable.h> #include <linux/device.h> +#include <linux/sched.h> +#include <linux/mutex.h> +#include <linux/regulator/consumer.h> +#include <linux/irqdomain.h> +#include <linux/of.h> #define I2C_MAX_ADAPTER_NAME_LENGTH 32 diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h index 12160df43915..b8f29560f200 100644 --- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h +++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2025 The FreeBSD Foundation + * Copyright (c) 2020-2026 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -51,8 +51,16 @@ extern int linuxkpi_debug_80211; #define IMPROVE(fmt, ...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \ printf("%s:%d: XXX LKPI80211 IMPROVE " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) - -/* 9.4.2.55 Management MIC element (CMAC-256, GMAC-128, and GMAC-256). */ +/* 802.11-2024, 9.4.2.53 MME. */ +/* BIP-CMAC-128 */ +struct ieee80211_mmie { + uint8_t element_id; + uint8_t length; + uint16_t key_id; + uint8_t ipn[6]; + uint8_t mic[8]; +}; +/* BIP-CMAC-256, BIP-GMAC-128, BIP-GMAC-256 */ struct ieee80211_mmie_16 { uint8_t element_id; uint8_t length; @@ -92,8 +100,6 @@ struct ieee80211_mmie_16 { #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) @@ -108,7 +114,18 @@ struct ieee80211_mmie_16 { #define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100 enum ieee80211_rate_flags { - IEEE80211_RATE_SHORT_PREAMBLE = BIT(0), + IEEE80211_RATE_SHORT_PREAMBLE = BIT(0), /* 2.4Ghz, CCK */ + IEEE80211_RATE_SUPPORTS_5MHZ = BIT(1), + IEEE80211_RATE_SUPPORTS_10MHZ = BIT(2), + IEEE80211_RATE_ERP_G = BIT(3), + + /* + * According to documentation these are flags initialized internally. + * See lkpi_wiphy_band_annotate(). + */ + IEEE80211_RATE_MANDATORY_A = BIT(4), + IEEE80211_RATE_MANDATORY_G = BIT(5), + IEEE80211_RATE_MANDATORY_B = BIT(6), }; enum ieee80211_rate_control_changed_flags { @@ -200,6 +217,7 @@ enum ieee80211_min_mpdu_start_spacing { #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_FCTL_MOREDATA (IEEE80211_FC1_MORE_DATA << 8) #define IEEE80211_FTYPE_MGMT IEEE80211_FC0_TYPE_MGT #define IEEE80211_FTYPE_CTL IEEE80211_FC0_TYPE_CTL @@ -461,18 +479,6 @@ enum ieee80211_tx_control_flags { 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 @@ -614,6 +620,8 @@ struct ieee80211_mgmt { } u; } __packed __aligned(2); +#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) + struct ieee80211_cts { /* net80211::ieee80211_frame_cts */ __le16 frame_control; __le16 duration; diff --git a/sys/compat/linuxkpi/common/include/linux/instruction_pointer.h b/sys/compat/linuxkpi/common/include/linux/instruction_pointer.h new file mode 100644 index 000000000000..200a8c3f1d5e --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/instruction_pointer.h @@ -0,0 +1,15 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Neel Chauhan + * Copyright (c) 2026 The FreeBSD Foundation + */ + +#ifndef _LINUXKPI_LINUX_INSTRUCTION_POINTER_H_ +#define _LINUXKPI_LINUX_INSTRUCTION_POINTER_H_ + +#define _RET_IP_ __builtin_return_address(0) + +#define _THIS_IP_ ((unsigned long)0) /* TODO: _THIS_IP_ not implemented. */ + +#endif /* _LINUXKPI_LINUX_INSTRUCTION_POINTER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ioport.h b/sys/compat/linuxkpi/common/include/linux/ioport.h index 763af2de7c4f..68f28cec4ec4 100644 --- a/sys/compat/linuxkpi/common/include/linux/ioport.h +++ b/sys/compat/linuxkpi/common/include/linux/ioport.h @@ -41,6 +41,7 @@ struct resource { resource_size_t start; resource_size_t end; const char *name; + unsigned long flags; }; static inline resource_size_t diff --git a/sys/compat/linuxkpi/common/include/linux/kconfig.h b/sys/compat/linuxkpi/common/include/linux/kconfig.h index c1d186b56e1f..529d41991900 100644 --- a/sys/compat/linuxkpi/common/include/linux/kconfig.h +++ b/sys/compat/linuxkpi/common/include/linux/kconfig.h @@ -73,4 +73,39 @@ #define IS_REACHABLE(_x) (IS_BUILTIN(_x) || \ (IS_MODULE(_x) && IS_BUILTIN(MODULE))) +/* + * On Linux, the CONFIG_PGTABLE_LEVELS value is defined by the config/build + * system. Here, we take the per-architecture default value defined in + * `arch/$ARCH/Kconfig` files upstream. + */ +#if defined(__amd64__) + +#define CONFIG_PGTABLE_LEVELS 4 + +#elif defined(__aarch64__) + +#define CONFIG_PGTABLE_LEVELS 4 + +#elif defined(__i386__) + +#define CONFIG_PGTABLE_LEVELS 2 + +#elif defined(__powerpc__) + +#if defined(__powerpc64__) +#define CONFIG_PGTABLE_LEVELS 4 +#else +#define CONFIG_PGTABLE_LEVELS 2 +#endif + +#elif defined(__riscv) + +#if defined(__riscv_xlen) && __riscv_xlen == 64 +#define CONFIG_PGTABLE_LEVELS 5 +#else +#define CONFIG_PGTABLE_LEVELS 2 +#endif + +#endif + #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 988dd771254a..964b7078e7f5 100644 --- a/sys/compat/linuxkpi/common/include/linux/kdev_t.h +++ b/sys/compat/linuxkpi/common/include/linux/kdev_t.h @@ -31,6 +31,21 @@ #include <sys/types.h> +/* + * The encoding of major/minor on FreeBSD is complex to take into account the + * compatibility with 16-bit dev_t (see <sys/types.h>). It is not possible to + * use a simple shift and thus, we can't have a proper definition of + * `MINORBITS`. + * + * At the time this is added to linuxkpi, this is used by the DRM generic code + * as the upper limit to allocate an ID using an xarray. It is not used to + * decode a minor, therefore any arbitrary value here is fine in this context. + * + * On Linux, the value is set to 20. Because of the above, we reuse this value, + * even so it does not correspond to the actual minor encoding on FreeBSD. + */ +#define MINORBITS 20 + #define MAJOR(dev) major(dev) #define MINOR(dev) minor(dev) #define MKDEV(ma, mi) makedev(ma, mi) diff --git a/sys/compat/linuxkpi/common/include/linux/kernel.h b/sys/compat/linuxkpi/common/include/linux/kernel.h index 11a13cbd49b4..e3ac4a05612c 100644 --- a/sys/compat/linuxkpi/common/include/linux/kernel.h +++ b/sys/compat/linuxkpi/common/include/linux/kernel.h @@ -55,6 +55,8 @@ #include <linux/jiffies.h> #include <linux/log2.h> #include <linux/kconfig.h> +#include <linux/instruction_pointer.h> +#include <linux/hex.h> #include <asm/byteorder.h> #include <asm/cpufeature.h> @@ -267,8 +269,6 @@ extern int linuxkpi_debug; #define u64_to_user_ptr(val) ((void *)(uintptr_t)(val)) -#define _RET_IP_ __builtin_return_address(0) - #define offsetofend(t, m) \ (offsetof(t, m) + sizeof((((t *)0)->m))) @@ -306,37 +306,6 @@ linux_ratelimited(linux_ratelimit_t *rl) #define add_taint(x,y) do { \ } while (0) -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) { @@ -382,4 +351,37 @@ mac_pton(const char *macin, uint8_t *macout) #define DECLARE_FLEX_ARRAY(_t, _n) \ struct { struct { } __dummy_ ## _n; _t _n[0]; } +/* + * The following functions/macros are debug/diagnostics tools. They default to + * no-ops, except `might_sleep()` which uses `WITNESS_WARN()` on FreeBSD. + */ +static inline void +__might_resched(const char *file, int line, unsigned int offsets) +{ +} + +static inline void +__might_sleep(const char *file, int line) +{ +} + +static inline void +might_fault(void) +{ +} + +#define might_sleep() \ + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "might_sleep()") + +#define might_sleep_if(cond) do { \ + if (cond) { might_sleep(); } \ +} while (0) + +#define might_resched() do { } while (0) +#define cant_sleep() do { } while (0) +#define cant_migrate() do { } while (0) +#define sched_annotate_sleep() do { } while (0) +#define non_block_start() do { } while (0) +#define non_block_end() do { } while (0) + #endif /* _LINUXKPI_LINUX_KERNEL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kfifo.h b/sys/compat/linuxkpi/common/include/linux/kfifo.h index d2f570781661..b0d0c17f07e4 100644 --- a/sys/compat/linuxkpi/common/include/linux/kfifo.h +++ b/sys/compat/linuxkpi/common/include/linux/kfifo.h @@ -33,8 +33,26 @@ #include <linux/slab.h> #include <linux/gfp.h> -#define INIT_KFIFO(x) 0 -#define DECLARE_KFIFO(x, y, z) +/* + * INIT_KFIFO() is used to initialize the structure declared with + * DECLARE_KFIFO(). It doesn't work with DECLARE_KFIFO_PTR(). + */ +#define INIT_KFIFO(_kf) \ + ({ \ + (_kf).total = nitems((_kf).head); \ + (_kf).count = 0; \ + (_kf).first = 0; \ + (_kf).last = 0; \ + }) + +#define DECLARE_KFIFO(_name, _type, _size) \ + struct kfifo_ ## _name { \ + size_t total; \ + size_t count; \ + size_t first; \ + size_t last; \ + _type head[_size]; \ + } _name #define DECLARE_KFIFO_PTR(_name, _type) \ struct kfifo_ ## _name { \ @@ -71,7 +89,7 @@ (_kf)->head[(_kf)->last] = (_e); \ (_kf)->count++; \ (_kf)->last++; \ - if ((_kf)->last > (_kf)->total) \ + if ((_kf)->last >= (_kf)->total) \ (_kf)->last = 0; \ _rc = true; \ } \ @@ -89,7 +107,7 @@ *(_e) = (_kf)->head[(_kf)->first]; \ (_kf)->count--; \ (_kf)->first++; \ - if ((_kf)->first > (_kf)->total) \ + if ((_kf)->first >= (_kf)->total) \ (_kf)->first = 0; \ _rc = true; \ } \ diff --git a/sys/compat/linuxkpi/common/include/linux/kmsg_dump.h b/sys/compat/linuxkpi/common/include/linux/kmsg_dump.h new file mode 100644 index 000000000000..539981c54d1b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kmsg_dump.h @@ -0,0 +1,93 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025-2026 The FreeBSD Foundation + * Copyright (c) 2025-2026 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + */ + +#ifndef _LINUXKPI_LINUX_KMSG_DUMP_H_ +#define _LINUXKPI_LINUX_KMSG_DUMP_H_ + +#include <linux/errno.h> +#include <linux/list.h> + +#include <linux/kernel.h> /* For pr_debug() */ + +enum kmsg_dump_reason { + KMSG_DUMP_UNDEF, + KMSG_DUMP_PANIC, + KMSG_DUMP_OOPS, + KMSG_DUMP_EMERG, + KMSG_DUMP_SHUTDOWN, + KMSG_DUMP_MAX +}; + +struct kmsg_dump_iter { + uint64_t cur_seq; + uint64_t next_seq; +}; + +struct kmsg_dumper { + struct list_head list; + void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason); + enum kmsg_dump_reason max_reason; + bool registered; +}; + +static inline void +kmsg_dump(enum kmsg_dump_reason reason) +{ + pr_debug("TODO"); +} + +static inline bool +kmsg_dump_get_line(struct kmsg_dump_iter *iter, bool syslog, + const char *line, size_t size, size_t *len) +{ + pr_debug("TODO"); + + return (false); +} + +static inline bool +kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog, + char *buf, size_t size, size_t *len) +{ + pr_debug("TODO"); + + return (false); +} + +static inline void +kmsg_dump_rewind(struct kmsg_dump_iter *iter) +{ + pr_debug("TODO"); +} + +static inline int +kmsg_dump_register(struct kmsg_dumper *dumper) +{ + pr_debug("TODO"); + + return (-EINVAL); +} + +static inline int +kmsg_dump_unregister(struct kmsg_dumper *dumper) +{ + pr_debug("TODO"); + + return (-EINVAL); +} + +static inline const char * +kmsg_dump_reason_str(enum kmsg_dump_reason reason) +{ + pr_debug("TODO"); + + return ("Unknown"); +} +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/kstrtox.h b/sys/compat/linuxkpi/common/include/linux/kstrtox.h index 5da99de24197..05bf94dd375d 100644 --- a/sys/compat/linuxkpi/common/include/linux/kstrtox.h +++ b/sys/compat/linuxkpi/common/include/linux/kstrtox.h @@ -74,14 +74,17 @@ static inline int kstrtoul(const char *cp, unsigned int base, unsigned long *res) { char *end; + unsigned long temp; - *res = strtoul(cp, &end, base); + temp = strtoul(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') end++; if (*cp == 0 || *end != 0) return (-EINVAL); + + *res = temp; return (0); } @@ -89,14 +92,17 @@ static inline int kstrtol(const char *cp, unsigned int base, long *res) { char *end; + long temp; - *res = strtol(cp, &end, base); + temp = strtol(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') end++; if (*cp == 0 || *end != 0) return (-EINVAL); + + *res = temp; return (0); } @@ -106,7 +112,7 @@ kstrtoint(const char *cp, unsigned int base, int *res) char *end; long temp; - *res = temp = strtol(cp, &end, base); + temp = strtol(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') @@ -115,6 +121,8 @@ kstrtoint(const char *cp, unsigned int base, int *res) return (-EINVAL); if (temp != (int)temp) return (-ERANGE); + + *res = (int)temp; return (0); } @@ -124,7 +132,7 @@ kstrtouint(const char *cp, unsigned int base, unsigned int *res) char *end; unsigned long temp; - *res = temp = strtoul(cp, &end, base); + temp = strtoul(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') @@ -133,6 +141,8 @@ kstrtouint(const char *cp, unsigned int base, unsigned int *res) return (-EINVAL); if (temp != (unsigned int)temp) return (-ERANGE); + + *res = (unsigned int)temp; return (0); } @@ -142,7 +152,7 @@ kstrtou8(const char *cp, unsigned int base, uint8_t *res) char *end; unsigned long temp; - *res = temp = strtoul(cp, &end, base); + temp = strtoul(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') @@ -151,6 +161,8 @@ kstrtou8(const char *cp, unsigned int base, uint8_t *res) return (-EINVAL); if (temp != (uint8_t)temp) return (-ERANGE); + + *res = (uint8_t)temp; return (0); } @@ -160,7 +172,7 @@ kstrtou16(const char *cp, unsigned int base, uint16_t *res) char *end; unsigned long temp; - *res = temp = strtoul(cp, &end, base); + temp = strtoul(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') @@ -169,20 +181,20 @@ kstrtou16(const char *cp, unsigned int base, uint16_t *res) return (-EINVAL); if (temp != (uint16_t)temp) return (-ERANGE); + + *res = (uint16_t)temp; 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)); } @@ -190,14 +202,17 @@ static inline int kstrtos64(const char *cp, unsigned int base, int64_t *res) { char *end; + quad_t temp; - *res = strtoq(cp, &end, base); + temp = strtoq(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') end++; if (*cp == 0 || *end != 0) return (-EINVAL); + + *res = (int64_t)temp; return (0); } @@ -208,17 +223,20 @@ kstrtoll(const char *cp, unsigned int base, long long *res) } static inline int -kstrtou64(const char *cp, unsigned int base, u64 *res) +kstrtou64(const char *cp, unsigned int base, uint64_t *res) { char *end; + u_quad_t temp; - *res = strtouq(cp, &end, base); + temp = strtouq(cp, &end, base); /* skip newline character, if any */ if (*end == '\n') end++; if (*cp == 0 || *end != 0) return (-EINVAL); + + *res = (uint64_t)temp; return (0); } @@ -231,22 +249,16 @@ kstrtoull(const char *cp, unsigned int base, unsigned long long *res) static inline int kstrtobool(const char *s, bool *res) { - int len; - - if (s == NULL || (len = strlen(s)) == 0 || res == NULL) + if (s == NULL || *s == '\0') return (-EINVAL); - /* skip newline character, if any */ - if (s[len - 1] == '\n') - len--; - - if (len == 1 && strchr("yY1", s[0]) != NULL) + if (strchr("eEtTyY1", s[0]) != NULL) *res = true; - else if (len == 1 && strchr("nN0", s[0]) != NULL) + else if (strchr("dDfFnN0", s[0]) != NULL) *res = false; - else if (strncasecmp("on", s, len) == 0) + else if (strncasecmp("on", s, 2) == 0) *res = true; - else if (strncasecmp("off", s, len) == 0) + else if (strncasecmp("of", s, 2) == 0) *res = false; else return (-EINVAL); @@ -302,7 +314,6 @@ 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)); } diff --git a/sys/compat/linuxkpi/common/include/linux/linux_logo.h b/sys/compat/linuxkpi/common/include/linux/linux_logo.h new file mode 100644 index 000000000000..cb60ba50f6a5 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/linux_logo.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 The FreeBSD Foundation + */ + +#ifndef _LINUXKPI_LINUX_LINUX_LOGO_H_ +#define _LINUXKPI_LINUX_LINUX_LOGO_H_ + +struct linux_logo { + int type; + unsigned int width; + unsigned int height; + unsigned int clutsize; + const unsigned char *clut; + const unsigned char *data; +}; + +#endif /* _LINUXKPI_LINUX_LINUX_LOGO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/memcontrol.h b/sys/compat/linuxkpi/common/include/linux/memcontrol.h new file mode 100644 index 000000000000..57fadf9af60f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/memcontrol.h @@ -0,0 +1,43 @@ +/*- + * 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_LINUX_MEMCONTROL_H_ +#define _LINUXKPI_LINUX_MEMCONTROL_H_ + +#include <linux/cgroup.h> +#include <linux/hardirq.h> +#include <linux/jump_label.h> +#include <linux/kernel.h> +#include <linux/eventfd.h> +#include <linux/mm.h> +#include <linux/page-flags.h> +#include <linux/shrinker.h> + +#endif /* defined(_LINUXKPI_LINUX_MEMCONTROL_H_) */ diff --git a/sys/compat/linuxkpi/common/include/linux/mfd/core.h b/sys/compat/linuxkpi/common/include/linux/mfd/core.h new file mode 100644 index 000000000000..1a69a3803b5d --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mfd/core.h @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 The FreeBSD Foundation + */ + +#ifndef _LINUXKPI_LINUX_MFD_CORE_H_ +#define _LINUXKPI_LINUX_MFD_CORE_H_ + +#include <linux/platform_device.h> + +/* + * <linux/ioport.h> is not included by Linux, but we need it here to get the + * definition of `struct resource`. + * + * At least the amdgpu DRM driver (amdgpu_isp.c at the time of this writing) + * needs the structure without including this header: it relies on an implicit + * include of <linux/ioport.h> from <linux/pci.h>, which we can't have due to + * conflict with the FreeBSD native `struct resource`. + */ +#include <linux/ioport.h> + +#include <linux/kernel.h> /* pr_debug */ + +struct resource; +struct mfd_cell { + const char *name; + void *platform_data; + size_t pdata_size; + int num_resources; + const struct resource *resources; +}; + +static inline int +mfd_add_hotplug_devices(struct device *parent, + const struct mfd_cell *cells, int n_devs) +{ + pr_debug("%s: TODO\n", __func__); + + return (0); +} + +static inline void +mfd_remove_devices(struct device *parent) +{ + pr_debug("%s: TODO\n", __func__); +} + +#endif /* _LINUXKPI_LINUX_MFD_CORE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/minmax.h b/sys/compat/linuxkpi/common/include/linux/minmax.h index d48958f0899f..5040d7f9141e 100644 --- a/sys/compat/linuxkpi/common/include/linux/minmax.h +++ b/sys/compat/linuxkpi/common/include/linux/minmax.h @@ -60,6 +60,9 @@ type __max2 = (y); \ __max1 > __max2 ? __max1 : __max2; }) +#define MIN_T(type, x, y) MIN((type)(x), (type)(y)) +#define MAX_T(type, x, y) MAX((type)(x), (type)(y)) + #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) @@ -71,4 +74,7 @@ b = _swap_tmp; \ } while (0) +/* XXX would have to make sure both are unsigned. */ +#define umin(x, y) MIN(x, y) + #endif /* _LINUXKPI_LINUX_MINMAX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h index 87bd6ec24bce..b345b98325e1 100644 --- a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h +++ b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h @@ -30,6 +30,7 @@ #define __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ #include <linux/types.h> +#include <linux/uuid.h> enum dmi_field { DMI_NONE, @@ -80,4 +81,10 @@ struct dmi_system_id { #define ACPI_ID_LEN 16 +/* ----------------------------------------------------------------------------- + * USB + */ +/* struct usb_device_id is defined in sys/dev/usb/usbdi.h. */ +/* MODULE_DEVICE_TABLE_BUS_usb we have in usb.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 079dacf8df6c..fbe57cbbed82 100644 --- a/sys/compat/linuxkpi/common/include/linux/module.h +++ b/sys/compat/linuxkpi/common/include/linux/module.h @@ -53,6 +53,24 @@ #define MODULE_SUPPORTED_DEVICE(name) #define MODULE_IMPORT_NS(_name) +/* 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) + /* * THIS_MODULE is used to differentiate modules on Linux. We currently * completely stub out any Linux struct module usage, but THIS_MODULE is still diff --git a/sys/compat/linuxkpi/common/include/linux/netdevice.h b/sys/compat/linuxkpi/common/include/linux/netdevice.h index cf27753bcb80..dfed5fbd61b4 100644 --- a/sys/compat/linuxkpi/common/include/linux/netdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/netdevice.h @@ -160,6 +160,30 @@ struct net_device { #define SET_NETDEV_DEV(_ndev, _dev) (_ndev)->dev.parent = _dev; +enum net_device_path_type { + DEV_PATH_MTK_WDMA, +}; + +struct net_device_path { + enum net_device_path_type type; + const struct net_device *dev; + /* We assume there's a struct per type. */ + union { + struct { + uint16_t wcid; + uint8_t wdma_idx; + uint8_t queue; + uint8_t bss; + uint8_t amsdu; + } mtk_wdma; + }; +}; + +struct net_device_path_ctx { + const struct net_device *dev; +}; + + /* -------------------------------------------------------------------------- */ /* According to linux::ipoib_main.c. */ struct netdev_notifier_info { diff --git a/sys/compat/linuxkpi/common/include/linux/notifier.h b/sys/compat/linuxkpi/common/include/linux/notifier.h index 9302a1ce4606..4fe43255c648 100644 --- a/sys/compat/linuxkpi/common/include/linux/notifier.h +++ b/sys/compat/linuxkpi/common/include/linux/notifier.h @@ -32,6 +32,11 @@ #include <sys/types.h> #include <sys/eventhandler.h> +#include <linux/errno.h> +#include <linux/mutex.h> +#include <linux/rwsem.h> +#include <linux/srcu.h> + #define NOTIFY_DONE 0 #define NOTIFY_OK 0x0001 #define NOTIFY_STOP_MASK 0x8000 diff --git a/sys/compat/linuxkpi/common/include/linux/overflow.h b/sys/compat/linuxkpi/common/include/linux/overflow.h index e811037b8ecc..4326f05e6d07 100644 --- a/sys/compat/linuxkpi/common/include/linux/overflow.h +++ b/sys/compat/linuxkpi/common/include/linux/overflow.h @@ -4,9 +4,7 @@ #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 @@ -38,19 +36,13 @@ #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) +static __always_inline bool __must_check __must_check_overflow(bool overflow) { return unlikely(overflow); } @@ -203,9 +195,9 @@ static inline bool __must_check __must_check_overflow(bool overflow) typeof(d) _d = d; \ unsigned long long _a_full = _a; \ unsigned int _to_shift = \ - is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \ + _s >= 0 && _s < 8 * sizeof(*d) ? _s : 0; \ *_d = (_a_full << _to_shift); \ - (_to_shift != _s || is_negative(*_d) || is_negative(_a) || \ + (_to_shift != _s || *_d < 0 || _a < 0 || \ (*_d >> _to_shift) != _a); \ })) @@ -241,6 +233,76 @@ static inline bool __must_check __must_check_overflow(bool overflow) __overflows_type(n, T)) /** + * range_overflows() - Check if a range is out of bounds + * @start: Start of the range. + * @size: Size of the range. + * @max: Exclusive upper boundary. + * + * A strict check to determine if the range [@start, @start + @size) is + * invalid with respect to the allowable range [0, @max). Any range + * starting at or beyond @max is considered an overflow, even if @size is 0. + * + * Returns: true if the range is out of bounds. + */ +#define range_overflows(start, size, max) ({ \ + typeof(start) start__ = (start); \ + typeof(size) size__ = (size); \ + typeof(max) max__ = (max); \ + (void)(&start__ == &size__); \ + (void)(&start__ == &max__); \ + start__ >= max__ || size__ > max__ - start__; \ +}) + +/** + * range_overflows_t() - Check if a range is out of bounds + * @type: Data type to use. + * @start: Start of the range. + * @size: Size of the range. + * @max: Exclusive upper boundary. + * + * Same as range_overflows() but forcing the parameters to @type. + * + * Returns: true if the range is out of bounds. + */ +#define range_overflows_t(type, start, size, max) \ + range_overflows((type)(start), (type)(size), (type)(max)) + +/** + * range_end_overflows() - Check if a range's endpoint is out of bounds + * @start: Start of the range. + * @size: Size of the range. + * @max: Exclusive upper boundary. + * + * Checks only if the endpoint of a range (@start + @size) exceeds @max. + * Unlike range_overflows(), a zero-sized range at the boundary (@start == @max) + * is not considered an overflow. Useful for iterator-style checks. + * + * Returns: true if the endpoint exceeds the boundary. + */ +#define range_end_overflows(start, size, max) ({ \ + typeof(start) start__ = (start); \ + typeof(size) size__ = (size); \ + typeof(max) max__ = (max); \ + (void)(&start__ == &size__); \ + (void)(&start__ == &max__); \ + start__ > max__ || size__ > max__ - start__; \ +}) + +/** + * range_end_overflows_t() - Check if a range's endpoint is out of bounds + * @type: Data type to use. + * @start: Start of the range. + * @size: Size of the range. + * @max: Exclusive upper boundary. + * + * Same as range_end_overflows() but forcing the parameters to @type. + * + * Returns: true if the endpoint exceeds the boundary. + */ +#define range_end_overflows_t(type, start, size, max) \ + range_end_overflows((type)(start), (type)(size), (type)(max)) + +/** * castable_to_type - like __same_type(), but also allows for casted literals * * @n: variable or constant value @@ -265,7 +327,7 @@ static inline bool __must_check __must_check_overflow(bool overflow) * 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) +static __always_inline size_t __must_check size_mul(size_t factor1, size_t factor2) { size_t bytes; @@ -284,7 +346,7 @@ static inline size_t __must_check size_mul(size_t factor1, size_t factor2) * 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) +static __always_inline size_t __must_check size_add(size_t addend1, size_t addend2) { size_t bytes; @@ -305,7 +367,7 @@ static inline size_t __must_check size_add(size_t addend1, size_t addend2) * 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) +static __always_inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) { size_t bytes; @@ -391,6 +453,18 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) struct_size((type *)NULL, member, count) /** + * struct_offset() - Calculate the offset of a member within a struct + * @p: Pointer to the struct + * @member: Name of the member to get the offset of + * + * Calculates the offset of a particular @member of the structure pointed + * to by @p. + * + * Return: number of bytes to the location of @member. + */ +#define struct_offset(p, member) (offsetof(typeof(*(p)), member)) + +/** * __DEFINE_FLEX() - helper macro for DEFINE_FLEX() family. * Enables caller macro to pass arbitrary trailing expressions * @@ -472,4 +546,46 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) (__member_size((name)->array) / sizeof(*(name)->array) + \ __must_be_array((name)->array)) +/** + * typeof_flex_counter() - Return the type of the counter variable of a given + * flexible array member annotated by __counted_by(). + * @FAM: Instance of flexible array member within a given struct. + * + * Returns: "size_t" if no annotation exists. + */ +#define typeof_flex_counter(FAM) \ + typeof(_Generic(__flex_counter(FAM), \ + void *: (size_t)0, \ + default: *__flex_counter(FAM))) + +/** + * overflows_flex_counter_type() - Check if the counter associated with the + * given flexible array member can represent + * a value. + * @TYPE: Type of the struct that contains the @FAM. + * @FAM: Member name of the FAM within @TYPE. + * @COUNT: Value to check against the __counted_by annotated @FAM's counter. + * + * Returns: true if @COUNT can be represented in the @FAM's counter. When + * @FAM is not annotated with __counted_by(), always returns true. + */ +#define overflows_flex_counter_type(TYPE, FAM, COUNT) \ + (overflows_type(COUNT, typeof_flex_counter(((TYPE *)NULL)->FAM))) + +/** + * __set_flex_counter() - Set the counter associated with the given flexible + * array member that has been annoated by __counted_by(). + * @FAM: Instance of flexible array member within a given struct. + * @COUNT: Value to store to the __counted_by annotated @FAM_PTR's counter. + * + * This is a no-op if no annotation exists. Count needs to be checked with + * overflows_flex_counter_type() before using this function. + */ +#define __set_flex_counter(FAM, COUNT) \ +({ \ + *_Generic(__flex_counter(FAM), \ + void *: &(size_t){ 0 }, \ + default: __flex_counter(FAM)) = (COUNT); \ +}) + #endif /* _LINUXKPI_LINUX_OVERFLOW_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index 06336bf963d6..ba68a9ee0dc3 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -60,6 +60,17 @@ #include <linux/pci_ids.h> #include <linux/pm.h> +/* + * <linux/ioport.h> should be included here, like Linux, but we can't have that + * because Linux `struct resource` definition would conflict with FreeBSD + * native definition. + * + * At least the amdgpu DRM driver (amdgpu_isp.c at the time of this writing) + * relies on this indirect include to get the definition of Linux `struct + * resource`. As a workaround, we include <linux/ioport.h> from + * <linux/mfd/core.h>. + */ + #include <linux/kernel.h> /* pr_debug */ struct pci_device_id { @@ -76,24 +87,6 @@ struct pci_device_id { 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 #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) @@ -253,6 +246,20 @@ extern const char *pci_power_names[6]; #define PCI_IRQ_LEGACY PCI_IRQ_INTX #endif +/* + * Linux PCI code uses `PCI_SET_ERROR_RESPONSE()` to indicate to the caller of + * a `pci_read_*()` function that the read failed. An example of failure is + * whether the device was disconnected. It is a bit weird because Linux + * `pci_read_*()` can return an error value, as the read value is stored in a + * integer passed by pointer. + * + * We don't set PCI_ERROR_RESPONSE anywhere as of this commit, but the DRM + * drivers started to use `PCI_POSSIBLE_ERROR()`. + */ +#define PCI_ERROR_RESPONSE (~0ULL) +#define PCI_SET_ERROR_RESPONSE(val) (*(val) = ((typeof(*(val))) PCI_ERROR_RESPONSE)) +#define PCI_POSSIBLE_ERROR(val) ((val) == ((typeof(val)) PCI_ERROR_RESPONSE)) + struct pci_dev; struct pci_driver { @@ -1122,19 +1129,28 @@ pci_num_vf(struct pci_dev *dev) static inline enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev) { + struct pci_dev *pbus; device_t root; uint32_t lnkcap, lnkcap2; int error, pos; - root = device_get_parent(dev->dev.bsddev); - if (root == NULL) - return (PCI_SPEED_UNKNOWN); - root = device_get_parent(root); - if (root == NULL) - return (PCI_SPEED_UNKNOWN); - root = device_get_parent(root); - if (root == NULL) - return (PCI_SPEED_UNKNOWN); + /* + * We should always be called on a PCI device. + * The only current consumer I could find was amdgpu which either + * calls us directly on a pdev(drmn?) or with the result of + * pci_upstream_bridge(). + * + * Treat "drmn" as special again as it is not a PCI device. + */ + if (dev->pdrv != NULL && dev->pdrv->isdrm) { + pbus = pci_upstream_bridge(dev); + if (pbus == NULL) + return (PCI_SPEED_UNKNOWN); + } else + pbus = dev; + + /* "root" may be misleading as it may not be that. */ + root = pbus->dev.bsddev; if (pci_get_vendor(root) == PCI_VENDOR_ID_VIA || pci_get_vendor(root) == PCI_VENDOR_ID_SERVERWORKS) diff --git a/sys/compat/linuxkpi/common/include/linux/platform_data/brcmfmac.h b/sys/compat/linuxkpi/common/include/linux/platform_data/brcmfmac.h new file mode 100644 index 000000000000..ec99b7b73d1d --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/platform_data/brcmfmac.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016 Broadcom Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LINUX_BRCMFMAC_PLATFORM_H +#define _LINUX_BRCMFMAC_PLATFORM_H + + +#define BRCMFMAC_PDATA_NAME "brcmfmac" + +#define BRCMFMAC_COUNTRY_BUF_SZ 4 + + +/* + * Platform specific driver functions and data. Through the platform specific + * device data functions and data can be provided to help the brcmfmac driver to + * operate with the device in combination with the used platform. + */ + + +/** + * Note: the brcmfmac can be loaded as module or be statically built-in into + * the kernel. If built-in then do note that it uses module_init (and + * module_exit) routines which equal device_initcall. So if you intend to + * create a module with the platform specific data for the brcmfmac and have + * it built-in to the kernel then use a higher initcall then device_initcall + * (see init.h). If this is not done then brcmfmac will load without problems + * but will not pickup the platform data. + * + * When the driver does not "detect" platform driver data then it will continue + * without reporting anything and just assume there is no data needed. Which is + * probably true for most platforms. + */ + +/** + * enum brcmf_bus_type - Bus type identifier. Currently SDIO, USB and PCIE are + * supported. + */ +enum brcmf_bus_type { + BRCMF_BUSTYPE_SDIO, + BRCMF_BUSTYPE_USB, + BRCMF_BUSTYPE_PCIE +}; + + +/** + * struct brcmfmac_sdio_pd - SDIO Device specific platform data. + * + * @txglomsz: SDIO txglom size. Use 0 if default of driver is to be + * used. + * @drive_strength: is the preferred drive_strength to be used for the SDIO + * pins. If 0 then a default value will be used. This is + * the target drive strength, the exact drive strength + * which will be used depends on the capabilities of the + * device. + * @oob_irq_supported: does the board have support for OOB interrupts. SDIO + * in-band interrupts are relatively slow and for having + * less overhead on interrupt processing an out of band + * interrupt can be used. If the HW supports this then + * enable this by setting this field to true and configure + * the oob related fields. + * @oob_irq_nr, + * @oob_irq_flags: the OOB interrupt information. The values are used for + * registering the irq using request_irq function. + * @broken_sg_support: flag for broken sg list support of SDIO host controller. + * Set this to true if the SDIO host controller has higher + * align requirement than 32 bytes for each scatterlist + * item. + * @sd_head_align: alignment requirement for start of data buffer. + * @sd_sgentry_align: length alignment requirement for each sg entry. + * @reset: This function can get called if the device communication + * broke down. This functionality is particularly useful in + * case of SDIO type devices. It is possible to reset a + * dongle via sdio data interface, but it requires that + * this is fully functional. This function is chip/module + * specific and this function should return only after the + * complete reset has completed. + */ +struct brcmfmac_sdio_pd { + int txglomsz; + unsigned int drive_strength; + bool oob_irq_supported; + unsigned int oob_irq_nr; + unsigned long oob_irq_flags; + bool broken_sg_support; + unsigned short sd_head_align; + unsigned short sd_sgentry_align; + void (*reset)(void); +}; + +/** + * struct brcmfmac_pd_cc_entry - Struct for translating user space country code + * (iso3166) to firmware country code and + * revision. + * + * @iso3166: iso3166 alpha 2 country code string. + * @cc: firmware country code string. + * @rev: firmware country code revision. + */ +struct brcmfmac_pd_cc_entry { + char iso3166[BRCMFMAC_COUNTRY_BUF_SZ]; + char cc[BRCMFMAC_COUNTRY_BUF_SZ]; + s32 rev; +}; + +/** + * struct brcmfmac_pd_cc - Struct for translating country codes as set by user + * space to a country code and rev which can be used by + * firmware. + * + * @table_size: number of entries in table (> 0) + * @table: array of 1 or more elements with translation information. + */ +struct brcmfmac_pd_cc { + int table_size; + struct brcmfmac_pd_cc_entry table[]; +}; + +/** + * struct brcmfmac_pd_device - Device specific platform data. (id/rev/bus_type) + * is the unique identifier of the device. + * + * @id: ID of the device for which this data is. In case of SDIO + * or PCIE this is the chipid as identified by chip.c In + * case of USB this is the chipid as identified by the + * device query. + * @rev: chip revision, see id. + * @bus_type: The type of bus. Some chipid/rev exist for different bus + * types. Each bus type has its own set of settings. + * @feature_disable: Bitmask of features to disable (override), See feature.c + * in brcmfmac for details. + * @country_codes: If available, pointer to struct for translating country + * codes. + * @bus: Bus specific (union) device settings. Currently only + * SDIO. + */ +struct brcmfmac_pd_device { + unsigned int id; + unsigned int rev; + enum brcmf_bus_type bus_type; + unsigned int feature_disable; + struct brcmfmac_pd_cc *country_codes; + union { + struct brcmfmac_sdio_pd sdio; + } bus; +}; + +/** + * struct brcmfmac_platform_data - BRCMFMAC specific platform data. + * + * @power_on: This function is called by the brcmfmac driver when the module + * gets loaded. This can be particularly useful for low power + * devices. The platform spcific routine may for example decide to + * power up the complete device. If there is no use-case for this + * function then provide NULL. + * @power_off: This function is called by the brcmfmac when the module gets + * unloaded. At this point the devices can be powered down or + * otherwise be reset. So if an actual power_off is not supported + * but reset is supported by the devices then reset the devices + * when this function gets called. This can be particularly useful + * for low power devices. If there is no use-case for this + * function then provide NULL. + */ +struct brcmfmac_platform_data { + void (*power_on)(void); + void (*power_off)(void); + char *fw_alternative_path; + int device_count; + struct brcmfmac_pd_device devices[]; +}; + + +#endif /* _LINUX_BRCMFMAC_PLATFORM_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/printk.h b/sys/compat/linuxkpi/common/include/linux/printk.h index d2d197682782..066ec900f04e 100644 --- a/sys/compat/linuxkpi/common/include/linux/printk.h +++ b/sys/compat/linuxkpi/common/include/linux/printk.h @@ -48,7 +48,13 @@ 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); + const void *, size_t, const bool, const bool); + +#define hex_dump_to_buffer(buf, len, rowsize, groupsize, linebuf, linebuflen, ascii) \ + lkpi_hex_dump_to_buffer((buf), (len), (rowsize), (groupsize), (linebuf), (linebuflen), (ascii)) + +int lkpi_hex_dump_to_buffer(const void *buf, size_t len, int rowsize, + int groupsize, char *linebuf, size_t linebuflen, bool ascii); static inline void print_hex_dump(const char *level, const char *prefix_str, @@ -56,7 +62,7 @@ print_hex_dump(const char *level, const char *prefix_str, const void *buf, size_t len, const bool ascii) { lkpi_hex_dump(__lkpi_hexdump_printf, NULL, level, prefix_str, prefix_type, - rowsize, groupsize, buf, len, ascii); + rowsize, groupsize, buf, len, ascii, true); } static inline void diff --git a/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h b/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h index aad46cc25b1b..6491cbeab7e2 100644 --- a/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h +++ b/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h @@ -49,6 +49,7 @@ struct ptp_clock_info { 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 *); + int (*settime64)(struct ptp_clock_info *, const struct timespec *); }; static inline struct ptp_clock * diff --git a/sys/compat/linuxkpi/common/include/linux/radix-tree.h b/sys/compat/linuxkpi/common/include/linux/radix-tree.h index 1019697303db..7182f4a9e407 100644 --- a/sys/compat/linuxkpi/common/include/linux/radix-tree.h +++ b/sys/compat/linuxkpi/common/include/linux/radix-tree.h @@ -38,12 +38,19 @@ #define RADIX_TREE_MAX_HEIGHT \ howmany(sizeof(long) * NBBY, RADIX_TREE_MAP_SHIFT) +#define RADIX_TREE_MAX_TAGS 3 +#define RADIX_TREE_TAG_LONGS RADIX_TREE_MAP_SIZE + #define RADIX_TREE_ENTRY_MASK 3UL #define RADIX_TREE_EXCEPTIONAL_ENTRY 2UL #define RADIX_TREE_EXCEPTIONAL_SHIFT 2 +#define RADIX_TREE_ITER_TAG_MASK 0x0f +#define RADIX_TREE_ITER_TAGGED 0x10 + struct radix_tree_node { void *slots[RADIX_TREE_MAP_SIZE]; + unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS]; int count; }; @@ -51,6 +58,8 @@ struct radix_tree_root { struct radix_tree_node *rnode; gfp_t gfp_mask; int height; + /* Linux stores root tags inside `gfp_mask`. */ + unsigned long tags[RADIX_TREE_MAX_TAGS]; }; struct radix_tree_iter { @@ -64,9 +73,22 @@ struct radix_tree_iter { #define RADIX_TREE(name, mask) \ struct radix_tree_root name = RADIX_TREE_INIT(mask) -#define radix_tree_for_each_slot(slot, root, iter, start) \ - for ((iter)->index = (start); \ - radix_tree_iter_find(root, iter, &(slot)); (iter)->index++) +#define radix_tree_for_each_slot(slot, root, iter, start) \ + for ((iter)->index = (start); \ + radix_tree_iter_find(root, iter, &(slot), 0); \ + (iter)->index++) + +#define radix_tree_for_each_slot_tagged(slot, root, iter, start, tag) \ + for ((iter)->index = (start); \ + radix_tree_iter_find(root, iter, &(slot), \ + RADIX_TREE_ITER_TAGGED | tag); \ + (iter)->index++) + +static inline void * +radix_tree_deref_slot(void **slot) +{ + return (*slot); +} static inline int radix_tree_exception(void *arg) @@ -78,7 +100,12 @@ void *radix_tree_lookup(const struct radix_tree_root *, unsigned long); void *radix_tree_delete(struct radix_tree_root *, unsigned long); int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); int radix_tree_store(struct radix_tree_root *, unsigned long, void **); -bool radix_tree_iter_find(const struct radix_tree_root *, struct radix_tree_iter *, void ***); +bool radix_tree_iter_find(const struct radix_tree_root *, struct radix_tree_iter *, void ***, int); void radix_tree_iter_delete(struct radix_tree_root *, struct radix_tree_iter *, void **); +void *radix_tree_tag_set(struct radix_tree_root *root, unsigned long index, unsigned int tag); +void *radix_tree_tag_clear(struct radix_tree_root *root, unsigned long index, unsigned int tag); +int radix_tree_tagged(const struct radix_tree_root *root, unsigned int tag); +unsigned int radix_tree_gang_lookup(const struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items); +unsigned int radix_tree_gang_lookup_tag(const struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items, unsigned int tag); #endif /* _LINUXKPI_LINUX_RADIX_TREE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ratelimit.h b/sys/compat/linuxkpi/common/include/linux/ratelimit.h index 9585b4b994d7..fdef57c7882d 100644 --- a/sys/compat/linuxkpi/common/include/linux/ratelimit.h +++ b/sys/compat/linuxkpi/common/include/linux/ratelimit.h @@ -14,4 +14,11 @@ struct ratelimit_state { #define ratelimit_state_init(x, y, z) #define ratelimit_set_flags(x, y) +#define WARN_RATELIMIT(condition, ...) ({ \ + bool __ret_warn_on = (condition); \ + if (unlikely(__ret_warn_on)) \ + pr_warn_ratelimited(__VA_ARGS__); \ + unlikely(__ret_warn_on); \ +}) + #endif diff --git a/sys/compat/linuxkpi/common/include/linux/regulator/consumer.h b/sys/compat/linuxkpi/common/include/linux/regulator/consumer.h new file mode 100644 index 000000000000..d6c23575bc83 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/regulator/consumer.h @@ -0,0 +1,17 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025-2026 The FreeBSD Foundation + * Copyright (c) 2025-2026 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + */ + +#ifndef _LINUXKPI_LINUX_REGULATOR_CONSUMER_H_ +#define _LINUXKPI_LINUX_REGULATOR_CONSUMER_H_ + +#include <linux/err.h> +#include <linux/suspend.h> + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/seq_buf.h b/sys/compat/linuxkpi/common/include/linux/seq_buf.h new file mode 100644 index 000000000000..d6246a40e6f7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/seq_buf.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025-2026 The FreeBSD Foundation + * Copyright (c) 2025-2026 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_SEQ_BUF_H_ +#define _LINUXKPI_LINUX_SEQ_BUF_H_ + +#include <linux/bug.h> +#include <linux/minmax.h> +#include <linux/seq_file.h> +#include <linux/types.h> + +struct seq_buf { + char *buffer; + size_t size; + size_t len; +}; + +#define DECLARE_SEQ_BUF(NAME, SIZE) \ + struct seq_buf NAME = { \ + .buffer = (char[SIZE]) { 0 }, \ + .size = SIZE, \ + } + +static inline void +seq_buf_clear(struct seq_buf *s) +{ + s->len = 0; + if (s->size > 0) + s->buffer[0] = '\0'; +} + +static inline void +seq_buf_set_overflow(struct seq_buf *s) +{ + s->len = s->size + 1; +} + +static inline bool +seq_buf_has_overflowed(struct seq_buf *s) +{ + return (s->len > s->size); +} + +static inline bool +seq_buf_buffer_left(struct seq_buf *s) +{ + if (seq_buf_has_overflowed(s)) + return (0); + + return (s->size - s->len); +} + +#define seq_buf_init(s, buf, size) linuxkpi_seq_buf_init((s), (buf), (size)) +void linuxkpi_seq_buf_init(struct seq_buf *s, char *buf, unsigned int size); + +#define seq_buf_printf(s, f, ...) linuxkpi_seq_buf_printf((s), (f), __VA_ARGS__) +int linuxkpi_seq_buf_printf(struct seq_buf *s, const char *fmt, ...) \ + __printflike(2, 3); + +#define seq_buf_vprintf(s, f, a) linuxkpi_seq_buf_vprintf((s), (f), (a)) +int linuxkpi_seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args); + +#define seq_buf_str(s) linuxkpi_seq_buf_str((s)) +const char * linuxkpi_seq_buf_str(struct seq_buf *s); + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/seq_file.h b/sys/compat/linuxkpi/common/include/linux/seq_file.h index 47da16ab8688..786c09bd6a20 100644 --- a/sys/compat/linuxkpi/common/include/linux/seq_file.h +++ b/sys/compat/linuxkpi/common/include/linux/seq_file.h @@ -85,7 +85,7 @@ struct seq_operations { int (*show) (struct seq_file *m, void *v); }; -ssize_t seq_read(struct linux_file *, char *, size_t, off_t *); +ssize_t seq_read(struct linux_file *, char __user *, 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); @@ -115,7 +115,7 @@ 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); + rowsize, groupsize, buf, len, ascii, true); } #define file linux_file diff --git a/sys/compat/linuxkpi/common/include/linux/siphash.h b/sys/compat/linuxkpi/common/include/linux/siphash.h new file mode 100644 index 000000000000..9153e77382e1 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/siphash.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* Copyright (C) 2016-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + * + * SipHash: a fast short-input PRF + * https://131002.net/siphash/ + * + * This implementation is specifically for SipHash2-4 for a secure PRF + * and HalfSipHash1-3/SipHash1-3 for an insecure PRF only suitable for + * hashtables. + */ + +#ifndef _LINUX_SIPHASH_H +#define _LINUX_SIPHASH_H + +#include <linux/types.h> +#include <linux/kernel.h> + +#define SIPHASH_ALIGNMENT __alignof__(u64) +typedef struct { + u64 key[2]; +} siphash_key_t; + +#define siphash_aligned_key_t siphash_key_t __aligned(16) + +static inline bool siphash_key_is_zero(const siphash_key_t *key) +{ + return !(key->key[0] | key->key[1]); +} + +u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key); +u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key); + +u64 siphash_1u64(const u64 a, const siphash_key_t *key); +u64 siphash_2u64(const u64 a, const u64 b, const siphash_key_t *key); +u64 siphash_3u64(const u64 a, const u64 b, const u64 c, + const siphash_key_t *key); +u64 siphash_4u64(const u64 a, const u64 b, const u64 c, const u64 d, + const siphash_key_t *key); +u64 siphash_1u32(const u32 a, const siphash_key_t *key); +u64 siphash_3u32(const u32 a, const u32 b, const u32 c, + const siphash_key_t *key); + +static inline u64 siphash_2u32(const u32 a, const u32 b, + const siphash_key_t *key) +{ + return siphash_1u64((u64)b << 32 | a, key); +} +static inline u64 siphash_4u32(const u32 a, const u32 b, const u32 c, + const u32 d, const siphash_key_t *key) +{ + return siphash_2u64((u64)b << 32 | a, (u64)d << 32 | c, key); +} + + +static inline u64 ___siphash_aligned(const __le64 *data, size_t len, + const siphash_key_t *key) +{ + if (__builtin_constant_p(len) && len == 4) + return siphash_1u32(le32_to_cpup((const __le32 *)data), key); + if (__builtin_constant_p(len) && len == 8) + return siphash_1u64(le64_to_cpu(data[0]), key); + if (__builtin_constant_p(len) && len == 16) + return siphash_2u64(le64_to_cpu(data[0]), le64_to_cpu(data[1]), + key); + if (__builtin_constant_p(len) && len == 24) + return siphash_3u64(le64_to_cpu(data[0]), le64_to_cpu(data[1]), + le64_to_cpu(data[2]), key); + if (__builtin_constant_p(len) && len == 32) + return siphash_4u64(le64_to_cpu(data[0]), le64_to_cpu(data[1]), + le64_to_cpu(data[2]), le64_to_cpu(data[3]), + key); + return __siphash_aligned(data, len, key); +} + +/** + * siphash - compute 64-bit siphash PRF value + * @data: buffer to hash + * @size: size of @data + * @key: the siphash key + */ +static inline u64 siphash(const void *data, size_t len, + const siphash_key_t *key) +{ + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || + !IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) + return __siphash_unaligned(data, len, key); + return ___siphash_aligned(data, len, key); +} + +#define HSIPHASH_ALIGNMENT __alignof__(unsigned long) +typedef struct { + unsigned long key[2]; +} hsiphash_key_t; + +u32 __hsiphash_aligned(const void *data, size_t len, + const hsiphash_key_t *key); +u32 __hsiphash_unaligned(const void *data, size_t len, + const hsiphash_key_t *key); + +u32 hsiphash_1u32(const u32 a, const hsiphash_key_t *key); +u32 hsiphash_2u32(const u32 a, const u32 b, const hsiphash_key_t *key); +u32 hsiphash_3u32(const u32 a, const u32 b, const u32 c, + const hsiphash_key_t *key); +u32 hsiphash_4u32(const u32 a, const u32 b, const u32 c, const u32 d, + const hsiphash_key_t *key); + +static inline u32 ___hsiphash_aligned(const __le32 *data, size_t len, + const hsiphash_key_t *key) +{ + if (__builtin_constant_p(len) && len == 4) + return hsiphash_1u32(le32_to_cpu(data[0]), key); + if (__builtin_constant_p(len) && len == 8) + return hsiphash_2u32(le32_to_cpu(data[0]), le32_to_cpu(data[1]), + key); + if (__builtin_constant_p(len) && len == 12) + return hsiphash_3u32(le32_to_cpu(data[0]), le32_to_cpu(data[1]), + le32_to_cpu(data[2]), key); + if (__builtin_constant_p(len) && len == 16) + return hsiphash_4u32(le32_to_cpu(data[0]), le32_to_cpu(data[1]), + le32_to_cpu(data[2]), le32_to_cpu(data[3]), + key); + return __hsiphash_aligned(data, len, key); +} + +/** + * hsiphash - compute 32-bit hsiphash PRF value + * @data: buffer to hash + * @size: size of @data + * @key: the hsiphash key + */ +static inline u32 hsiphash(const void *data, size_t len, + const hsiphash_key_t *key) +{ + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || + !IS_ALIGNED((unsigned long)data, HSIPHASH_ALIGNMENT)) + return __hsiphash_unaligned(data, len, key); + return ___hsiphash_aligned(data, len, key); +} + +/* + * These macros expose the raw SipHash and HalfSipHash permutations. + * Do not use them directly! If you think you have a use for them, + * be sure to CC the maintainer of this file explaining why. + */ + +#define SIPHASH_PERMUTATION(a, b, c, d) ( \ + (a) += (b), (b) = rol64((b), 13), (b) ^= (a), (a) = rol64((a), 32), \ + (c) += (d), (d) = rol64((d), 16), (d) ^= (c), \ + (a) += (d), (d) = rol64((d), 21), (d) ^= (a), \ + (c) += (b), (b) = rol64((b), 17), (b) ^= (c), (c) = rol64((c), 32)) + +#define SIPHASH_CONST_0 0x736f6d6570736575ULL +#define SIPHASH_CONST_1 0x646f72616e646f6dULL +#define SIPHASH_CONST_2 0x6c7967656e657261ULL +#define SIPHASH_CONST_3 0x7465646279746573ULL + +#define HSIPHASH_PERMUTATION(a, b, c, d) ( \ + (a) += (b), (b) = rol32((b), 5), (b) ^= (a), (a) = rol32((a), 16), \ + (c) += (d), (d) = rol32((d), 8), (d) ^= (c), \ + (a) += (d), (d) = rol32((d), 7), (d) ^= (a), \ + (c) += (b), (b) = rol32((b), 13), (b) ^= (c), (c) = rol32((c), 16)) + +#define HSIPHASH_CONST_0 0U +#define HSIPHASH_CONST_1 0U +#define HSIPHASH_CONST_2 0x6c796765U +#define HSIPHASH_CONST_3 0x74656462U + +#endif /* _LINUX_SIPHASH_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/sizes.h b/sys/compat/linuxkpi/common/include/linux/sizes.h index d8a6e75192f6..430ad3ec427d 100644 --- a/sys/compat/linuxkpi/common/include/linux/sizes.h +++ b/sys/compat/linuxkpi/common/include/linux/sizes.h @@ -29,6 +29,17 @@ #ifndef _LINUXKPI_LINUX_SIZES_H_ #define _LINUXKPI_LINUX_SIZES_H_ +#define SZ_1 1 +#define SZ_2 2 +#define SZ_4 4 +#define SZ_8 8 +#define SZ_16 16 +#define SZ_32 32 +#define SZ_64 64 +#define SZ_128 128 +#define SZ_256 256 +#define SZ_512 512 + #define SZ_1K (1024 * 1) #define SZ_2K (1024 * 2) #define SZ_4K (1024 * 4) diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h index 2e560a120e41..c43d6daff5ee 100644 --- a/sys/compat/linuxkpi/common/include/linux/skbuff.h +++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h @@ -770,7 +770,7 @@ ___skb_queue_splice(const struct sk_buff_head *from, } static inline void -skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to) +skb_queue_splice(const struct sk_buff_head *from, struct sk_buff_head *to) { SKB_TRACE2(from, to); @@ -780,6 +780,13 @@ skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to) ___skb_queue_splice(from, (struct sk_buff *)to, to->next); to->qlen += from->qlen; +} + +static inline void +skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to) +{ + + skb_queue_splice(from, to); __skb_queue_head_init(from); } diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h index 0e649e1e3c4a..8d023eaddadd 100644 --- a/sys/compat/linuxkpi/common/include/linux/slab.h +++ b/sys/compat/linuxkpi/common/include/linux/slab.h @@ -4,7 +4,7 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2021 Mellanox Technologies, Ltd. * All rights reserved. - * Copyright (c) 2024-2025 The FreeBSD Foundation + * Copyright (c) 2024-2026 The FreeBSD Foundation * * Portions of this software were developed by Björn Zeeb * under sponsorship from the FreeBSD Foundation. @@ -51,6 +51,22 @@ MALLOC_DECLARE(M_KMALLOC); #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 kzalloc_obj(_p, ...) \ + kzalloc(sizeof(typeof(_p)), default_gfp(__VA_ARGS__)) +#define kzalloc_objs(_p, _n, ...) \ + kzalloc(size_mul((_n), sizeof(typeof(_p))), default_gfp(__VA_ARGS__)) +#define kzalloc_flex(_p, _field, _n, ...) \ +({ \ + const size_t __n = (_n); \ + const size_t __psize = struct_size_t(typeof(_p), _field, __n); \ + typeof(_p) *__p_obj; \ + \ + __p_obj = kzalloc(__psize, default_gfp(__VA_ARGS__)); \ + if (__p_obj != NULL) \ + __set_flex_counter(__p_obj->_field, __n); \ + \ + __p_obj; \ +}) #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) @@ -104,7 +120,7 @@ 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_krealloc(const void *, size_t, gfp_t); void lkpi_kfree(const void *); static inline gfp_t @@ -143,8 +159,14 @@ kmalloc_node(size_t size, gfp_t flags, int node) return (lkpi___kmalloc_node(size, flags, node)); } +#define kmalloc_obj(_p, ...) \ + kmalloc(sizeof(typeof(_p)), default_gfp(__VA_ARGS__)) + +#define kmalloc_objs(_p, _n, ...) \ + kmalloc(size_mul((_n) * sizeof(typeof(_p))), default_gfp(__VA_ARGS__)) + static inline void * -krealloc(void *ptr, size_t size, gfp_t flags) +krealloc(const void *ptr, size_t size, gfp_t flags) { return (lkpi_krealloc(ptr, size, flags)); } diff --git a/sys/compat/linuxkpi/common/include/linux/soc/airoha/airoha_offload.h b/sys/compat/linuxkpi/common/include/linux/soc/airoha/airoha_offload.h new file mode 100644 index 000000000000..ade0b06d839f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/soc/airoha/airoha_offload.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2026 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_SOC_AIROHA_AIROHA_OFFLOAD_H +#define _LINUXKPI_LINUX_SOC_AIROHA_AIROHA_OFFLOAD_H + +#include <linux/kernel.h> /* pr_debug */ + +enum airoha_npu_wlan_get_cmd { + __dummy_airoha_npu_wlan_get_cmd, +}; +enum airoha_npu_wlan_set_cmd { + __dummy_airoha_npu_wlan_set_cmd, +}; + +struct airoha_npu { +}; +struct airoha_npu_rx_dma_desc { +}; +struct airoha_npu_tx_dma_desc { +}; + +static __inline int +airoha_npu_wlan_send_msg(void *npu, int ifindex, + enum airoha_npu_wlan_set_cmd cmd, void *val, size_t len, gfp_t gfp) +{ + pr_debug("%s: TODO\n", __func__); + return (-EOPNOTSUPP); +} + +static __inline int +airoha_npu_wlan_get_msg(void *npu, int ifindex, + enum airoha_npu_wlan_get_cmd cmd, void *val, size_t len, gfp_t gfp) +{ + pr_debug("%s: TODO\n", __func__); + return (-EOPNOTSUPP); +} + +static __inline void +airoha_npu_wlan_enable_irq(struct airoha_npu *npu, int q) +{ + pr_debug("%s: TODO\n", __func__); +} + +#endif /* _LINUXKPI_LINUX_SOC_AIROHA_AIROHA_OFFLOAD_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 index 2b9c6ae4911e..64daa8c78c9d 100644 --- a/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h +++ b/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2022-2025 Bjoern A. Zeeb + * Copyright (c) 2022-2026 Bjoern A. Zeeb * * SPDX-License-Identifier: BSD-2-Clause */ @@ -37,7 +37,13 @@ mtk_wed_device_active(struct mtk_wed_device *dev __unused) static inline bool mtk_wed_get_rx_capa(struct mtk_wed_device *dev __unused) { + pr_debug("%s: TODO\n", __func__); + return (false); +} +static inline bool +mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev __unused) +{ pr_debug("%s: TODO\n", __func__); return (false); } @@ -66,6 +72,12 @@ mtk_wed_get_rx_capa(struct mtk_wed_device *dev __unused) { return (false); } + +static inline bool +mtk_wed_is_amsdu_supported(struct mtk_wed_device *dev __unused) +{ + return (false); +} #endif /* CONFIG_NET_MEDIATEK_SOC_WED */ #endif /* _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/sort.h b/sys/compat/linuxkpi/common/include/linux/sort.h index e6196d1f41c7..972c8514e6fb 100644 --- a/sys/compat/linuxkpi/common/include/linux/sort.h +++ b/sys/compat/linuxkpi/common/include/linux/sort.h @@ -34,8 +34,13 @@ #include <sys/libkern.h> #define sort(base, num, size, cmp, swap) do { \ - BUILD_BUG_ON_ZERO(swap); \ + BUILD_BUG_ON(swap); \ qsort(base, num, size, cmp); \ } while (0) +#define sort_r(base, num, size, cmp, swap, priv) do { \ + BUILD_BUG_ON(swap); \ + qsort_r(base, num, size, cmp, priv); \ +} 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 dc10b0457153..a786cbab5e13 100644 --- a/sys/compat/linuxkpi/common/include/linux/spinlock.h +++ b/sys/compat/linuxkpi/common/include/linux/spinlock.h @@ -36,10 +36,12 @@ #include <sys/mutex.h> #include <sys/kdb.h> +#include <linux/cleanup.h> #include <linux/compiler.h> #include <linux/rwlock.h> #include <linux/bottom_half.h> #include <linux/lockdep.h> +#include <linux/preempt.h> typedef struct mtx spinlock_t; @@ -178,4 +180,33 @@ _atomic_dec_and_lock_irqsave(atomic_t *cnt, spinlock_t *lock, return (0); } +/* + * struct raw_spinlock + */ + +typedef struct raw_spinlock { + struct mtx lock; +} raw_spinlock_t; + +#define raw_spin_lock_init(rlock) \ + mtx_init(&(rlock)->lock, spin_lock_name("lnxspin_raw"), \ + NULL, MTX_DEF | MTX_NOWITNESS | MTX_NEW) + +#define raw_spin_lock(rl) spin_lock(&(rl)->lock) +#define raw_spin_trylock(rl) spin_trylock(&(rl)->lock) +#define raw_spin_unlock(rl) spin_unlock(&(rl)->lock) + +#define raw_spin_lock_irqsave(rl, f) spin_lock_irqsave(&(rl)->lock, (f)) +#define raw_spin_trylock_irqsave(rl, f) spin_trylock_irqsave(&(rl)->lock, (f)) +#define raw_spin_unlock_irqrestore(rl, f) spin_unlock_irqrestore(&(rl)->lock, (f)) + +/* + * cleanup.h related pre-defined cases. + */ +DEFINE_LOCK_GUARD_1(spinlock_irqsave, + spinlock_t, + spin_lock_irqsave(_T->lock, _T->flags), + spin_unlock_irqrestore(_T->lock, _T->flags), + unsigned long flags) + #endif /* _LINUXKPI_LINUX_SPINLOCK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ssb/ssb_regs.h b/sys/compat/linuxkpi/common/include/linux/ssb/ssb_regs.h new file mode 100644 index 000000000000..e1c18b6b632a --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ssb/ssb_regs.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Bjoern A. Zeeb + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _LINUXKPI_LINUX_SSB_SSB_REGS_H +#define _LINUXKPI_LINUX_SSB_SSB_REGS_H + +#define SSB_IDHIGH_RCHI 0x00007000 +#define SSB_IDHIGH_RCHI_SHIFT 8 +#define SSB_IDHIGH_RCLO 0x0000000F +#define SSB_IDLOW_INITIATOR 0x00000080 +#define SSB_IMSTATE_BUSY 0x01800000 +#define SSB_IMSTATE_IBE 0x00020000 +#define SSB_IMSTATE_REJECT 0x02000000 +#define SSB_IMSTATE_TO 0x00040000 +#define SSB_TMSHIGH_BUSY 0x00000004 +#define SSB_TMSHIGH_SERR 0x00000001 +#define SSB_TMSLOW_CLOCK 0x00010000 +#define SSB_TMSLOW_FGC 0x00020000 +#define SSB_TMSLOW_REJECT 0x00000002 +#define SSB_TMSLOW_RESET 0x00000001 + +#endif /* _LINUXKPI_LINUX_SSB_SSB_REGS_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/string.h b/sys/compat/linuxkpi/common/include/linux/string.h index f7b64560d254..0b858e7af623 100644 --- a/sys/compat/linuxkpi/common/include/linux/string.h +++ b/sys/compat/linuxkpi/common/include/linux/string.h @@ -303,6 +303,22 @@ memcpy_and_pad(void *dst, size_t dstlen, const void *src, size_t len, int ch) } } +#define strtomem(dst, src) do { \ + size_t dstlen = ARRAY_SIZE(dst); \ + size_t srclen = __builtin_object_size(src, 1); \ + srclen = MIN(srclen, dstlen); \ + srclen = strnlen(src, srclen); \ + memcpy(dst, src, srclen); \ +} while (0) + +#define strtomem_pad(dst, src, pad) do { \ + size_t dstlen = ARRAY_SIZE(dst); \ + size_t srclen = __builtin_object_size(src, 1); \ + srclen = MIN(srclen, dstlen); \ + srclen = strnlen(src, srclen); \ + memcpy_and_pad(dst, dstlen, src, srclen, pad); \ +} while (0) + #define memset_startat(ptr, bytepat, smember) \ ({ \ uint8_t *_ptr = (uint8_t *)(ptr); \ diff --git a/sys/compat/linuxkpi/common/include/linux/string_choices.h b/sys/compat/linuxkpi/common/include/linux/string_choices.h index 74aa3fd019b2..db540d3e7d40 100644 --- a/sys/compat/linuxkpi/common/include/linux/string_choices.h +++ b/sys/compat/linuxkpi/common/include/linux/string_choices.h @@ -33,39 +33,33 @@ static inline const char * str_yes_no(bool value) { - if (value) - return "yes"; - else - return "no"; + return (value ? "yes" : "no"); } static inline const char * str_on_off(bool value) { - if (value) - return "on"; - else - return "off"; + return (value ? "on" : "off"); } static inline const char * str_enabled_disabled(bool value) { - if (value) - return "enabled"; - else - return "disabled"; + return (value ? "enabled" : "disabled"); } static inline const char * str_enable_disable(bool value) { - if (value) - return "enable"; - else - return "disable"; + return (value ? "enable" : "disable"); } #define str_disable_enable(_v) str_enable_disable(!(_v)) +static inline const char * +str_read_write(bool value) +{ + return (value ? "read" : "write"); +} + #endif diff --git a/sys/compat/linuxkpi/common/include/linux/suspend.h b/sys/compat/linuxkpi/common/include/linux/suspend.h index dacecbebdc08..3d5d5d594127 100644 --- a/sys/compat/linuxkpi/common/include/linux/suspend.h +++ b/sys/compat/linuxkpi/common/include/linux/suspend.h @@ -3,6 +3,12 @@ #ifndef _LINUXKPI_LINUX_SUSPEND_H_ #define _LINUXKPI_LINUX_SUSPEND_H_ +#include <linux/swap.h> +#include <linux/notifier.h> +#include <linux/init.h> +#include <linux/pm.h> +#include <linux/mm.h> + typedef int suspend_state_t; extern suspend_state_t pm_suspend_target_state; diff --git a/sys/compat/linuxkpi/common/include/linux/swap.h b/sys/compat/linuxkpi/common/include/linux/swap.h index 5828db7ae392..9c1db9677f9e 100644 --- a/sys/compat/linuxkpi/common/include/linux/swap.h +++ b/sys/compat/linuxkpi/common/include/linux/swap.h @@ -37,7 +37,14 @@ #include <vm/swap_pager.h> #include <vm/vm_pageout.h> +#include <linux/spinlock.h> +#include <linux/mmzone.h> +#include <linux/list.h> +#include <linux/memcontrol.h> +#include <linux/sched.h> +#include <linux/fs.h> #include <linux/pagemap.h> +#include <linux/atomic.h> #include <linux/page-flags.h> static inline long diff --git a/sys/compat/linuxkpi/common/include/linux/sysfs.h b/sys/compat/linuxkpi/common/include/linux/sysfs.h index 470c224a9778..7c8c4e2e32b9 100644 --- a/sys/compat/linuxkpi/common/include/linux/sysfs.h +++ b/sys/compat/linuxkpi/common/include/linux/sysfs.h @@ -43,13 +43,6 @@ struct sysfs_ops { size_t); }; -struct attribute_group { - const char *name; - mode_t (*is_visible)(struct kobject *, - struct attribute *, int); - struct attribute **attrs; -}; - struct bin_attribute { struct attribute attr; size_t size; @@ -59,6 +52,14 @@ struct bin_attribute { struct bin_attribute *, char *, loff_t, size_t); }; +struct attribute_group { + const char *name; + mode_t (*is_visible)(struct kobject *, + struct attribute *, int); + struct attribute **attrs; + struct bin_attribute **bin_attrs; +}; + #define __ATTR(_name, _mode, _show, _store) { \ .attr = { .name = __stringify(_name), .mode = _mode }, \ .show = _show, .store = _store, \ @@ -370,6 +371,7 @@ static inline int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { struct attribute **attr; + struct bin_attribute **bin_attr; struct sysctl_oid *oidp; /* Don't create the group node if grp->name is undefined. */ @@ -378,11 +380,19 @@ sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) OID_AUTO, grp->name, CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, grp->name); else oidp = kobj->oidp; - for (attr = grp->attrs; *attr != NULL; attr++) { + for (attr = grp->attrs; attr != NULL && *attr != NULL; attr++) { SYSCTL_ADD_OID(NULL, SYSCTL_CHILDREN(oidp), OID_AUTO, (*attr)->name, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE, kobj, (uintptr_t)*attr, sysctl_handle_attr, "A", ""); } + for (bin_attr = grp->bin_attrs; + bin_attr != NULL && *bin_attr != NULL; + bin_attr++) { + SYSCTL_ADD_OID(NULL, SYSCTL_CHILDREN(oidp), OID_AUTO, + (*bin_attr)->attr.name, + CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_MPSAFE, + kobj, (uintptr_t)*bin_attr, sysctl_handle_bin_attr, "", ""); + } return (0); } @@ -434,14 +444,20 @@ static inline void sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp) { struct attribute **attr; + struct bin_attribute **bin_attr; struct sysctl_oid *oidp; SYSCTL_FOREACH(oidp, SYSCTL_CHILDREN(kobj->oidp)) { if (strcmp(oidp->oid_name, grp->name) != 0) continue; - for (attr = grp->attrs; *attr != NULL; attr++) { + for (attr = grp->attrs; attr != NULL && *attr != NULL; attr++) { sysctl_remove_name(oidp, (*attr)->name, 1, 1); } + for (bin_attr = grp->bin_attrs; + bin_attr != NULL && *bin_attr != NULL; + bin_attr++) { + sysctl_remove_name(oidp, (*bin_attr)->attr.name, 1, 1); + } } } diff --git a/sys/compat/linuxkpi/common/include/linux/uuid.h b/sys/compat/linuxkpi/common/include/linux/uuid.h index 4f6f4a8b34f0..0765ef4dcc1e 100644 --- a/sys/compat/linuxkpi/common/include/linux/uuid.h +++ b/sys/compat/linuxkpi/common/include/linux/uuid.h @@ -33,6 +33,7 @@ #include <linux/random.h> +#define UUID_SIZE 16 #define UUID_STRING_LEN 36 #define GUID_INIT(x0_3, x4_5, x6_7, x8, x9, x10, x11, x12, x13, x14, x15) \ @@ -59,6 +60,8 @@ typedef struct { char x[16]; } guid_t; +extern const guid_t guid_null; + static inline void guid_gen(guid_t *g) { @@ -68,10 +71,34 @@ guid_gen(guid_t *g) g->x[8] = (g->x[8] & 0x3f) | 0x80; } +static inline bool +guid_equal(const guid_t *u1, const guid_t *u2) +{ + return (memcmp(u1, u2, sizeof(guid_t)) == 0); +} + static inline void guid_copy(guid_t *dst, const guid_t *src) { memcpy(dst, src, sizeof(*dst)); } +static inline void +import_guid(guid_t *dst, const uint8_t *src) +{ + memcpy(dst, src, sizeof(guid_t)); +} + +static inline void +export_guid(uint8_t *dst, const guid_t *src) +{ + memcpy(dst, src, sizeof(guid_t)); +} + +static inline bool +guid_is_null(const guid_t *guid) +{ + return (guid_equal(guid, &guid_null)); +} + #endif /* _LINUXKPI_LINUX_UUID_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/wait.h b/sys/compat/linuxkpi/common/include/linux/wait.h index 03ddce2c06f5..698a1056b713 100644 --- a/sys/compat/linuxkpi/common/include/linux/wait.h +++ b/sys/compat/linuxkpi/common/include/linux/wait.h @@ -43,13 +43,6 @@ #define SKIP_SLEEP() (SCHEDULER_STOPPED() || kdb_active) -#define might_sleep() \ - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "might_sleep()") - -#define might_sleep_if(cond) do { \ - if (cond) { might_sleep(); } \ -} while (0) - struct wait_queue; struct wait_queue_head; |
