diff options
Diffstat (limited to 'sys/compat/linuxkpi/common/include/linux')
206 files changed, 8783 insertions, 1871 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/acpi.h b/sys/compat/linuxkpi/common/include/linux/acpi.h index 1a9d25e7a7ff..3e1ec1b20626 100644 --- a/sys/compat/linuxkpi/common/include/linux/acpi.h +++ b/sys/compat/linuxkpi/common/include/linux/acpi.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org> * @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_ACPI_H_ @@ -41,6 +39,10 @@ #define ACPI_HANDLE(dev) \ ((dev)->bsddev != NULL ? bsd_acpi_get_handle((dev)->bsddev) : NULL) +#define acpi_device_handle(dev) \ + ((dev) != NULL ? bsd_acpi_get_handle(dev) : NULL) +static inline void acpi_dev_put(struct acpi_device *adev) {} +#define acpi_handle_debug(handle, fmt, ...) #endif diff --git a/sys/compat/linuxkpi/common/include/linux/acpi_amd_wbrf.h b/sys/compat/linuxkpi/common/include/linux/acpi_amd_wbrf.h new file mode 100644 index 000000000000..92c2ead41c45 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/acpi_amd_wbrf.h @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_ACPI_AMD_WBRF_H_ +#define _LINUXKPI_LINUX_ACPI_AMD_WBRF_H_ + +#include <linux/device.h> +#include <linux/notifier.h> + +#define MAX_NUM_OF_WBRF_RANGES 11 + +#define WBRF_RECORD_ADD 0x0 +#define WBRF_RECORD_REMOVE 0x1 + +struct freq_band_range { + uint64_t start; + uint64_t end; +}; + +struct wbrf_ranges_in_out { + uint64_t num_of_ranges; + struct freq_band_range band_list[MAX_NUM_OF_WBRF_RANGES]; +}; + +enum wbrf_notifier_actions { + WBRF_CHANGED, +}; + +/* + * The following functions currently have dummy implementations that, on Linux, + * are used when CONFIG_AMD_WBRF is not set at compile time. + */ + +static inline bool +acpi_amd_wbrf_supported_consumer(struct device *dev) +{ + return (false); +} + +static inline int +acpi_amd_wbrf_add_remove(struct device *dev, uint8_t action, + struct wbrf_ranges_in_out *in) +{ + return (-ENODEV); +} + +static inline bool +acpi_amd_wbrf_supported_producer(struct device *dev) +{ + return (false); +} + +static inline int +amd_wbrf_retrieve_freq_band(struct device *dev, struct wbrf_ranges_in_out *out) +{ + return (-ENODEV); +} + +static inline int +amd_wbrf_register_notifier(struct notifier_block *nb) +{ + return (-ENODEV); +} + +static inline int +amd_wbrf_unregister_notifier(struct notifier_block *nb) +{ + return (-ENODEV); +} + +#endif /* _LINUXKPI_LINUX_ACPI_AMD_WBRF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/agp_backend.h b/sys/compat/linuxkpi/common/include/linux/agp_backend.h new file mode 100644 index 000000000000..c855fd842970 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/agp_backend.h @@ -0,0 +1,28 @@ +/* Public domain */ + +#ifndef _LINUXKPI_LINUX_AGP_BACKEND_H_ +#define _LINUXKPI_LINUX_AGP_BACKEND_H_ + +#include <sys/types.h> + +struct agp_version { + uint16_t major; + uint16_t minor; +}; + +struct agp_kern_info { + struct agp_version version; + uint16_t vendor; + uint16_t device; + unsigned long mode; + unsigned long aper_base; + size_t aper_size; + int max_memory; + int current_memory; + bool cant_use_aperture; + unsigned long page_mask; +}; + +struct agp_memory; + +#endif /* _LINUXKPI_LINUX_AGP_BACKEND_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/anon_inodes.h b/sys/compat/linuxkpi/common/include/linux/anon_inodes.h index cab5cbd4d67e..c69f6e152b17 100644 --- a/sys/compat/linuxkpi/common/include/linux/anon_inodes.h +++ b/sys/compat/linuxkpi/common/include/linux/anon_inodes.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> * diff --git a/sys/compat/linuxkpi/common/include/linux/aperture.h b/sys/compat/linuxkpi/common/include/linux/aperture.h new file mode 100644 index 000000000000..7eced3cc3cb1 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/aperture.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef _LINUX_APERTURE_H_ +#define _LINUX_APERTURE_H_ + +#include <linux/types.h> + +#define CONFIG_APERTURE_HELPERS + +struct pci_dev; +struct platform_device; + +#if defined(CONFIG_APERTURE_HELPERS) +int devm_aperture_acquire_for_platform_device(struct platform_device *pdev, + resource_size_t base, + resource_size_t size); + +int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, + const char *name); + +int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev); + +int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name); +#else +static inline int devm_aperture_acquire_for_platform_device(struct platform_device *pdev, + resource_size_t base, + resource_size_t size) +{ + return 0; +} + +static inline int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, + const char *name) +{ + return 0; +} + +static inline int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev) +{ + return 0; +} + +static inline int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name) +{ + return 0; +} +#endif + +/** + * aperture_remove_all_conflicting_devices - remove all existing framebuffers + * @name: a descriptive name of the requesting driver + * + * This function removes all graphics device drivers. Use this function on systems + * that can have their framebuffer located anywhere in memory. + * + * Returns: + * 0 on success, or a negative errno code otherwise + */ +static inline int aperture_remove_all_conflicting_devices(const char *name) +{ + return aperture_remove_conflicting_devices(0, (resource_size_t)-1, name); +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/apple-gmux.h b/sys/compat/linuxkpi/common/include/linux/apple-gmux.h new file mode 100644 index 000000000000..812a782c57d4 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/apple-gmux.h @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_APPLE_GMUX_H +#define _LINUXKPI_LINUX_APPLE_GMUX_H + +static inline bool +apple_gmux_detect(void *a, void *b) +{ + return false; +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/atomic.h b/sys/compat/linuxkpi/common/include/linux/atomic.h index e491283ae6e5..bc76928a7d67 100644 --- a/sys/compat/linuxkpi/common/include/linux/atomic.h +++ b/sys/compat/linuxkpi/common/include/linux/atomic.h @@ -22,8 +22,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_ATOMIC_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/average.h b/sys/compat/linuxkpi/common/include/linux/average.h index 61b2010d6509..4191a351c5c6 100644 --- a/sys/compat/linuxkpi/common/include/linux/average.h +++ b/sys/compat/linuxkpi/common/include/linux/average.h @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_AVERAGE_H diff --git a/sys/compat/linuxkpi/common/include/linux/backlight.h b/sys/compat/linuxkpi/common/include/linux/backlight.h index 9591a4b671ab..4f8f7440925a 100644 --- a/sys/compat/linuxkpi/common/include/linux/backlight.h +++ b/sys/compat/linuxkpi/common/include/linux/backlight.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BACKLIGHT_H_ @@ -92,6 +90,13 @@ backlight_force_update(struct backlight_device *bd, int reason) } static inline int +backlight_get_brightness(struct backlight_device *bd) +{ + + return (bd->props.brightness); +} + +static inline int backlight_device_set_brightness(struct backlight_device *bd, int brightness) { @@ -119,4 +124,11 @@ backlight_disable(struct backlight_device *bd) return (backlight_update_status(bd)); } +static inline bool +backlight_is_blank(struct backlight_device *bd) +{ + + return (bd->props.power != 0/* FB_BLANK_UNBLANK */); +} + #endif /* _LINUXKPI_LINUX_BACKLIGHT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/bcd.h b/sys/compat/linuxkpi/common/include/linux/bcd.h index 8a40da1a330b..385819910454 100644 --- a/sys/compat/linuxkpi/common/include/linux/bcd.h +++ b/sys/compat/linuxkpi/common/include/linux/bcd.h @@ -23,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BCD_H diff --git a/sys/compat/linuxkpi/common/include/linux/bitfield.h b/sys/compat/linuxkpi/common/include/linux/bitfield.h index c22757d54290..8a91b0663f37 100644 --- a/sys/compat/linuxkpi/common/include/linux/bitfield.h +++ b/sys/compat/linuxkpi/common/include/linux/bitfield.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BITFIELD_H @@ -127,9 +125,16 @@ _uX_replace_bits(8) #define __bf_shf(x) (__builtin_ffsll(x) - 1) +#define FIELD_FIT(_mask, _value) \ + (!(((typeof(_mask))(_value) << __bf_shf(_mask)) & ~(_mask))) + #define FIELD_PREP(_mask, _value) \ (((typeof(_mask))(_value) << __bf_shf(_mask)) & (_mask)) +/* Likely would need extra sanity checks compared to FIELD_PREP()? */ +#define FIELD_PREP_CONST(_mask, _value) \ + (((typeof(_mask))(_value) << __bf_shf(_mask)) & (_mask)) + #define FIELD_GET(_mask, _value) \ ((typeof(_mask))(((_value) & (_mask)) >> __bf_shf(_mask))) diff --git a/sys/compat/linuxkpi/common/include/linux/bitmap.h b/sys/compat/linuxkpi/common/include/linux/bitmap.h index 1ae6078966a4..f26a0f99dc03 100644 --- a/sys/compat/linuxkpi/common/include/linux/bitmap.h +++ b/sys/compat/linuxkpi/common/include/linux/bitmap.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BITMAP_H_ @@ -266,6 +264,27 @@ bitmap_subset(const unsigned long *pa, return (1); } +static inline bool +bitmap_intersects(const unsigned long *pa, const unsigned long *pb, + unsigned size) +{ + const unsigned end = BIT_WORD(size); + const unsigned tail = size & (BITS_PER_LONG - 1); + unsigned i; + + for (i = 0; i != end; i++) + if (pa[i] & pb[i]) + return (true); + + if (tail) { + const unsigned long mask = BITMAP_LAST_WORD_MASK(tail); + + if (pa[end] & pb[end] & mask) + return (true); + } + return (false); +} + static inline void bitmap_complement(unsigned long *dst, const unsigned long *src, const unsigned int size) @@ -289,6 +308,49 @@ bitmap_copy(unsigned long *dst, const unsigned long *src, } static inline void +bitmap_to_arr32(uint32_t *dst, const unsigned long *src, unsigned int size) +{ + const unsigned int end = howmany(size, 32); + +#ifdef __LP64__ + unsigned int i = 0; + while (i < end) { + dst[i++] = (uint32_t)(*src & UINT_MAX); + if (i < end) + dst[i++] = (uint32_t)(*src >> 32); + src++; + } +#else + bitmap_copy((unsigned long *)dst, src, size); +#endif + if ((size % 32) != 0) /* Linux uses BITS_PER_LONG. Seems to be a bug */ + dst[end - 1] &= (uint32_t)(UINT_MAX >> (32 - (size % 32))); +} + +static inline void +bitmap_from_arr32(unsigned long *dst, const uint32_t *src, + unsigned int size) +{ + const unsigned int end = BIT_WORD(size); + const unsigned int tail = size & (BITS_PER_LONG - 1); + +#ifdef __LP64__ + const unsigned int end32 = howmany(size, 32); + unsigned int i = 0; + + while (i < end32) { + dst[i++/2] = (unsigned long) *(src++); + if (i < end32) + dst[i++/2] |= ((unsigned long) *(src++)) << 32; + } +#else + bitmap_copy(dst, (const unsigned long *)src, size); +#endif + if ((size % BITS_PER_LONG) != 0) + dst[end] &= BITMAP_LAST_WORD_MASK(tail); +} + +static inline void bitmap_or(unsigned long *dst, const unsigned long *src1, const unsigned long *src2, const unsigned int size) { @@ -332,6 +394,40 @@ bitmap_xor(unsigned long *dst, const unsigned long *src1, dst[i] = src1[i] ^ src2[i]; } +static inline void +bitmap_shift_right(unsigned long *dst, const unsigned long *src, + unsigned int shift, unsigned int size) +{ + const unsigned int end = BITS_TO_LONGS(size); + const unsigned int tail = size & (BITS_PER_LONG - 1); + const unsigned long mask = BITMAP_LAST_WORD_MASK(tail); + const unsigned int off = BIT_WORD(shift); + const unsigned int rem = shift & (BITS_PER_LONG - 1); + unsigned long left, right; + unsigned int i, srcpos; + + for (i = 0, srcpos = off; srcpos < end; i++, srcpos++) { + right = src[srcpos]; + left = 0; + + if (srcpos == end - 1) + right &= mask; + + if (rem != 0) { + right >>= rem; + if (srcpos + 1 < end) { + left = src[srcpos + 1]; + if (srcpos + 1 == end - 1) + left &= mask; + left <<= (BITS_PER_LONG - rem); + } + } + dst[i] = left | right; + } + if (off != 0) + memset(dst + end - off, 0, off * sizeof(unsigned long)); +} + static inline unsigned long * bitmap_alloc(unsigned int size, gfp_t flags) { diff --git a/sys/compat/linuxkpi/common/include/linux/bitops.h b/sys/compat/linuxkpi/common/include/linux/bitops.h index b6c54b2e6858..bc776a0db9c4 100644 --- a/sys/compat/linuxkpi/common/include/linux/bitops.h +++ b/sys/compat/linuxkpi/common/include/linux/bitops.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BITOPS_H_ #define _LINUXKPI_LINUX_BITOPS_H_ @@ -56,6 +54,7 @@ #define GENMASK_ULL(h, l) (((~0ULL) >> (BITS_PER_LONG_LONG - (h) - 1)) & ((~0ULL) << (l))) #define BITS_PER_BYTE 8 #define BITS_PER_TYPE(t) (sizeof(t) * BITS_PER_BYTE) +#define BITS_TO_BYTES(n) howmany((n), BITS_PER_BYTE) #define hweight8(x) bitcount((uint8_t)(x)) #define hweight16(x) bitcount16(x) @@ -63,10 +62,10 @@ #define hweight64(x) bitcount64(x) #define hweight_long(x) bitcountl(x) -#define HWEIGHT8(x) (bitcount8((uint8_t)(x)) + 1) -#define HWEIGHT16(x) (bitcount16(x) + 1) -#define HWEIGHT32(x) (bitcount32(x) + 1) -#define HWEIGHT64(x) (bitcount64(x) + 1) +#define HWEIGHT8(x) (bitcount8((uint8_t)(x))) +#define HWEIGHT16(x) (bitcount16(x)) +#define HWEIGHT32(x) (bitcount32(x)) +#define HWEIGHT64(x) (bitcount64(x)) static inline int __ffs(int mask) @@ -289,6 +288,15 @@ find_next_zero_bit(const unsigned long *addr, unsigned long size, #define test_bit(i, a) \ !!(READ_ONCE(((volatile const unsigned long *)(a))[BIT_WORD(i)]) & BIT_MASK(i)) +static inline void +__assign_bit(long bit, volatile unsigned long *addr, bool value) +{ + if (value) + __set_bit(bit, addr); + else + __clear_bit(bit, addr); +} + static inline int test_and_clear_bit(long bit, volatile unsigned long *var) { diff --git a/sys/compat/linuxkpi/common/include/linux/bottom_half.h b/sys/compat/linuxkpi/common/include/linux/bottom_half.h index 1b139c481283..12b170845cbc 100644 --- a/sys/compat/linuxkpi/common/include/linux/bottom_half.h +++ b/sys/compat/linuxkpi/common/include/linux/bottom_half.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BOTTOM_HALF_H_ #define _LINUXKPI_LINUX_BOTTOM_HALF_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/bsearch.h b/sys/compat/linuxkpi/common/include/linux/bsearch.h index 8cc329aa855c..fb67109e4bba 100644 --- a/sys/compat/linuxkpi/common/include/linux/bsearch.h +++ b/sys/compat/linuxkpi/common/include/linux/bsearch.h @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_BSEARCH_H diff --git a/sys/compat/linuxkpi/common/include/linux/build_bug.h b/sys/compat/linuxkpi/common/include/linux/build_bug.h new file mode 100644 index 000000000000..6a026376cfc8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/build_bug.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org> + * Copyright (c) 2018 Johannes Lundberg <johalun0@gmail.com> + * Copyright (c) 2021 The FreeBSD Foundation + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC + * + * Portions of this software were developed by Bjoern A. Zeeb + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_BUILD_BUG_H_ +#define _LINUXKPI_LINUX_BUILD_BUG_H_ + +#include <sys/param.h> + +#include <linux/compiler.h> + +/* + * BUILD_BUG_ON() can happen inside functions where _Static_assert() does not + * seem to work. Use old-schoold-ish CTASSERT from before commit + * a3085588a88fa58eb5b1eaae471999e1995a29cf but also make sure we do not + * end up with an unused typedef or variable. The compiler should optimise + * it away entirely. + */ +#define _O_CTASSERT(x) _O__CTASSERT(x, __LINE__) +#define _O__CTASSERT(x, y) _O___CTASSERT(x, y) +#define _O___CTASSERT(x, y) while (0) { \ + typedef char __assert_line_ ## y[(x) ? 1 : -1]; \ + __assert_line_ ## y _x __unused; \ + _x[0] = '\0'; \ +} + +#define BUILD_BUG() do { CTASSERT(0); } while (0) +#define BUILD_BUG_ON(x) do { _O_CTASSERT(!(x)) } while (0) +#define BUILD_BUG_ON_MSG(x, msg) BUILD_BUG_ON(x) +#define BUILD_BUG_ON_NOT_POWER_OF_2(x) BUILD_BUG_ON(!powerof2(x)) +#define BUILD_BUG_ON_INVALID(expr) while (0) { (void)(expr); } +#define BUILD_BUG_ON_ZERO(x) ((int)sizeof(struct { int:-((x) != 0); })) + +#define static_assert(x, ...) __static_assert(x, ##__VA_ARGS__, #x) +#define __static_assert(x, msg, ...) _Static_assert(x, msg) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/cache.h b/sys/compat/linuxkpi/common/include/linux/cache.h index 6479d5d04d3a..b02b28d08ea9 100644 --- a/sys/compat/linuxkpi/common/include/linux/cache.h +++ b/sys/compat/linuxkpi/common/include/linux/cache.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_CACHE_H_ #define _LINUXKPI_LINUX_CACHE_H_ @@ -35,6 +33,7 @@ #define cache_line_size() CACHE_LINE_SIZE #define L1_CACHE_BYTES CACHE_LINE_SIZE +#define L1_CACHE_ALIGN(x) ALIGN(x, CACHE_LINE_SIZE) #define SMP_CACHE_BYTES L1_CACHE_BYTES diff --git a/sys/compat/linuxkpi/common/include/linux/capability.h b/sys/compat/linuxkpi/common/include/linux/capability.h index 547ee586ad8e..e3dacd4e9f15 100644 --- a/sys/compat/linuxkpi/common/include/linux/capability.h +++ b/sys/compat/linuxkpi/common/include/linux/capability.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2015 Rimvydas Jasinskas * All rights reserved. diff --git a/sys/compat/linuxkpi/common/include/linux/cc_platform.h b/sys/compat/linuxkpi/common/include/linux/cc_platform.h new file mode 100644 index 000000000000..1544c141614b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cc_platform.h @@ -0,0 +1,21 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_CC_PLATFORM_H_ +#define _LINUXKPI_LINUX_CC_PLATFORM_H_ + +#include <linux/types.h> +#include <linux/stddef.h> + +enum cc_attr { + CC_ATTR_MEM_ENCRYPT, + CC_ATTR_GUEST_MEM_ENCRYPT, +}; + +static inline bool +cc_platform_has(enum cc_attr attr __unused) +{ + + return (false); +} + +#endif /* _LINUXKPI_LINUX_CC_PLATFORM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cdev.h b/sys/compat/linuxkpi/common/include/linux/cdev.h index 2befe9b259cb..d989db14c2f8 100644 --- a/sys/compat/linuxkpi/common/include/linux/cdev.h +++ b/sys/compat/linuxkpi/common/include/linux/cdev.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_CDEV_H_ #define _LINUXKPI_LINUX_CDEV_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/cec.h b/sys/compat/linuxkpi/common/include/linux/cec.h new file mode 100644 index 000000000000..e0854d87d85c --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cec.h @@ -0,0 +1,8 @@ +/* Public domain */ + +#ifndef _LINUXKPI_LINUX_CEC_H_ +#define _LINUXKPI_LINUX_CEC_H_ + +#define CEC_PHYS_ADDR_INVALID 0xffff + +#endif /* _LINUXKPI_LINUX_CEC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cgroup.h b/sys/compat/linuxkpi/common/include/linux/cgroup.h new file mode 100644 index 000000000000..a9dd22fd0f4c --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cgroup.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_CGROUP_H_ +#define _LINUXKPI_LINUX_CGROUP_H_ + +#include <linux/kernel_stat.h> + +#endif /* _LINUXKPI_LINUX_CGROUP_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/cleanup.h b/sys/compat/linuxkpi/common/include/linux/cleanup.h new file mode 100644 index 000000000000..01f234f0cbe7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cleanup.h @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + */ + +#ifndef _LINUXKPI_LINUX_CLEANUP_H +#define _LINUXKPI_LINUX_CLEANUP_H + +#define __cleanup(_f) __attribute__((__cleanup__(_f))) + +/* + * Note: "_T" are special as they are exposed into common code for + * statements. Extra care should be taken when changing the code. + */ +#define DEFINE_GUARD(_n, _dt, _lock, _unlock) \ + \ + typedef _dt guard_ ## _n ## _t; \ + \ + static inline _dt \ + guard_ ## _n ## _create( _dt _T) \ + { \ + _dt c; \ + \ + c = ({ _lock; _T; }); \ + return (c); \ + } \ + \ + static inline void \ + guard_ ## _n ## _destroy(_dt *t) \ + { \ + _dt _T; \ + \ + _T = *t; \ + if (_T) { _unlock; }; \ + } + +/* We need to keep these calls unique. */ +#define guard(_n) \ + guard_ ## _n ## _t guard_ ## _n ## _ ## __COUNTER__ \ + __cleanup(guard_ ## _n ## _destroy) = guard_ ## _n ## _create + +#endif /* _LINUXKPI_LINUX_CLEANUP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/clocksource.h b/sys/compat/linuxkpi/common/include/linux/clocksource.h index 8027ed76ec0f..3e7664c3e57e 100644 --- a/sys/compat/linuxkpi/common/include/linux/clocksource.h +++ b/sys/compat/linuxkpi/common/include/linux/clocksource.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_CLOCKSOURCE_H #define _LINUXKPI_LINUX_CLOCKSOURCE_H diff --git a/sys/compat/linuxkpi/common/include/linux/compat.h b/sys/compat/linuxkpi/common/include/linux/compat.h index 5e4dd1daf67d..8a5a6918bb7c 100644 --- a/sys/compat/linuxkpi/common/include/linux/compat.h +++ b/sys/compat/linuxkpi/common/include/linux/compat.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_COMPAT_H_ #define _LINUXKPI_LINUX_COMPAT_H_ @@ -43,19 +41,28 @@ extern int linux_alloc_current(struct thread *, int flags); extern void linux_free_current(struct task_struct *); extern struct domainset *linux_get_vm_domain_set(int node); +#define __current_unallocated(td) \ + __predict_false((td)->td_lkpi_task == NULL) + static inline void linux_set_current(struct thread *td) { - if (__predict_false(td->td_lkpi_task == NULL)) + if (__current_unallocated(td)) lkpi_alloc_current(td, M_WAITOK); } static inline int linux_set_current_flags(struct thread *td, int flags) { - if (__predict_false(td->td_lkpi_task == NULL)) + if (__current_unallocated(td)) return (lkpi_alloc_current(td, flags)); return (0); } +#define compat_ptr(x) ((void *)(uintptr_t)x) +#define ptr_to_compat(x) ((uintptr_t)x) + +typedef void fpu_safe_exec_cb_t(void *ctx); +void lkpi_fpu_safe_exec(fpu_safe_exec_cb_t func, void *ctx); + #endif /* _LINUXKPI_LINUX_COMPAT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/compiler.h b/sys/compat/linuxkpi/common/include/linux/compiler.h index 87a37228736f..fb5ad3bf4fe4 100644 --- a/sys/compat/linuxkpi/common/include/linux/compiler.h +++ b/sys/compat/linuxkpi/common/include/linux/compiler.h @@ -26,8 +26,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_COMPILER_H_ #define _LINUXKPI_LINUX_COMPILER_H_ @@ -50,7 +48,9 @@ #define __cond_lock(x,c) (c) #define __bitwise #define __devinitdata +#ifndef __deprecated #define __deprecated +#endif #define __init #define __initconst #define __devinit @@ -64,10 +64,22 @@ #undef __always_inline #define __always_inline inline #define noinline __noinline +#define noinline_for_stack __noinline #define ____cacheline_aligned __aligned(CACHE_LINE_SIZE) #define ____cacheline_aligned_in_smp __aligned(CACHE_LINE_SIZE) #define fallthrough /* FALLTHROUGH */ do { } while(0) +#if __has_attribute(__nonstring__) +#define __nonstring __attribute__((__nonstring__)) +#else +#define __nonstring +#endif +#if __has_attribute(__counted_by__) +#define __counted_by(_x) __attribute__((__counted_by__(_x))) +#else +#define __counted_by(_x) +#endif + #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #define typeof(x) __typeof(x) @@ -79,6 +91,10 @@ #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)) @@ -87,18 +103,16 @@ #define ___PASTE(a,b) a##b #define __PASTE(a,b) ___PASTE(a,b) -#define ACCESS_ONCE(x) (*(volatile __typeof(x) *)&(x)) - #define WRITE_ONCE(x,v) do { \ barrier(); \ - ACCESS_ONCE(x) = (v); \ + (*(volatile __typeof(x) *)(uintptr_t)&(x)) = (v); \ barrier(); \ } while (0) #define READ_ONCE(x) ({ \ __typeof(x) __var = ({ \ barrier(); \ - ACCESS_ONCE(x); \ + (*(const volatile __typeof(x) *)&(x)); \ }); \ barrier(); \ __var; \ @@ -113,4 +127,7 @@ #define sizeof_field(_s, _m) sizeof(((_s *)0)->_m) +#define is_signed_type(t) ((t)-1 < (t)1) +#define is_unsigned_type(t) ((t)-1 > (t)1) + #endif /* _LINUXKPI_LINUX_COMPILER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/completion.h b/sys/compat/linuxkpi/common/include/linux/completion.h index 2f58bd5c03e6..9f8bebb4cf82 100644 --- a/sys/compat/linuxkpi/common/include/linux/completion.h +++ b/sys/compat/linuxkpi/common/include/linux/completion.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_COMPLETION_H_ #define _LINUXKPI_LINUX_COMPLETION_H_ @@ -62,7 +60,8 @@ struct completion { extern void linux_complete_common(struct completion *, int); extern int linux_wait_for_common(struct completion *, int); -extern int linux_wait_for_timeout_common(struct completion *, int, int); +extern unsigned long linux_wait_for_timeout_common(struct completion *, + unsigned long, int); extern int linux_try_wait_for_completion(struct completion *); extern int linux_completion_done(struct completion *); diff --git a/sys/compat/linuxkpi/common/include/linux/container_of.h b/sys/compat/linuxkpi/common/include/linux/container_of.h new file mode 100644 index 000000000000..7210d531b055 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/container_of.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2017 Matt Macy <mmacy@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_CONTAINER_OF_H +#define _LINUXKPI_LINUX_CONTAINER_OF_H + +#include <sys/stdint.h> + +#include <linux/build_bug.h> +#include <linux/stddef.h> + +#define container_of(ptr, type, member) \ +({ \ + const __typeof(((type *)0)->member) *__p = (ptr); \ + (type *)((uintptr_t)__p - offsetof(type, member)); \ +}) + +#define container_of_const(ptr, type, member) \ + _Generic(ptr, \ + const typeof(*(ptr)) *: \ + (const type *)container_of(ptr, type, member), \ + default: \ + container_of(ptr, type, member) \ + ) + +#define typeof_member(type, member) __typeof(((type *)0)->member) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/cpu.h b/sys/compat/linuxkpi/common/include/linux/cpu.h index 53fa9db424c2..43ec3d66a2e3 100644 --- a/sys/compat/linuxkpi/common/include/linux/cpu.h +++ b/sys/compat/linuxkpi/common/include/linux/cpu.h @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_CPU_H @@ -44,6 +42,8 @@ typedef cpuset_t cpumask_t; extern cpumask_t cpu_online_mask; +cpumask_t *lkpi_get_static_single_cpu_mask(int); + static __inline int cpumask_next(int cpuid, cpumask_t mask) { @@ -73,4 +73,6 @@ cpumask_set_cpu(int cpu, cpumask_t *mask) CPU_SET(cpu, mask); } +#define cpumask_of(_cpu) (lkpi_get_static_single_cpu_mask(_cpu)) + #endif /* _LINUXKPI_LINUX_CPU_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/cpufeature.h b/sys/compat/linuxkpi/common/include/linux/cpufeature.h new file mode 100644 index 000000000000..746d1a7164a8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/cpufeature.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_CPUFEATURE_H_ +#define _LINUXKPI_LINUX_CPUFEATURE_H_ + +/* + * Linux includes the following header. We don't have it on FreeBSD yet, so + * let's comment this include for now. It is still referenced here because + * sometimes, consumers of headers rely voluntarily or not on the namespace + * pollution. + */ +/* #include <linux/init.h> */ +#include <linux/mod_devicetable.h> +#include <asm/cpufeature.h> + +#endif /* _LINUXKPI_LINUX_CPUFEATURE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/crc32.h b/sys/compat/linuxkpi/common/include/linux/crc32.h index a93be642fb1a..e6d39fa7c5ff 100644 --- a/sys/compat/linuxkpi/common/include/linux/crc32.h +++ b/sys/compat/linuxkpi/common/include/linux/crc32.h @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_CRC32_H diff --git a/sys/compat/linuxkpi/common/include/linux/dcache.h b/sys/compat/linuxkpi/common/include/linux/dcache.h index 9f9943a18dc6..992d6f7c2720 100644 --- a/sys/compat/linuxkpi/common/include/linux/dcache.h +++ b/sys/compat/linuxkpi/common/include/linux/dcache.h @@ -22,15 +22,14 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DCACHE_H #define _LINUXKPI_LINUX_DCACHE_H -struct vnode; -struct pfs_node; +#include <sys/vnode.h> + +#include <fs/pseudofs/pseudofs.h> struct dentry { struct vnode *d_inode; diff --git a/sys/compat/linuxkpi/common/include/linux/debugfs.h b/sys/compat/linuxkpi/common/include/linux/debugfs.h index 6a3273cbbf3c..4d146e085a7b 100644 --- a/sys/compat/linuxkpi/common/include/linux/debugfs.h +++ b/sys/compat/linuxkpi/common/include/linux/debugfs.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org> * @@ -23,29 +23,102 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DEBUGFS_H_ #define _LINUXKPI_LINUX_DEBUGFS_H_ #include <linux/fs.h> +#include <linux/module.h> #include <linux/seq_file.h> - #include <linux/types.h> -void debugfs_remove(struct dentry *dentry); +MALLOC_DECLARE(M_DFSINT); + +struct debugfs_reg32 { + char *name; + unsigned long offset; +}; + +struct debugfs_regset32 { + const struct debugfs_reg32 *regs; + int nregs; +}; + +struct debugfs_blob_wrapper { + void *data; + size_t size; +}; + +static inline bool +debugfs_initialized(void) +{ + + return (true); +} struct dentry *debugfs_create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops); + struct dentry *parent, void *data, + const struct file_operations *fops); + +/* TODO: We currently ignore the `file_size` argument. */ +struct dentry *debugfs_create_file_size(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + loff_t file_size); + +struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, +struct dentry *parent, void *data, + const struct file_operations *fops); + +struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + const struct file_operations *fops_ro, + const struct file_operations *fops_wo); struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, - const char *dest); + const char *dest); + +struct dentry *debugfs_lookup(const char *name, struct dentry *parent); + +void debugfs_remove(struct dentry *dentry); void debugfs_remove_recursive(struct dentry *dentry); -#endif +#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ + DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) +#define DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) \ + DEFINE_SIMPLE_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) + +void debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, + bool *value); +void debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, + uint8_t *value); +void debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, + uint16_t *value); +void debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, + uint32_t *value); +void debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, + uint64_t *value); +void debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, + uint8_t *value); +void debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, + uint16_t *value); +void debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, + uint32_t *value); +void debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, + uint64_t *value); +void debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent, + unsigned long *value); +void debugfs_create_atomic_t(const char *name, umode_t mode, struct dentry *parent, + atomic_t *value); +void debugfs_create_str(const char *name, umode_t mode, struct dentry *parent, + char **value); + +struct dentry *debugfs_create_blob(const char *name, umode_t mode, + struct dentry *parent, struct debugfs_blob_wrapper *value); + +#endif /* _LINUXKPI_LINUX_DEBUGFS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/delay.h b/sys/compat/linuxkpi/common/include/linux/delay.h index ea0a8253b09f..f19d1a759c26 100644 --- a/sys/compat/linuxkpi/common/include/linux/delay.h +++ b/sys/compat/linuxkpi/common/include/linux/delay.h @@ -26,8 +26,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DELAY_H_ #define _LINUXKPI_LINUX_DELAY_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/devcoredump.h b/sys/compat/linuxkpi/common/include/linux/devcoredump.h index eecf5380bfc3..5fa06c6595a8 100644 --- a/sys/compat/linuxkpi/common/include/linux/devcoredump.h +++ b/sys/compat/linuxkpi/common/include/linux/devcoredump.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 The FreeBSD Foundation + * Copyright (c) 2020-2025 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DEVCOREDUMP_H @@ -73,4 +71,11 @@ dev_coredumpsg(struct device *dev __unused, struct scatterlist *table, _lkpi_dev_coredumpsg_free(table); } +static inline void +_devcd_free_sgtable(struct scatterlist *table) +{ + /* UNIMPLEMENTED */ + _lkpi_dev_coredumpsg_free(table); +} + #endif /* _LINUXKPI_LINUX_DEVCOREDUMP_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h index e39b3f95ca0d..2556b0c45e49 100644 --- a/sys/compat/linuxkpi/common/include/linux/device.h +++ b/sys/compat/linuxkpi/common/include/linux/device.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2021-2022 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,8 +29,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DEVICE_H_ #define _LINUXKPI_LINUX_DEVICE_H_ @@ -37,25 +39,24 @@ #include <linux/sysfs.h> #include <linux/list.h> #include <linux/compiler.h> -#include <linux/types.h> #include <linux/module.h> #include <linux/workqueue.h> #include <linux/kdev_t.h> #include <linux/backlight.h> #include <linux/pm.h> #include <linux/idr.h> +#include <linux/overflow.h> #include <linux/ratelimit.h> /* via linux/dev_printk.h */ +#include <linux/fwnode.h> #include <asm/atomic.h> #include <sys/bus.h> #include <sys/backlight.h> struct device; -struct fwnode_handle; struct class { const char *name; - struct module *owner; struct kobject kobj; devclass_t bsdclass; const struct dev_pm_ops *pm; @@ -67,6 +68,7 @@ struct class { struct dev_pm_ops { int (*prepare)(struct device *dev); + void (*complete)(struct device *dev); int (*suspend)(struct device *dev); int (*suspend_late)(struct device *dev); int (*resume)(struct device *dev); @@ -79,6 +81,7 @@ struct dev_pm_ops { int (*poweroff_late)(struct device *dev); int (*restore)(struct device *dev); int (*restore_early)(struct device *dev); + int (*suspend_noirq)(struct device *dev); int (*runtime_suspend)(struct device *dev); int (*runtime_resume)(struct device *dev); int (*runtime_idle)(struct device *dev); @@ -87,6 +90,8 @@ struct dev_pm_ops { struct device_driver { const char *name; const struct dev_pm_ops *pm; + + void (*shutdown) (struct device *); }; struct device_type { @@ -124,6 +129,8 @@ struct device { spinlock_t devres_lock; struct list_head devres_head; + + struct dev_pm_info power; }; extern struct device linux_root_device; @@ -183,15 +190,47 @@ show_class_attr_string(struct class *class, struct class_attribute_string class_attr_##_name = \ _CLASS_ATTR_STRING(_name, _mode, _str) -#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_crit(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_emerg(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) -#define dev_dbg(dev, fmt, ...) do { } while (0) #define dev_printk(lvl, dev, fmt, ...) \ - device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) + device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) + +#define dev_emerg(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_alert(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_crit(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_err(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_warn(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_info(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__) +#define dev_dbg(dev, fmt, ...) do { } while (0) + +#define dev_WARN(dev, fmt, ...) \ + device_printf((dev)->bsddev, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__) + +#define dev_WARN_ONCE(dev, condition, fmt, ...) do { \ + static bool __dev_WARN_ONCE; \ + bool __ret_warn_on = (condition); \ + if (unlikely(__ret_warn_on)) { \ + if (!__dev_WARN_ONCE) { \ + __dev_WARN_ONCE = true; \ + device_printf((dev)->bsddev, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__); \ + } \ + } \ +} while (0) + +#define dev_info_once(dev, ...) do { \ + static bool __dev_info_once; \ + if (!__dev_info_once) { \ + __dev_info_once = true; \ + dev_info(dev, __VA_ARGS__); \ + } \ +} while (0) + +#define dev_warn_once(dev, ...) do { \ + static bool __dev_warn_once; \ + if (!__dev_warn_once) { \ + __dev_warn_once = 1; \ + dev_warn(dev, __VA_ARGS__); \ + } \ +} while (0) #define dev_err_once(dev, ...) do { \ static bool __dev_err_once; \ @@ -201,6 +240,14 @@ show_class_attr_string(struct class *class, } \ } while (0) +#define dev_dbg_once(dev, ...) do { \ + static bool __dev_dbg_once; \ + if (!__dev_dbg_once) { \ + __dev_dbg_once = 1; \ + dev_dbg(dev, __VA_ARGS__); \ + } \ +} while (0) + #define dev_err_ratelimited(dev, ...) do { \ static linux_ratelimit_t __ratelimited; \ if (linux_ratelimited(&__ratelimited)) \ @@ -213,6 +260,12 @@ show_class_attr_string(struct class *class, dev_warn(dev, __VA_ARGS__); \ } while (0) +#define dev_dbg_ratelimited(dev, ...) do { \ + static linux_ratelimit_t __ratelimited; \ + if (linux_ratelimited(&__ratelimited)) \ + dev_dbg(dev, __VA_ARGS__); \ +} while (0) + /* Public and LinuxKPI internal devres functions. */ void *lkpi_devres_alloc(void(*release)(struct device *, void *), size_t, gfp_t); void lkpi_devres_add(struct device *, void *); @@ -231,6 +284,7 @@ int lkpi_devres_destroy(struct device *, void(*release)(struct device *, void *) void lkpi_devres_release_free_list(struct device *); void lkpi_devres_unlink(struct device *, void *); void lkpi_devm_kmalloc_release(struct device *, void *); +#define devm_kfree(_d, _p) lkpi_devm_kmalloc_release(_d, _p) static inline const char * dev_driver_string(const struct device *dev) @@ -278,6 +332,13 @@ dev_name(const struct device *dev) return kobject_name(&dev->kobj); } +static inline bool +dev_is_removable(struct device *dev) +{ + + return (false); +} + #define dev_set_name(_dev, _fmt, ...) \ kobject_set_name(&(_dev)->kobj, (_fmt), ##__VA_ARGS__) @@ -289,7 +350,12 @@ put_device(struct device *dev) kobject_put(&dev->kobj); } -struct class *class_create(struct module *owner, const char *name); +struct class *lkpi_class_create(const char *name); +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60400 +#define class_create(name) lkpi_class_create(name) +#else +#define class_create(owner, name) lkpi_class_create(name) +#endif static inline int class_register(struct class *class) @@ -517,6 +583,30 @@ device_reprobe(struct device *dev) return (-error); } +static inline void +device_set_wakeup_enable(struct device *dev __unused, bool enable __unused) +{ + + /* + * XXX-BZ TODO This is used by wireless drivers supporting WoWLAN which + * we currently do not support. + */ +} + +static inline int +device_wakeup_enable(struct device *dev) +{ + + device_set_wakeup_enable(dev, true); + return (0); +} + +static inline bool +device_iommu_mapped(struct device *dev __unused) +{ + return (false); +} + #define dev_pm_set_driver_flags(dev, flags) do { \ } while (0) @@ -593,10 +683,36 @@ devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) return (p); } +static inline void * +devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp) +{ + void *dst; + + if (len == 0) + return (NULL); + + dst = devm_kmalloc(dev, len, gfp); + if (dst != NULL) + memcpy(dst, src, len); + + return (dst); +} + #define devm_kzalloc(_dev, _size, _gfp) \ devm_kmalloc((_dev), (_size), (_gfp) | __GFP_ZERO) #define devm_kcalloc(_dev, _sizen, _size, _gfp) \ devm_kmalloc((_dev), ((_sizen) * (_size)), (_gfp) | __GFP_ZERO) +int lkpi_devm_add_action(struct device *dev, void (*action)(void *), void *data); +#define devm_add_action(dev, action, data) \ + lkpi_devm_add_action(dev, action, data); +int lkpi_devm_add_action_or_reset(struct device *dev, void (*action)(void *), void *data); +#define devm_add_action_or_reset(dev, action, data) \ + lkpi_devm_add_action_or_reset(dev, action, data) + +int lkpi_devm_device_add_group(struct device *dev, const struct attribute_group *group); +#define devm_device_add_group(dev, group) \ + lkpi_devm_device_add_group(dev, group) + #endif /* _LINUXKPI_LINUX_DEVICE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/device/driver.h b/sys/compat/linuxkpi/common/include/linux/device/driver.h new file mode 100644 index 000000000000..03b510c9c8b7 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/device/driver.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Bjoern A. Zeeb + * Copyright (c) 2024 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. + */ + +#ifndef LINUXKPI_LINUX_DEVICE_DRIVER_H +#define LINUXKPI_LINUX_DEVICE_DRIVER_H + +#include <sys/cdefs.h> +#include <linux/module.h> + +#define module_driver(_drv, _regf, _unregf) \ +static inline int \ +__CONCAT(__CONCAT(_, _drv), _init)(void) \ +{ \ + return (_regf(&(_drv))); \ +} \ + \ +static inline void \ +__CONCAT(__CONCAT(_, _drv), _exit)(void) \ +{ \ + _unregf(&(_drv)); \ +} \ + \ +module_init(__CONCAT(__CONCAT(_, _drv), _init)); \ +module_exit(__CONCAT(__CONCAT(_, _drv), _exit)) + +#endif /* LINUXKPI_LINUX_DEVICE_DRIVER_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/dma-attrs.h b/sys/compat/linuxkpi/common/include/linux/dma-attrs.h index 741e1aa15d67..c9cfa9b621d5 100644 --- a/sys/compat/linuxkpi/common/include/linux/dma-attrs.h +++ b/sys/compat/linuxkpi/common/include/linux/dma-attrs.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DMA_ATTR_H_ #define _LINUXKPI_LINUX_DMA_ATTR_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/dma-buf-map.h b/sys/compat/linuxkpi/common/include/linux/dma-buf-map.h new file mode 100644 index 000000000000..567ce3b072b3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/dma-buf-map.h @@ -0,0 +1,91 @@ +/* Public domain. */ + +#ifndef _LINUX_DMA_BUF_MAP_H +#define _LINUX_DMA_BUF_MAP_H + +#include <linux/io.h> +#include <linux/string.h> + +struct dma_buf_map { + union { + void *vaddr_iomem; + void *vaddr; + }; + bool is_iomem; +}; + +static inline void +dma_buf_map_incr(struct dma_buf_map *dbm, size_t n) +{ + if (dbm->is_iomem) + dbm->vaddr_iomem += n; + else + dbm->vaddr += n; +} + +static inline void +dma_buf_map_memcpy_to(struct dma_buf_map *dbm, const void *src, size_t len) +{ + if (dbm->is_iomem) + memcpy_toio(dbm->vaddr_iomem, src, len); + else + memcpy(dbm->vaddr, src, len); +} + +static inline bool +dma_buf_map_is_null(const struct dma_buf_map *dbm) +{ + if (dbm->is_iomem) + return (dbm->vaddr_iomem == NULL); + else + return (dbm->vaddr == NULL); +} + +static inline bool +dma_buf_map_is_set(const struct dma_buf_map *dbm) +{ + if (dbm->is_iomem) + return (dbm->vaddr_iomem != NULL); + else + return (dbm->vaddr != NULL); +} + +static inline bool +dma_buf_map_is_equal( + const struct dma_buf_map *dbm_a, const struct dma_buf_map *dbm_b) +{ + if (dbm_a->is_iomem != dbm_b->is_iomem) + return (false); + + if (dbm_a->is_iomem) + return (dbm_a->vaddr_iomem == dbm_b->vaddr_iomem); + else + return (dbm_a->vaddr == dbm_b->vaddr); +} + +static inline void +dma_buf_map_clear(struct dma_buf_map *dbm) +{ + if (dbm->is_iomem) { + dbm->vaddr_iomem = NULL; + dbm->is_iomem = false; + } else { + dbm->vaddr = NULL; + } +} + +static inline void +dma_buf_map_set_vaddr_iomem(struct dma_buf_map *dbm, void *addr) +{ + dbm->vaddr_iomem = addr; + dbm->is_iomem = true; +} + +static inline void +dma_buf_map_set_vaddr(struct dma_buf_map *dbm, void *addr) +{ + dbm->vaddr = addr; + dbm->is_iomem = false; +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h index dd3bbc094dfb..2d8e1196d3d3 100644 --- a/sys/compat/linuxkpi/common/include/linux/dma-mapping.h +++ b/sys/compat/linuxkpi/common/include/linux/dma-mapping.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DMA_MAPPING_H_ #define _LINUXKPI_LINUX_DMA_MAPPING_H_ @@ -45,6 +43,7 @@ #include <vm/vm.h> #include <vm/vm_page.h> +#include <vm/uma_align_mask.h> #include <vm/pmap.h> #include <machine/bus.h> @@ -95,13 +94,19 @@ int linux_dma_tag_init(struct device *, u64); int linux_dma_tag_init_coherent(struct device *, u64); void *linux_dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag); -dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len); -void linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t size); +void *linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); +dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len); /* backward compat */ +dma_addr_t lkpi_dma_map_phys(struct device *, vm_paddr_t, size_t, + enum dma_data_direction, unsigned long); +void linux_dma_unmap(struct device *dev, dma_addr_t dma_addr, size_t size); /* backward compat */ +void lkpi_dma_unmap(struct device *, dma_addr_t, size_t, + enum dma_data_direction, unsigned long); int linux_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, - int nents, enum dma_data_direction dir __unused, + int nents, enum dma_data_direction direction, unsigned long attrs __unused); void linux_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, - int nents __unused, enum dma_data_direction dir __unused, + int nents __unused, enum dma_data_direction direction, unsigned long attrs __unused); void linuxkpi_dma_sync(struct device *, dma_addr_t, size_t, bus_dmasync_op_t); @@ -159,21 +164,30 @@ dma_zalloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, return (dma_alloc_coherent(dev, size, dma_handle, flag | __GFP_ZERO)); } +static inline void * +dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flag) +{ + + return (linuxkpi_dmam_alloc_coherent(dev, size, dma_handle, flag)); +} + static inline void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr) { - linux_dma_unmap(dev, dma_addr, size); - kmem_free((vm_offset_t)cpu_addr, size); + lkpi_dma_unmap(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0); + kmem_free(cpu_addr, size); } static inline dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page, size_t offset, - size_t size, enum dma_data_direction dir, unsigned long attrs) + size_t size, enum dma_data_direction direction, unsigned long attrs) { - return (linux_dma_map_phys(dev, VM_PAGE_TO_PHYS(page) + offset, size)); + return (lkpi_dma_map_phys(dev, page_to_phys(page) + offset, size, + direction, attrs)); } /* linux_dma_(un)map_sg_attrs does not support attrs yet */ @@ -188,7 +202,8 @@ dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction) { - return (linux_dma_map_phys(dev, VM_PAGE_TO_PHYS(page) + offset, size)); + return (lkpi_dma_map_phys(dev, page_to_phys(page) + offset, size, + direction, 0)); } static inline void @@ -196,7 +211,21 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction) { - linux_dma_unmap(dev, dma_address, size); + lkpi_dma_unmap(dev, dma_address, size, direction, 0); +} + +static inline dma_addr_t +dma_map_resource(struct device *dev, phys_addr_t paddr, size_t size, + enum dma_data_direction direction, unsigned long attrs) +{ + return (lkpi_dma_map_phys(dev, paddr, size, direction, attrs)); +} + +static inline void +dma_unmap_resource(struct device *dev, dma_addr_t dma, size_t size, + enum dma_data_direction direction, unsigned long attrs) +{ + lkpi_dma_unmap(dev, dma, size, direction, attrs); } static inline void @@ -254,35 +283,44 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma, linuxkpi_dma_sync(dev, dma, size, op); } +/* (20250329) These four seem to be unused code. */ static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } static inline void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } static inline void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, int direction) + unsigned long offset, size_t size, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } static inline void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, int direction) + unsigned long offset, size_t size, enum dma_data_direction direction) { + pr_debug("%s:%d: TODO dir %d\n", __func__, __LINE__, direction); } +#define DMA_MAPPING_ERROR (~(dma_addr_t)0) + static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { - return (dma_addr == 0); + if (dma_addr == 0 || dma_addr == DMA_MAPPING_ERROR) + return (-ENOMEM); + return (0); } static inline unsigned int dma_set_max_seg_size(struct device *dev, @@ -293,24 +331,17 @@ static inline unsigned int dma_set_max_seg_size(struct device *dev, static inline dma_addr_t _dma_map_single_attrs(struct device *dev, void *ptr, size_t size, - enum dma_data_direction direction, unsigned long attrs __unused) + enum dma_data_direction direction, unsigned long attrs) { - dma_addr_t dma; - - dma = linux_dma_map_phys(dev, vtophys(ptr), size); - if (!dma_mapping_error(dev, dma)) - dma_sync_single_for_device(dev, dma, size, direction); - - return (dma); + return (lkpi_dma_map_phys(dev, vtophys(ptr), size, + direction, attrs)); } static inline void _dma_unmap_single_attrs(struct device *dev, dma_addr_t dma, size_t size, - enum dma_data_direction direction, unsigned long attrs __unused) + enum dma_data_direction direction, unsigned long attrs) { - - dma_sync_single_for_cpu(dev, dma, size, direction); - linux_dma_unmap(dev, dma, size); + lkpi_dma_unmap(dev, dma, size, direction, attrs); } static inline size_t @@ -338,7 +369,31 @@ dma_max_mapping_size(struct device *dev) #define dma_unmap_len(p, name) ((p)->name) #define dma_unmap_len_set(p, name, v) (((p)->name) = (v)) -extern int uma_align_cache; -#define dma_get_cache_alignment() uma_align_cache +#define dma_get_cache_alignment() (uma_get_cache_align_mask() + 1) + + +static inline int +dma_map_sgtable(struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir, + unsigned long attrs) +{ + int nents; + + nents = dma_map_sg_attrs(dev, sgt->sgl, sgt->nents, dir, attrs); + if (nents < 0) + return (nents); + sgt->nents = nents; + return (0); +} + +static inline void +dma_unmap_sgtable(struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir, + unsigned long attrs) +{ + + dma_unmap_sg_attrs(dev, sgt->sgl, sgt->nents, dir, attrs); +} + #endif /* _LINUXKPI_LINUX_DMA_MAPPING_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/dmapool.h b/sys/compat/linuxkpi/common/include/linux/dmapool.h index e45472dabc60..8501a32e30b7 100644 --- a/sys/compat/linuxkpi/common/include/linux/dmapool.h +++ b/sys/compat/linuxkpi/common/include/linux/dmapool.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_DMAPOOL_H_ #define _LINUXKPI_LINUX_DMAPOOL_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/dmi.h b/sys/compat/linuxkpi/common/include/linux/dmi.h index 339f622f89b2..d9760ee0324f 100644 --- a/sys/compat/linuxkpi/common/include/linux/dmi.h +++ b/sys/compat/linuxkpi/common/include/linux/dmi.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef __LINUXKPI_LINUX_DMI_H__ @@ -34,6 +32,12 @@ #include <sys/types.h> #include <linux/mod_devicetable.h> +struct dmi_header { + uint8_t type; + uint8_t length; + uint16_t handle; +}; + int linux_dmi_check_system(const struct dmi_system_id *); bool linux_dmi_match(enum dmi_field, const char *); const struct dmi_system_id *linux_dmi_first_match(const struct dmi_system_id *); @@ -44,4 +48,11 @@ const char *linux_dmi_get_system_info(int); #define dmi_first_match(sysid) linux_dmi_first_match(sysid) #define dmi_get_system_info(sysid) linux_dmi_get_system_info(sysid) +static inline int +dmi_walk(void (*callbackf)(const struct dmi_header *, void *), void *arg) +{ + + return (-ENXIO); +} + #endif /* __LINUXKPI_LINUX_DMI_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/dynamic_debug.h b/sys/compat/linuxkpi/common/include/linux/dynamic_debug.h new file mode 100644 index 000000000000..12915eec3b68 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/dynamic_debug.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_DYNAMIC_DEBUG_H +#define _LINUXKPI_LINUX_DYNAMIC_DEBUG_H + +#define DECLARE_DYNDBG_CLASSMAP(a, b, c, ...) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/efi.h b/sys/compat/linuxkpi/common/include/linux/efi.h index 03702bba557a..aa33371bd0e8 100644 --- a/sys/compat/linuxkpi/common/include/linux/efi.h +++ b/sys/compat/linuxkpi/common/include/linux/efi.h @@ -29,6 +29,7 @@ #define _LINUXKPI_LINUX_EFI_H_ #include <sys/param.h> +#include <sys/queue.h> #include <sys/linker.h> #include <sys/systm.h> @@ -40,9 +41,6 @@ static inline bool __efi_enabled(int feature) { -#if defined(MODINFOMD_EFI_MAP) && !defined(__amd64__) - caddr_t kmdp; -#endif bool enabled = false; switch (feature) { @@ -51,10 +49,7 @@ __efi_enabled(int feature) /* Use cached value on amd64 */ enabled = efi_boot; #elif defined(MODINFOMD_EFI_MAP) - kmdp = preload_search_by_type("elf kernel"); - if (kmdp == NULL) - kmdp = preload_search_by_type("elf64 kernel"); - enabled = preload_search_info(kmdp, + enabled = preload_search_info(preload_kmdp, MODINFO_METADATA | MODINFOMD_EFI_MAP) != NULL; #endif break; diff --git a/sys/compat/linuxkpi/common/include/linux/err.h b/sys/compat/linuxkpi/common/include/linux/err.h index 693f7962df65..3d19949e641e 100644 --- a/sys/compat/linuxkpi/common/include/linux/err.h +++ b/sys/compat/linuxkpi/common/include/linux/err.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_ERR_H_ #define _LINUXKPI_LINUX_ERR_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/errno.h b/sys/compat/linuxkpi/common/include/linux/errno.h index f9c0ceeac5e2..d634675d43d0 100644 --- a/sys/compat/linuxkpi/common/include/linux/errno.h +++ b/sys/compat/linuxkpi/common/include/linux/errno.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_ERRNO_H_ #define _LINUXKPI_LINUX_ERRNO_H_ @@ -34,6 +32,8 @@ #include <sys/errno.h> #define EBADRQC 56 /* Bad request code */ +#define EBADSLT 57 /* Invalid slot */ +#define ENOKEY 126 /* Required key not available */ #define ECHRNG EDOM #define ETIME ETIMEDOUT @@ -44,6 +44,7 @@ #define ERESTARTSYS 512 #define ENOTSUPP EOPNOTSUPP #define ENONET EHOSTDOWN +#define EHWPOISON 133 /* Memory page hardware error */ /* * The error numbers below are arbitrary and do not resemble the numbers @@ -67,5 +68,6 @@ #define ENOMEDIUM 532 #define ENOSR 533 #define ELNRNG 534 +#define ENAVAIL 535 #endif /* _LINUXKPI_LINUX_ERRNO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/etherdevice.h b/sys/compat/linuxkpi/common/include/linux/etherdevice.h index 219ed55a880d..1f2d6cf22d7e 100644 --- a/sys/compat/linuxkpi/common/include/linux/etherdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/etherdevice.h @@ -21,8 +21,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_ETHERDEVICE_H_ #define _LINUXKPI_LINUX_ETHERDEVICE_H_ @@ -55,19 +53,27 @@ struct ethtool_modinfo { static inline bool is_zero_ether_addr(const u8 * addr) { - return ((addr[0] + addr[1] + addr[2] + addr[3] + addr[4] + addr[5]) == 0x00); + return ((addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == + 0x00); +} + +static inline bool +is_unicast_ether_addr(const u8 * addr) +{ + return ((addr[0] & 0x01) == 0x00); } static inline bool is_multicast_ether_addr(const u8 * addr) { - return (0x01 & addr[0]); + return ((addr[0] & 0x01) == 0x01); } static inline bool is_broadcast_ether_addr(const u8 * addr) { - return ((addr[0] + addr[1] + addr[2] + addr[3] + addr[4] + addr[5]) == (6 * 0xff)); + return ((addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == + 0xff); } static inline bool diff --git a/sys/compat/linuxkpi/common/include/linux/ethtool.h b/sys/compat/linuxkpi/common/include/linux/ethtool.h index 9195766f752d..f5567cd7ea40 100644 --- a/sys/compat/linuxkpi/common/include/linux/ethtool.h +++ b/sys/compat/linuxkpi/common/include/linux/ethtool.h @@ -23,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_ETHTOOL_H_ @@ -32,10 +30,28 @@ #include <linux/types.h> -#define ETHTOOL_FWVERS_LEN 64 +#define ETH_GSTRING_LEN (2 * IF_NAMESIZE) /* Increase if not large enough */ + +#define ETHTOOL_FWVERS_LEN 32 struct ethtool_stats { uint8_t __dummy[0]; }; +enum ethtool_ss { + ETH_SS_STATS, +}; + +struct ethtool_drvinfo { + char driver[32]; + char version[32]; + char fw_version[ETHTOOL_FWVERS_LEN]; + char bus_info[32]; +}; + +struct net_device; +struct ethtool_ops { + void(*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); +}; + #endif /* _LINUXKPI_LINUX_ETHTOOL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/eventpoll.h b/sys/compat/linuxkpi/common/include/linux/eventpoll.h new file mode 100644 index 000000000000..e77e6d689f86 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/eventpoll.h @@ -0,0 +1,45 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022, Jake Freeland <jfree@freebsd.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_EVENTPOLL_H_ +#define _LINUXKPI_LINUX_EVENTPOLL_H_ + +#include <sys/poll.h> + +#define EPOLLIN POLLIN +#define EPOLLPRI POLLPRI +#define EPOLLOUT POLLOUT +#define EPOLLERR POLLERR +#define EPOLLHUP POLLHUP +#define EPOLLNVAL POLLNVAL +#define EPOLLRDNORM POLLRDNORM +#define EPOLLRDBAND POLLRDBAND +#define EPOLLWRNORM POLLWRNORM +#define EPOLLWRBAND POLLWRBAND +#define EPOLLRDHUP POLLRDHUP + +#endif /* _LINUXKPI_LINUX_EVENTPOLL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/export.h b/sys/compat/linuxkpi/common/include/linux/export.h index e9ac669a535f..f48bd6af45d3 100644 --- a/sys/compat/linuxkpi/common/include/linux/export.h +++ b/sys/compat/linuxkpi/common/include/linux/export.h @@ -21,8 +21,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_EXPORT_H #define _LINUXKPI_LINUX_EXPORT_H diff --git a/sys/compat/linuxkpi/common/include/linux/file.h b/sys/compat/linuxkpi/common/include/linux/file.h index 32db72d771fc..f6e988c2d88e 100644 --- a/sys/compat/linuxkpi/common/include/linux/file.h +++ b/sys/compat/linuxkpi/common/include/linux/file.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_FILE_H_ #define _LINUXKPI_LINUX_FILE_H_ @@ -45,7 +43,7 @@ struct linux_file; #undef file -extern struct fileops linuxfileops; +extern const struct fileops linuxfileops; static inline struct linux_file * linux_fget(unsigned int fd) diff --git a/sys/compat/linuxkpi/common/include/linux/firmware.h b/sys/compat/linuxkpi/common/include/linux/firmware.h index ada7d0d73edf..a6330ddafb55 100644 --- a/sys/compat/linuxkpi/common/include/linux/firmware.h +++ b/sys/compat/linuxkpi/common/include/linux/firmware.h @@ -2,6 +2,7 @@ * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2022 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,8 +27,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_FIRMWARE_H @@ -56,6 +55,8 @@ int linuxkpi_request_firmware(const struct linuxkpi_firmware **, int linuxkpi_firmware_request_nowarn(const struct linuxkpi_firmware **, const char *, struct device *); void linuxkpi_release_firmware(const struct linuxkpi_firmware *); +int linuxkpi_request_partial_firmware_into_buf(const struct linuxkpi_firmware **, + const char *, struct device *, uint8_t *, size_t, size_t); static __inline int @@ -100,6 +101,16 @@ release_firmware(const struct linuxkpi_firmware *fw) linuxkpi_release_firmware(fw); } +static inline int +request_partial_firmware_into_buf(const struct linuxkpi_firmware **fw, + const char *fw_name, struct device *dev, void *buf, size_t buflen, + size_t offset) +{ + + return (linuxkpi_request_partial_firmware_into_buf(fw, fw_name, + dev, buf, buflen, offset)); +} + #define firmware linuxkpi_firmware #endif /* _LINUXKPI_LINUX_FIRMWARE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h index a21c140d5a9b..f1568ad6282d 100644 --- a/sys/compat/linuxkpi/common/include/linux/fs.h +++ b/sys/compat/linuxkpi/common/include/linux/fs.h @@ -25,13 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_FS_H_ #define _LINUXKPI_LINUX_FS_H_ -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/systm.h> #include <sys/conf.h> @@ -45,6 +42,8 @@ #include <linux/dcache.h> #include <linux/capability.h> #include <linux/wait_bit.h> +#include <linux/kernel.h> +#include <linux/mutex.h> struct module; struct kiocb; @@ -151,6 +150,11 @@ struct file_operations { * an illegal seek error */ off_t (*llseek)(struct linux_file *, off_t, int); +/* + * Not supported in FreeBSD. That's ok, we never call it and it allows some + * drivers like DRM drivers to compile without changes. + */ + void (*show_fdinfo)(struct seq_file *, struct file *); #if 0 /* We do not support these methods. Don't permit them to compile. */ loff_t (*llseek)(struct file *, loff_t, int); @@ -250,6 +254,7 @@ nonseekable_open(struct inode *inode, struct file *filp) static inline int simple_open(struct inode *inode, struct file *filp) { + filp->private_data = inode->i_private; return 0; } @@ -264,12 +269,18 @@ get_file(struct linux_file *f) return (f); } +struct linux_file * linux_get_file_rcu(struct linux_file **f); +struct linux_file * get_file_active(struct linux_file **f); +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION < 60700 static inline bool get_file_rcu(struct linux_file *f) { return (refcount_acquire_if_not_zero( f->_file == NULL ? &f->f_count : &f->_file->f_count)); } +#else +#define get_file_rcu(f) linux_get_file_rcu(f) +#endif static inline struct inode * igrab(struct inode *inode) @@ -298,6 +309,18 @@ no_llseek(struct file *file, loff_t offset, int whence) } static inline loff_t +default_llseek(struct file *file, loff_t offset, int whence) +{ + return (no_llseek(file, offset, whence)); +} + +static inline loff_t +generic_file_llseek(struct file *file, loff_t offset, int whence) +{ + return (no_llseek(file, offset, whence)); +} + +static inline loff_t noop_llseek(struct linux_file *file, loff_t offset, int whence) { @@ -318,4 +341,85 @@ call_mmap(struct linux_file *file, struct vm_area_struct *vma) return (file->f_op->mmap(file, vma)); } +static inline void +i_size_write(struct inode *inode, loff_t i_size) +{ +} + +/* + * simple_read_from_buffer: copy data from kernel-space origin + * buffer into user-space destination buffer + * + * @dest: destination buffer + * @read_size: number of bytes to be transferred + * @ppos: starting transfer position pointer + * @orig: origin buffer + * @buf_size: size of destination and origin buffers + * + * Return value: + * On success, total bytes copied with *ppos incremented accordingly. + * On failure, negative value. + */ +static inline ssize_t +simple_read_from_buffer(void __user *dest, size_t read_size, loff_t *ppos, + void *orig, size_t buf_size) +{ + void *p, *read_pos = ((char *) orig) + *ppos; + size_t buf_remain = buf_size - *ppos; + + if (buf_remain < 0 || buf_remain > buf_size) + return -EINVAL; + + if (read_size > buf_remain) + read_size = buf_remain; + + /* + * XXX At time of commit only debugfs consumers could be + * identified. If others will use this function we may + * have to revise this: normally we would call copy_to_user() + * here but lindebugfs will return the result and the + * copyout is done elsewhere for us. + */ + p = memcpy(dest, read_pos, read_size); + if (p != NULL) + *ppos += read_size; + + return (read_size); +} + +MALLOC_DECLARE(M_LSATTR); + +#define __DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt, __wrfunc)\ +static inline int \ +__fops ## _open(struct inode *inode, struct file *filp) \ +{ \ + return (simple_attr_open(inode, filp, __get, __set, __fmt)); \ +} \ +static const struct file_operations __fops = { \ + .owner = THIS_MODULE, \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = simple_attr_read, \ + .write = __wrfunc, \ + .llseek = no_llseek \ +} + +#define DEFINE_SIMPLE_ATTRIBUTE(fops, get, set, fmt) \ + __DEFINE_SIMPLE_ATTRIBUTE(fops, get, set, fmt, simple_attr_write) +#define DEFINE_SIMPLE_ATTRIBUTE_SIGNED(fops, get, set, fmt) \ + __DEFINE_SIMPLE_ATTRIBUTE(fops, get, set, fmt, simple_attr_write_signed) + +int simple_attr_open(struct inode *inode, struct file *filp, + int (*get)(void *, uint64_t *), int (*set)(void *, uint64_t), + const char *fmt); + +int simple_attr_release(struct inode *inode, struct file *filp); + +ssize_t simple_attr_read(struct file *filp, char *buf, size_t read_size, loff_t *ppos); + +ssize_t simple_attr_write(struct file *filp, const char *buf, size_t write_size, loff_t *ppos); + +ssize_t simple_attr_write_signed(struct file *filp, const char *buf, + size_t write_size, loff_t *ppos); + #endif /* _LINUXKPI_LINUX_FS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/fwnode.h b/sys/compat/linuxkpi/common/include/linux/fwnode.h new file mode 100644 index 000000000000..a1fbc1b6d6a3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/fwnode.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_FWNODE_H_ +#define _LINUXKPI_LINUX_FWNODE_H_ + +struct fwnode_handle { + struct fwnode_handle *secondary; +}; + +#endif /* _LINUXKPI_LINUX_FWNODE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/gcd.h b/sys/compat/linuxkpi/common/include/linux/gcd.h index 40523bd6cba6..5ca0540e5102 100644 --- a/sys/compat/linuxkpi/common/include/linux/gcd.h +++ b/sys/compat/linuxkpi/common/include/linux/gcd.h @@ -25,8 +25,6 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_GCD_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/gfp.h b/sys/compat/linuxkpi/common/include/linux/gfp.h index 6273fa969db8..4c4caa621789 100644 --- a/sys/compat/linuxkpi/common/include/linux/gfp.h +++ b/sys/compat/linuxkpi/common/include/linux/gfp.h @@ -25,13 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_GFP_H_ #define _LINUXKPI_LINUX_GFP_H_ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/systm.h> #include <sys/malloc.h> @@ -46,7 +43,7 @@ #define __GFP_NOWARN 0 #define __GFP_HIGHMEM 0 #define __GFP_ZERO M_ZERO -#define __GFP_NORETRY 0 +#define __GFP_NOMEMALLOC 0 #define __GFP_RECLAIM 0 #define __GFP_RECLAIMABLE 0 #define __GFP_RETRY_MAYFAIL 0 @@ -59,7 +56,8 @@ #define __GFP_KSWAPD_RECLAIM 0 #define __GFP_WAIT M_WAITOK #define __GFP_DMA32 (1U << 24) /* LinuxKPI only */ -#define __GFP_BITS_SHIFT 25 +#define __GFP_NORETRY (1U << 25) /* LinuxKPI only */ +#define __GFP_BITS_SHIFT 26 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1) #define __GFP_NOFAIL M_WAITOK @@ -71,6 +69,7 @@ #define GFP_HIGHUSER_MOVABLE M_WAITOK #define GFP_IOFS M_NOWAIT #define GFP_NOIO M_NOWAIT +#define GFP_NOFS M_NOWAIT #define GFP_DMA32 __GFP_DMA32 #define GFP_TEMPORARY M_NOWAIT #define GFP_NATIVE_MASK (M_NOWAIT | M_WAITOK | M_USE_RESERVE | M_ZERO) @@ -80,20 +79,19 @@ CTASSERT((__GFP_DMA32 & GFP_NATIVE_MASK) == 0); CTASSERT((__GFP_BITS_MASK & GFP_NATIVE_MASK) == GFP_NATIVE_MASK); -/* - * Resolve a page into a virtual address: - * - * NOTE: This function only works for pages allocated by the kernel. - */ -extern void *linux_page_address(struct page *); - -#define page_address(page) linux_page_address(page) +struct page_frag_cache { + void *va; + int pagecnt_bias; +}; /* * Page management for unmapped pages: */ -extern vm_page_t linux_alloc_pages(gfp_t flags, unsigned int order); -extern void linux_free_pages(vm_page_t page, unsigned int order); +struct page *linux_alloc_pages(gfp_t flags, unsigned int order); +void linux_free_pages(struct page *page, unsigned int order); +void *linuxkpi_page_frag_alloc(struct page_frag_cache *, size_t, gfp_t); +void linuxkpi_page_frag_free(void *); +void linuxkpi__page_frag_cache_drain(struct page *, size_t); static inline struct page * alloc_page(gfp_t flags) @@ -130,11 +128,19 @@ __free_page(struct page *page) linux_free_pages(page, 0); } +static inline struct page * +dev_alloc_pages(unsigned int order) +{ + return (linux_alloc_pages(GFP_ATOMIC, order)); +} + +struct folio *folio_alloc(gfp_t gfp, unsigned int order); + /* * Page management for mapped pages: */ -extern vm_offset_t linux_alloc_kmem(gfp_t flags, unsigned int order); -extern void linux_free_kmem(vm_offset_t, unsigned int order); +vm_offset_t linux_alloc_kmem(gfp_t flags, unsigned int order); +void linux_free_kmem(vm_offset_t, unsigned int order); static inline vm_offset_t get_zeroed_page(gfp_t flags) @@ -175,6 +181,27 @@ free_page(uintptr_t addr) linux_free_kmem(addr, 0); } +static inline void * +page_frag_alloc(struct page_frag_cache *pfc, size_t fragsz, gfp_t gfp) +{ + + return (linuxkpi_page_frag_alloc(pfc, fragsz, gfp)); +} + +static inline void +page_frag_free(void *addr) +{ + + linuxkpi_page_frag_free(addr); +} + +static inline void +__page_frag_cache_drain(struct page *page, size_t count) +{ + + linuxkpi__page_frag_cache_drain(page, count); +} + static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) { diff --git a/sys/compat/linuxkpi/common/include/linux/gpf.h b/sys/compat/linuxkpi/common/include/linux/gpf.h new file mode 100644 index 000000000000..01e883a94728 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/gpf.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_GPF_H_ +#define _LINUXKPI_LINUX_GPF_H_ + +#include <linux/mmzone.h> + +#endif /* _LINUXKPI_LINUX_GPF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/hardirq.h b/sys/compat/linuxkpi/common/include/linux/hardirq.h index 07f00f076860..f79451dd0d35 100644 --- a/sys/compat/linuxkpi/common/include/linux/hardirq.h +++ b/sys/compat/linuxkpi/common/include/linux/hardirq.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_HARDIRQ_H_ #define _LINUXKPI_LINUX_HARDIRQ_H_ @@ -40,4 +38,14 @@ #define synchronize_irq(irq) _intr_drain((irq)) +/* + * FIXME: In the i915 driver's `intel_engine_cs.c` file, + * `synchronize_hardirq()` was replaced by `synchronize_rcu()` with the + * following comment: + * "Is it enough to wait that all cpu have context-switched?" + * + * See commit f6d50b7af554e21c380486d6f41c8537b265c777 in drm-kmod. + */ +#define synchronize_hardirq(irq) _intr_drain((irq)) + #endif /* _LINUXKPI_LINUX_HARDIRQ_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/hashtable.h b/sys/compat/linuxkpi/common/include/linux/hashtable.h index a7a30143a58e..55755c354959 100644 --- a/sys/compat/linuxkpi/common/include/linux/hashtable.h +++ b/sys/compat/linuxkpi/common/include/linux/hashtable.h @@ -23,8 +23,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_HASHTABLE_H @@ -94,8 +92,6 @@ __hash_node_type_assert(struct hlist_node *node) #define hash_add_rcu(ht, node, key) do { \ struct lkpi_hash_head *__head = &(ht)[hash_min(key, HASH_BITS(ht))]; \ __hash_node_type_assert(node); \ - KASSERT(((struct lkpi_hash_entry *)(node))->entry.cle_prev == NULL, \ - ("node is already on list or was not zeroed")); \ CK_LIST_INSERT_HEAD(&__head->head, \ (struct lkpi_hash_entry *)(node), entry); \ } while (0) diff --git a/sys/compat/linuxkpi/common/include/linux/hdmi.h b/sys/compat/linuxkpi/common/include/linux/hdmi.h new file mode 100644 index 000000000000..e07578167d69 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/hdmi.h @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LINUX_HDMI_H_ +#define __LINUX_HDMI_H_ + +#include <linux/types.h> +#include <linux/device.h> + +enum hdmi_packet_type { + HDMI_PACKET_TYPE_NULL = 0x00, + HDMI_PACKET_TYPE_AUDIO_CLOCK_REGEN = 0x01, + HDMI_PACKET_TYPE_AUDIO_SAMPLE = 0x02, + HDMI_PACKET_TYPE_GENERAL_CONTROL = 0x03, + HDMI_PACKET_TYPE_ACP = 0x04, + HDMI_PACKET_TYPE_ISRC1 = 0x05, + HDMI_PACKET_TYPE_ISRC2 = 0x06, + HDMI_PACKET_TYPE_ONE_BIT_AUDIO_SAMPLE = 0x07, + HDMI_PACKET_TYPE_DST_AUDIO = 0x08, + HDMI_PACKET_TYPE_HBR_AUDIO_STREAM = 0x09, + HDMI_PACKET_TYPE_GAMUT_METADATA = 0x0a, + /* + enum hdmi_infoframe_type */ +}; + +enum hdmi_infoframe_type { + HDMI_INFOFRAME_TYPE_VENDOR = 0x81, + HDMI_INFOFRAME_TYPE_AVI = 0x82, + HDMI_INFOFRAME_TYPE_SPD = 0x83, + HDMI_INFOFRAME_TYPE_AUDIO = 0x84, + HDMI_INFOFRAME_TYPE_DRM = 0x87, +}; + +#define HDMI_IEEE_OUI 0x000c03 +#define HDMI_FORUM_IEEE_OUI 0xc45dd8 +#define HDMI_INFOFRAME_HEADER_SIZE 4 +#define HDMI_AVI_INFOFRAME_SIZE 13 +#define HDMI_SPD_INFOFRAME_SIZE 25 +#define HDMI_AUDIO_INFOFRAME_SIZE 10 +#define HDMI_DRM_INFOFRAME_SIZE 26 +#define HDMI_VENDOR_INFOFRAME_SIZE 4 + +#define HDMI_INFOFRAME_SIZE(type) \ + (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) + +struct hdmi_any_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; +}; + +enum hdmi_colorspace { + HDMI_COLORSPACE_RGB, + HDMI_COLORSPACE_YUV422, + HDMI_COLORSPACE_YUV444, + HDMI_COLORSPACE_YUV420, + HDMI_COLORSPACE_RESERVED4, + HDMI_COLORSPACE_RESERVED5, + HDMI_COLORSPACE_RESERVED6, + HDMI_COLORSPACE_IDO_DEFINED, +}; + +enum hdmi_scan_mode { + HDMI_SCAN_MODE_NONE, + HDMI_SCAN_MODE_OVERSCAN, + HDMI_SCAN_MODE_UNDERSCAN, + HDMI_SCAN_MODE_RESERVED, +}; + +enum hdmi_colorimetry { + HDMI_COLORIMETRY_NONE, + HDMI_COLORIMETRY_ITU_601, + HDMI_COLORIMETRY_ITU_709, + HDMI_COLORIMETRY_EXTENDED, +}; + +enum hdmi_picture_aspect { + HDMI_PICTURE_ASPECT_NONE, + HDMI_PICTURE_ASPECT_4_3, + HDMI_PICTURE_ASPECT_16_9, + HDMI_PICTURE_ASPECT_64_27, + HDMI_PICTURE_ASPECT_256_135, + HDMI_PICTURE_ASPECT_RESERVED, +}; + +enum hdmi_active_aspect { + HDMI_ACTIVE_ASPECT_16_9_TOP = 2, + HDMI_ACTIVE_ASPECT_14_9_TOP = 3, + HDMI_ACTIVE_ASPECT_16_9_CENTER = 4, + HDMI_ACTIVE_ASPECT_PICTURE = 8, + HDMI_ACTIVE_ASPECT_4_3 = 9, + HDMI_ACTIVE_ASPECT_16_9 = 10, + HDMI_ACTIVE_ASPECT_14_9 = 11, + HDMI_ACTIVE_ASPECT_4_3_SP_14_9 = 13, + HDMI_ACTIVE_ASPECT_16_9_SP_14_9 = 14, + HDMI_ACTIVE_ASPECT_16_9_SP_4_3 = 15, +}; + +enum hdmi_extended_colorimetry { + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601, + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709, + HDMI_EXTENDED_COLORIMETRY_S_YCC_601, + HDMI_EXTENDED_COLORIMETRY_OPYCC_601, + HDMI_EXTENDED_COLORIMETRY_OPRGB, + + /* The following EC values are only defined in CEA-861-F. */ + HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM, + HDMI_EXTENDED_COLORIMETRY_BT2020, + HDMI_EXTENDED_COLORIMETRY_RESERVED, +}; + +enum hdmi_quantization_range { + HDMI_QUANTIZATION_RANGE_DEFAULT, + HDMI_QUANTIZATION_RANGE_LIMITED, + HDMI_QUANTIZATION_RANGE_FULL, + HDMI_QUANTIZATION_RANGE_RESERVED, +}; + +/* non-uniform picture scaling */ +enum hdmi_nups { + HDMI_NUPS_UNKNOWN, + HDMI_NUPS_HORIZONTAL, + HDMI_NUPS_VERTICAL, + HDMI_NUPS_BOTH, +}; + +enum hdmi_ycc_quantization_range { + HDMI_YCC_QUANTIZATION_RANGE_LIMITED, + HDMI_YCC_QUANTIZATION_RANGE_FULL, +}; + +enum hdmi_content_type { + HDMI_CONTENT_TYPE_GRAPHICS, + HDMI_CONTENT_TYPE_PHOTO, + HDMI_CONTENT_TYPE_CINEMA, + HDMI_CONTENT_TYPE_GAME, +}; + +enum hdmi_metadata_type { + HDMI_STATIC_METADATA_TYPE1 = 0, +}; + +enum hdmi_eotf { + HDMI_EOTF_TRADITIONAL_GAMMA_SDR, + HDMI_EOTF_TRADITIONAL_GAMMA_HDR, + HDMI_EOTF_SMPTE_ST2084, + HDMI_EOTF_BT_2100_HLG, +}; + +struct hdmi_avi_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + bool itc; + unsigned char pixel_repeat; + enum hdmi_colorspace colorspace; + enum hdmi_scan_mode scan_mode; + enum hdmi_colorimetry colorimetry; + enum hdmi_picture_aspect picture_aspect; + enum hdmi_active_aspect active_aspect; + enum hdmi_extended_colorimetry extended_colorimetry; + enum hdmi_quantization_range quantization_range; + enum hdmi_nups nups; + unsigned char video_code; + enum hdmi_ycc_quantization_range ycc_quantization_range; + enum hdmi_content_type content_type; + unsigned short top_bar; + unsigned short bottom_bar; + unsigned short left_bar; + unsigned short right_bar; +}; + +/* DRM Infoframe as per CTA 861.G spec */ +struct hdmi_drm_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + enum hdmi_eotf eotf; + enum hdmi_metadata_type metadata_type; + struct { + u16 x, y; + } display_primaries[3]; + struct { + u16 x, y; + } white_point; + u16 max_display_mastering_luminance; + u16 min_display_mastering_luminance; + u16 max_cll; + u16 max_fall; +}; + +void hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame); +ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame, + void *buffer, size_t size); +int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame); +int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame); +ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame, + void *buffer, size_t size); +int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame); +int hdmi_drm_infoframe_unpack_only(struct hdmi_drm_infoframe *frame, + const void *buffer, size_t size); + +enum hdmi_spd_sdi { + HDMI_SPD_SDI_UNKNOWN, + HDMI_SPD_SDI_DSTB, + HDMI_SPD_SDI_DVDP, + HDMI_SPD_SDI_DVHS, + HDMI_SPD_SDI_HDDVR, + HDMI_SPD_SDI_DVC, + HDMI_SPD_SDI_DSC, + HDMI_SPD_SDI_VCD, + HDMI_SPD_SDI_GAME, + HDMI_SPD_SDI_PC, + HDMI_SPD_SDI_BD, + HDMI_SPD_SDI_SACD, + HDMI_SPD_SDI_HDDVD, + HDMI_SPD_SDI_PMP, +}; + +struct hdmi_spd_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + char vendor[8]; + char product[16]; + enum hdmi_spd_sdi sdi; +}; + +int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame, + const char *vendor, const char *product); +ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_spd_infoframe_pack_only(const struct hdmi_spd_infoframe *frame, + void *buffer, size_t size); +int hdmi_spd_infoframe_check(struct hdmi_spd_infoframe *frame); + +enum hdmi_audio_coding_type { + HDMI_AUDIO_CODING_TYPE_STREAM, + HDMI_AUDIO_CODING_TYPE_PCM, + HDMI_AUDIO_CODING_TYPE_AC3, + HDMI_AUDIO_CODING_TYPE_MPEG1, + HDMI_AUDIO_CODING_TYPE_MP3, + HDMI_AUDIO_CODING_TYPE_MPEG2, + HDMI_AUDIO_CODING_TYPE_AAC_LC, + HDMI_AUDIO_CODING_TYPE_DTS, + HDMI_AUDIO_CODING_TYPE_ATRAC, + HDMI_AUDIO_CODING_TYPE_DSD, + HDMI_AUDIO_CODING_TYPE_EAC3, + HDMI_AUDIO_CODING_TYPE_DTS_HD, + HDMI_AUDIO_CODING_TYPE_MLP, + HDMI_AUDIO_CODING_TYPE_DST, + HDMI_AUDIO_CODING_TYPE_WMA_PRO, + HDMI_AUDIO_CODING_TYPE_CXT, +}; + +enum hdmi_audio_sample_size { + HDMI_AUDIO_SAMPLE_SIZE_STREAM, + HDMI_AUDIO_SAMPLE_SIZE_16, + HDMI_AUDIO_SAMPLE_SIZE_20, + HDMI_AUDIO_SAMPLE_SIZE_24, +}; + +enum hdmi_audio_sample_frequency { + HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM, + HDMI_AUDIO_SAMPLE_FREQUENCY_32000, + HDMI_AUDIO_SAMPLE_FREQUENCY_44100, + HDMI_AUDIO_SAMPLE_FREQUENCY_48000, + HDMI_AUDIO_SAMPLE_FREQUENCY_88200, + HDMI_AUDIO_SAMPLE_FREQUENCY_96000, + HDMI_AUDIO_SAMPLE_FREQUENCY_176400, + HDMI_AUDIO_SAMPLE_FREQUENCY_192000, +}; + +enum hdmi_audio_coding_type_ext { + /* Refer to Audio Coding Type (CT) field in Data Byte 1 */ + HDMI_AUDIO_CODING_TYPE_EXT_CT, + + /* + * The next three CXT values are defined in CEA-861-E only. + * They do not exist in older versions, and in CEA-861-F they are + * defined as 'Not in use'. + */ + HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC, + HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND, + + /* The following CXT values are only defined in CEA-861-F. */ + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC, + HDMI_AUDIO_CODING_TYPE_EXT_DRA, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND = 10, +}; + +struct hdmi_audio_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned char channels; + enum hdmi_audio_coding_type coding_type; + enum hdmi_audio_sample_size sample_size; + enum hdmi_audio_sample_frequency sample_frequency; + enum hdmi_audio_coding_type_ext coding_type_ext; + unsigned char channel_allocation; + unsigned char level_shift_value; + bool downmix_inhibit; + +}; + +int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame); +ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, + void *buffer, size_t size); +ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, + void *buffer, size_t size); +int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame); + +#ifdef __linux__ +struct dp_sdp; +ssize_t +hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame, + struct dp_sdp *sdp, u8 dp_version); +#endif + +enum hdmi_3d_structure { + HDMI_3D_STRUCTURE_INVALID = -1, + HDMI_3D_STRUCTURE_FRAME_PACKING = 0, + HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE, + HDMI_3D_STRUCTURE_LINE_ALTERNATIVE, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL, + HDMI_3D_STRUCTURE_L_DEPTH, + HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH, + HDMI_3D_STRUCTURE_TOP_AND_BOTTOM, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF = 8, +}; + + +struct hdmi_vendor_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned int oui; + u8 vic; + enum hdmi_3d_structure s3d_struct; + unsigned int s3d_ext_data; +}; + +/* HDR Metadata as per 861.G spec */ +struct hdr_static_metadata { + __u8 eotf; + __u8 metadata_type; + __u16 max_cll; + __u16 max_fall; + __u16 min_cll; +}; + +/** + * struct hdr_sink_metadata - HDR sink metadata + * + * Metadata Information read from Sink's EDID + */ +struct hdr_sink_metadata { + /** + * @metadata_type: Static_Metadata_Descriptor_ID. + */ + __u32 metadata_type; + /** + * @hdmi_type1: HDR Metadata Infoframe. + */ + union { + struct hdr_static_metadata hdmi_type1; + }; +}; + +int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame); +ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, + void *buffer, size_t size); +ssize_t hdmi_vendor_infoframe_pack_only(const struct hdmi_vendor_infoframe *frame, + void *buffer, size_t size); +int hdmi_vendor_infoframe_check(struct hdmi_vendor_infoframe *frame); + +union hdmi_vendor_any_infoframe { + struct { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned int oui; + } any; + struct hdmi_vendor_infoframe hdmi; +}; + +/** + * union hdmi_infoframe - overall union of all abstract infoframe representations + * @any: generic infoframe + * @avi: avi infoframe + * @spd: spd infoframe + * @vendor: union of all vendor infoframes + * @audio: audio infoframe + * @drm: Dynamic Range and Mastering infoframe + * + * This is used by the generic pack function. This works since all infoframes + * have the same header which also indicates which type of infoframe should be + * packed. + */ +union hdmi_infoframe { + struct hdmi_any_infoframe any; + struct hdmi_avi_infoframe avi; + struct hdmi_spd_infoframe spd; + union hdmi_vendor_any_infoframe vendor; + struct hdmi_audio_infoframe audio; + struct hdmi_drm_infoframe drm; +}; + +ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_infoframe_pack_only(const union hdmi_infoframe *frame, + void *buffer, size_t size); +int hdmi_infoframe_check(union hdmi_infoframe *frame); +int hdmi_infoframe_unpack(union hdmi_infoframe *frame, + const void *buffer, size_t size); +void hdmi_infoframe_log(const char *level, struct device *dev, + const union hdmi_infoframe *frame); + +#endif /* _DRM_HDMI_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/highmem.h b/sys/compat/linuxkpi/common/include/linux/highmem.h index 53efbec06385..58a9cdcdf60f 100644 --- a/sys/compat/linuxkpi/common/include/linux/highmem.h +++ b/sys/compat/linuxkpi/common/include/linux/highmem.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2010 Isilon Systems, Inc. * Copyright (c) 2016 Matthew Macy (mmacy@mattmacy.io) @@ -43,23 +43,25 @@ #include <vm/vm_page.h> #include <vm/pmap.h> +#include <linux/mm.h> #include <linux/page.h> #define PageHighMem(p) (0) -static inline vm_page_t +static inline struct page * kmap_to_page(void *addr) { + return (virt_to_page(addr)); } static inline void * -kmap(vm_page_t page) +kmap(struct page *page) { struct sf_buf *sf; if (PMAP_HAS_DMAP) { - return ((void *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(page))); + return ((void *)PHYS_TO_DMAP(page_to_phys(page))); } else { sched_pin(); sf = sf_buf_alloc(page, SFB_NOWAIT | SFB_CPUPRIVATE); @@ -72,27 +74,39 @@ kmap(vm_page_t page) } static inline void * -kmap_atomic_prot(vm_page_t page, pgprot_t prot) +kmap_atomic_prot(struct page *page, pgprot_t prot) { vm_memattr_t attr = pgprot2cachemode(prot); if (attr != VM_MEMATTR_DEFAULT) { - vm_page_lock(page); page->flags |= PG_FICTITIOUS; - vm_page_unlock(page); pmap_page_set_memattr(page, attr); } return (kmap(page)); } static inline void * -kmap_atomic(vm_page_t page) +kmap_atomic(struct page *page) { + return (kmap_atomic_prot(page, VM_PROT_ALL)); } +static inline void * +kmap_local_page(struct page *page) +{ + return (kmap(page)); +} + +static inline void * +kmap_local_page_prot(struct page *page, pgprot_t prot) +{ + + return (kmap_atomic_prot(page, prot)); +} + static inline void -kunmap(vm_page_t page) +kunmap(struct page *page) { struct sf_buf *sf; @@ -111,8 +125,46 @@ kunmap(vm_page_t page) static inline void kunmap_atomic(void *vaddr) { + if (!PMAP_HAS_DMAP) kunmap(virt_to_page(vaddr)); } +static inline void +kunmap_local(void *addr) +{ + + kunmap_atomic(addr); +} + +static inline void +memcpy_from_page(char *to, struct page *page, size_t offset, size_t len) +{ + char *from; + + KASSERT(offset + len <= PAGE_SIZE, + ("%s: memcpy from page %p to address %p: " + "offset+len (%zu+%zu) would go beyond page end", + __func__, page, to, offset, len)); + + from = kmap_local_page(page); + memcpy(to, from + offset, len); + kunmap_local(from); +} + +static inline void +memcpy_to_page(struct page *page, size_t offset, const char *from, size_t len) +{ + char *to; + + KASSERT(offset + len <= PAGE_SIZE, + ("%s: memcpy from address %p to page %p: " + "offset+len (%zu+%zu) would go beyond page end", + __func__, from, page, offset, len)); + + to = kmap_local_page(page); + memcpy(to + offset, from, len); + kunmap_local(to); +} + #endif /* _LINUXKPI_LINUX_HIGHMEM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/hrtimer.h b/sys/compat/linuxkpi/common/include/linux/hrtimer.h index 23e707d906b4..88f9487d0b85 100644 --- a/sys/compat/linuxkpi/common/include/linux/hrtimer.h +++ b/sys/compat/linuxkpi/common/include/linux/hrtimer.h @@ -21,8 +21,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_HRTIMER_H_ @@ -32,6 +30,7 @@ #include <sys/_mutex.h> #include <linux/ktime.h> +#include <linux/rbtree.h> #include <linux/timer.h> enum hrtimer_mode { @@ -53,6 +52,7 @@ struct hrtimer { }; #define hrtimer_active(hrtimer) linux_hrtimer_active(hrtimer) +#define hrtimer_try_to_cancel(hrtimer) linux_hrtimer_try_to_cancel(hrtimer) #define hrtimer_cancel(hrtimer) linux_hrtimer_cancel(hrtimer) #define hrtimer_init(hrtimer, clock, mode) do { \ @@ -79,6 +79,7 @@ struct hrtimer { } while (0) bool linux_hrtimer_active(struct hrtimer *); +int linux_hrtimer_try_to_cancel(struct hrtimer *); int linux_hrtimer_cancel(struct hrtimer *); void linux_hrtimer_init(struct hrtimer *); void linux_hrtimer_set_expires(struct hrtimer *, ktime_t); diff --git a/sys/compat/linuxkpi/common/include/linux/i2c.h b/sys/compat/linuxkpi/common/include/linux/i2c.h index 0bb8b470edd7..f24d282586f6 100644 --- a/sys/compat/linuxkpi/common/include/linux/i2c.h +++ b/sys/compat/linuxkpi/common/include/linux/i2c.h @@ -46,6 +46,7 @@ #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0 #define I2C_FUNC_10BIT_ADDR 0 +#define I2C_CLASS_HWMON 0x1 #define I2C_CLASS_DDC 0x8 #define I2C_CLASS_SPD 0x80 @@ -58,6 +59,7 @@ struct i2c_adapter { const struct i2c_lock_operations *lock_ops; const struct i2c_algorithm *algo; + const struct i2c_adapter_quirks *quirks; void *algo_data; int retries; @@ -82,6 +84,29 @@ struct i2c_lock_operations { void (*unlock_bus)(struct i2c_adapter *, unsigned int); }; +struct i2c_adapter_quirks { + uint64_t flags; + int max_num_msgs; + uint16_t max_write_len; + uint16_t max_read_len; + uint16_t max_comb_1st_msg_len; + uint16_t max_comb_2nd_msg_len; +}; + +#define I2C_AQ_COMB BIT(0) +#define I2C_AQ_COMB_WRITE_FIRST BIT(1) +#define I2C_AQ_COMB_READ_SECOND BIT(2) +#define I2C_AQ_COMB_SAME_ADDR BIT(3) +#define I2C_AQ_COMB_WRITE_THEN_READ \ + (I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \ + I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR) +#define I2C_AQ_NO_CLK_STRETCH BIT(4) +#define I2C_AQ_NO_ZERO_LEN_READ BIT(5) +#define I2C_AQ_NO_ZERO_LEN_WRITE BIT(6) +#define I2C_AQ_NO_ZERO_LEN \ + (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE) +#define I2C_AQ_NO_REP_START BIT(7) + int lkpi_i2c_add_adapter(struct i2c_adapter *adapter); int lkpi_i2c_del_adapter(struct i2c_adapter *adapter); @@ -100,7 +125,7 @@ do_i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) retries = adapter->retries == 0 ? 1 : adapter->retries; for (; retries != 0; retries--) { - if (adapter->algo->master_xfer != NULL) + if (adapter->algo != NULL && adapter->algo->master_xfer != NULL) ret = adapter->algo->master_xfer(adapter, msgs, nmsgs); else ret = lkpi_i2cbb_transfer(adapter, msgs, nmsgs); @@ -116,7 +141,7 @@ i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs) { int ret; - if (!adapter->algo) + if (adapter->algo == NULL && adapter->algo_data == NULL) return (-EOPNOTSUPP); if (adapter->lock_ops) diff --git a/sys/compat/linuxkpi/common/include/linux/idr.h b/sys/compat/linuxkpi/common/include/linux/idr.h index 5310fcf9950c..535d8ce07fb4 100644 --- a/sys/compat/linuxkpi/common/include/linux/idr.h +++ b/sys/compat/linuxkpi/common/include/linux/idr.h @@ -25,16 +25,17 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IDR_H_ #define _LINUXKPI_LINUX_IDR_H_ #include <sys/param.h> #include <sys/lock.h> +#include <sys/limits.h> #include <sys/mutex.h> +#include <linux/radix-tree.h> +#include <linux/gpf.h> #include <linux/types.h> #define IDR_BITS 5 @@ -134,6 +135,12 @@ ida_get_new(struct ida *ida, int *p_id) } static inline int +ida_alloc_min(struct ida *ida, unsigned int min, gfp_t gfp) +{ + return (ida_simple_get(ida, min, UINT_MAX, gfp)); +} + +static inline int ida_alloc_max(struct ida *ida, unsigned int max, gfp_t gfp) { diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h index dee8c385464c..3644ef80861b 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-2021 The FreeBSD Foundation + * Copyright (c) 2020-2025 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IEEE80211_H @@ -35,9 +33,18 @@ #include <net80211/ieee80211.h> #include <asm/unaligned.h> +#include <linux/kernel.h> #include <linux/bitops.h> #include <linux/if_ether.h> +/* linux_80211.c */ +extern int linuxkpi_debug_80211; +#ifndef D80211_TODO +#define D80211_TODO 0x1 +#endif +#define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ + printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) + /* 9.4.2.55 Management MIC element (CMAC-256, GMAC-128, and GMAC-256). */ struct ieee80211_mmie_16 { @@ -57,20 +64,22 @@ struct ieee80211_mmie_16 { #define IEEE80211_GCMP_MIC_LEN 16 #define IEEE80211_GCMP_PN_LEN 6 #define IEEE80211_GMAC_PN_LEN 6 +#define IEEE80211_CMAC_PN_LEN 6 #define IEEE80211_MAX_PN_LEN 16 #define IEEE80211_INVAL_HW_QUEUE ((uint8_t)-1) -#define IEEE80211_MAX_AMPDU_BUF_HT 0x40 -#define IEEE80211_MAX_AMPDU_BUF 256 /* for HE? */ +#define IEEE80211_MAX_AMPDU_BUF_HT IEEE80211_AGGR_BAWMAX #define IEEE80211_MAX_AMPDU_BUF_HE 256 +#define IEEE80211_MAX_AMPDU_BUF_EHT 1024 #define IEEE80211_MAX_FRAME_LEN 2352 #define IEEE80211_MAX_DATA_LEN (2300 + IEEE80211_CRC_LEN) #define IEEE80211_MAX_MPDU_LEN_HT_BA 4095 /* 9.3.2.1 Format of Data frames; non-VHT non-DMG STA */ #define IEEE80211_MAX_MPDU_LEN_HT_3839 3839 +#define IEEE80211_MAX_MPDU_LEN_HT_7935 7935 #define IEEE80211_MAX_MPDU_LEN_VHT_3895 3895 #define IEEE80211_MAX_MPDU_LEN_VHT_7991 7991 #define IEEE80211_MAX_MPDU_LEN_VHT_11454 11454 @@ -83,12 +92,18 @@ struct ieee80211_mmie_16 { #define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7f #define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7) +/* 802.11-2016, 9.2.4.5.1, Table 9-6 QoS Control Field */ #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 #define IEEE80211_QOS_CTL_TID_MASK IEEE80211_QOS_TID #define IEEE80211_QOS_CTL_EOSP 0x0010 -#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080 /* 9.2.4.5.1, Table 9-6 QoS Control Field */ +#define IEEE80211_QOS_CTL_A_MSDU_PRESENT 0x0080 +#define IEEE80211_QOS_CTL_ACK_POLICY_MASK 0x0060 +#define IEEE80211_QOS_CTL_ACK_POLICY_NOACK 0x0020 +#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100 -#define IEEE80211_RATE_SHORT_PREAMBLE BIT(0) +enum ieee80211_rate_flags { + IEEE80211_RATE_SHORT_PREAMBLE = BIT(0), +}; enum ieee80211_rate_control_changed_flags { IEEE80211_RC_BW_CHANGED = BIT(0), @@ -103,7 +118,8 @@ enum ieee80211_rate_control_changed_flags { #define IEEE80211_TKIP_ICV_LEN 4 #define IEEE80211_TKIP_IV_LEN 8 /* WEP + KID + EXT */ -#define IEEE80211_VHT_EXT_NSS_BW_CAPABLE (1 << 13) /* assigned to tx_highest */ +/* 802.11-2016, 9.4.2.158.3 Supported VHT-MCS and NSS Set field. */ +#define IEEE80211_VHT_EXT_NSS_BW_CAPABLE (1 << 13) /* part of tx_highest */ #define IEEE80211_VHT_MAX_AMPDU_1024K 7 /* 9.4.2.56.3 A-MPDU Parameters field, Table 9-163 */ @@ -122,21 +138,31 @@ enum wlan_ht_cap_sm_ps { WLAN_HT_CAP_SM_PS_DISABLED, }; -#define WLAN_MAX_KEY_LEN 32 /* TODO FIXME brcmfmac */ -#define WLAN_PMKID_LEN 16 /* TODO FIXME brcmfmac */ - -#define WLAN_KEY_LEN_WEP40 5 -#define WLAN_KEY_LEN_WEP104 13 -#define WLAN_KEY_LEN_CCMP 16 -#define WLAN_KEY_LEN_GCMP_256 32 +#define WLAN_MAX_KEY_LEN 32 +#define WLAN_PMKID_LEN 16 +#define WLAN_PMK_LEN_SUITE_B_192 48 + +enum ieee80211_key_len { + WLAN_KEY_LEN_WEP40 = 5, + WLAN_KEY_LEN_WEP104 = 13, + WLAN_KEY_LEN_TKIP = 32, + WLAN_KEY_LEN_CCMP = 16, + WLAN_KEY_LEN_CCMP_256 = 32, + WLAN_KEY_LEN_GCMP = 16, + WLAN_KEY_LEN_AES_CMAC = 16, + WLAN_KEY_LEN_GCMP_256 = 32, + WLAN_KEY_LEN_BIP_CMAC_256 = 32, + WLAN_KEY_LEN_BIP_GMAC_128 = 16, + WLAN_KEY_LEN_BIP_GMAC_256 = 32, +}; /* 802.11-2020, 9.4.2.55.3, Table 9-185 Subfields of the A-MPDU Parameters field */ enum ieee80211_min_mpdu_start_spacing { IEEE80211_HT_MPDU_DENSITY_NONE = 0, #if 0 IEEE80211_HT_MPDU_DENSITY_XXX = 1, /* 1/4 us */ - IEEE80211_HT_MPDU_DENSITY_YYY = 2, /* 1/2 us */ #endif + IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 us */ IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 us */ IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 us */ IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4us */ @@ -151,6 +177,14 @@ enum ieee80211_min_mpdu_start_spacing { #define IEEE80211_FCTL_STYPE IEEE80211_FC0_SUBTYPE_MASK #define IEEE80211_FCTL_ORDER (IEEE80211_FC1_ORDER << 8) #define IEEE80211_FCTL_PROTECTED (IEEE80211_FC1_PROTECTED << 8) +#define IEEE80211_FCTL_FROMDS (IEEE80211_FC1_DIR_FROMDS << 8) +#define IEEE80211_FCTL_TODS (IEEE80211_FC1_DIR_TODS << 8) +#define IEEE80211_FCTL_MOREFRAGS (IEEE80211_FC1_MORE_FRAG << 8) +#define IEEE80211_FCTL_PM (IEEE80211_FC1_PWR_MGT << 8) + +#define IEEE80211_FTYPE_MGMT IEEE80211_FC0_TYPE_MGT +#define IEEE80211_FTYPE_CTL IEEE80211_FC0_TYPE_CTL +#define IEEE80211_FTYPE_DATA IEEE80211_FC0_TYPE_DATA #define IEEE80211_STYPE_ASSOC_REQ IEEE80211_FC0_SUBTYPE_ASSOC_REQ #define IEEE80211_STYPE_REASSOC_REQ IEEE80211_FC0_SUBTYPE_REASSOC_REQ @@ -158,8 +192,13 @@ enum ieee80211_min_mpdu_start_spacing { #define IEEE80211_STYPE_DISASSOC IEEE80211_FC0_SUBTYPE_DISASSOC #define IEEE80211_STYPE_AUTH IEEE80211_FC0_SUBTYPE_AUTH #define IEEE80211_STYPE_DEAUTH IEEE80211_FC0_SUBTYPE_DEAUTH +#define IEEE80211_STYPE_CTS IEEE80211_FC0_SUBTYPE_CTS +#define IEEE80211_STYPE_RTS IEEE80211_FC0_SUBTYPE_RTS #define IEEE80211_STYPE_ACTION IEEE80211_FC0_SUBTYPE_ACTION -#define IEEE80211_STYPE_QOS_DATA IEEE80211_FC0_SUBTYPE_QOS +#define IEEE80211_STYPE_DATA IEEE80211_FC0_SUBTYPE_DATA +#define IEEE80211_STYPE_QOS_DATA IEEE80211_FC0_SUBTYPE_QOS_DATA +#define IEEE80211_STYPE_QOS_NULLFUNC IEEE80211_FC0_SUBTYPE_QOS_NULL +#define IEEE80211_STYPE_QOS_CFACK 0xd0 /* XXX-BZ reserved? */ #define IEEE80211_NUM_ACS 4 /* net8021::WME_NUM_AC */ @@ -176,11 +215,12 @@ enum ieee80211_min_mpdu_start_spacing { #define IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK 8 /* TODO FIXME ax? */ #define IEEE80211_HE_PPE_THRES_INFO_HEADER_SIZE 16 /* TODO FIXME ax? */ -#define IEEE80211_HT_OP_MODE_PROTECTION 0x03 /* MASK */ -#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0x00 -#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 0x01 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 0x02 -#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 0x03 +/* 802.11-2012, Table 8-130-HT Operation element fields and subfields, HT Protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION IEEE80211_HTINFO_OPMODE /* Mask. */ +#define IEEE80211_HT_OP_MODE_PROTECTION_NONE IEEE80211_HTINFO_OPMODE_PURE /* No protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER IEEE80211_HTINFO_OPMODE_PROTOPT /* Nonmember protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ IEEE80211_HTINFO_OPMODE_HT20PR /* 20 MHz protection */ +#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED IEEE80211_HTINFO_OPMODE_MIXED /* Non-HT mixed */ /* 9.6.13.1, Table 9-342 TDLS Action field values. */ @@ -199,13 +239,19 @@ enum ieee80211_tdls_action_code { /* 11-255 reserved */ }; -/* 9.4.2.27, Table 9-135. Extended Capabilities field. */ +/* 802.11-2020 9.4.2.26, Table 9-153. Extended Capabilities field. */ /* This is split up into octets CAPA1 = octet 1, ... */ #define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2 % 8) #define WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT BIT(22 % 8) +#define WLAN_EXT_CAPA3_TIMING_MEASUREMENT_SUPPORT BIT(23 % 8) #define WLAN_EXT_CAPA8_OPMODE_NOTIF BIT(62 % 8) -#define WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT BIT(5) /* XXX */ -#define WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT BIT(7) /* XXX */ +#define WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB BIT(63 % 8) +#define WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB BIT(64 % 8) +#define WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT BIT(77 % 8) +#define WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT BIT(78 % 8) +#define WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT BIT(79 % 8) + +#define WLAN_EXT_CAPA11_EMA_SUPPORT 0x00 /* XXX TODO FIXME */ /* iwlwifi/mvm/utils:: for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_VI; ac++) */ @@ -225,19 +271,55 @@ enum ieee80211_ac_numbers { #define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE 8 #define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0xf -struct vht_mcs { - uint16_t rx_mcs_map; - uint16_t rx_highest; - uint16_t tx_mcs_map; - uint16_t tx_highest; -}; -struct ieee80211_vht_cap { - struct vht_mcs supp_mcs;; - __le32 vht_cap_info; -}; +/* Define the LinuxKPI names directly to the net80211 ones. */ +#define IEEE80211_HT_CAP_LDPC_CODING IEEE80211_HTCAP_LDPC +#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 IEEE80211_HTCAP_CHWIDTH40 +#define IEEE80211_HT_CAP_SM_PS IEEE80211_HTCAP_SMPS +#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 +#define IEEE80211_HT_CAP_GRN_FLD IEEE80211_HTCAP_GREENFIELD +#define IEEE80211_HT_CAP_SGI_20 IEEE80211_HTCAP_SHORTGI20 +#define IEEE80211_HT_CAP_SGI_40 IEEE80211_HTCAP_SHORTGI40 +#define IEEE80211_HT_CAP_TX_STBC IEEE80211_HTCAP_TXSTBC +#define IEEE80211_HT_CAP_RX_STBC IEEE80211_HTCAP_RXSTBC +#define IEEE80211_HT_CAP_RX_STBC_SHIFT IEEE80211_HTCAP_RXSTBC_S +#define IEEE80211_HT_CAP_MAX_AMSDU IEEE80211_HTCAP_MAXAMSDU +#define IEEE80211_HT_CAP_DSSSCCK40 IEEE80211_HTCAP_DSSSCCK40 +#define IEEE80211_HT_CAP_LSIG_TXOP_PROT IEEE80211_HTCAP_LSIGTXOPPROT + +#define IEEE80211_HT_MCS_TX_DEFINED 0x0001 +#define IEEE80211_HT_MCS_TX_RX_DIFF 0x0002 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0c +#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff +#define IEEE80211_HT_MCS_MASK_LEN 10 + +#define IEEE80211_MLD_MAX_NUM_LINKS 15 +#define IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS 0xf +#define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP 0x0060 +#define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME 1 + +struct ieee80211_mcs_info { + uint8_t rx_mask[IEEE80211_HT_MCS_MASK_LEN]; + uint16_t rx_highest; + uint8_t tx_params; + uint8_t __reserved[3]; +} __packed; + +/* 802.11-2020, 9.4.2.55.1 HT Capabilities element structure */ +struct ieee80211_ht_cap { + uint16_t cap_info; + uint8_t ampdu_params_info; + struct ieee80211_mcs_info mcs; + uint16_t extended_ht_cap_info; + uint32_t tx_BF_cap_info; + uint8_t antenna_selection_info; +} __packed; #define IEEE80211_HT_MAX_AMPDU_FACTOR 13 +#define IEEE80211_HE_HT_MAX_AMPDU_FACTOR 16 +#define IEEE80211_HE_VHT_MAX_AMPDU_FACTOR 20 +#define IEEE80211_HE_6GHZ_MAX_AMPDU_FACTOR 13 enum ieee80211_ht_max_ampdu_len { IEEE80211_HT_MAX_AMPDU_64K @@ -248,13 +330,14 @@ enum ieee80211_ampdu_mlme_action { IEEE80211_AMPDU_RX_STOP, IEEE80211_AMPDU_TX_OPERATIONAL, IEEE80211_AMPDU_TX_START, - IEEE80211_AMPDU_TX_START_DELAY_ADDBA, - IEEE80211_AMPDU_TX_START_IMMEDIATE, IEEE80211_AMPDU_TX_STOP_CONT, IEEE80211_AMPDU_TX_STOP_FLUSH, IEEE80211_AMPDU_TX_STOP_FLUSH_CONT }; +#define IEEE80211_AMPDU_TX_START_IMMEDIATE 1 +#define IEEE80211_AMPDU_TX_START_DELAY_ADDBA 2 + enum ieee80211_chanctx_switch_mode { CHANCTX_SWMODE_REASSIGN_VIF, CHANCTX_SWMODE_SWAP_CONTEXTS, @@ -266,6 +349,8 @@ enum ieee80211_chanctx_change_flags { IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(2), IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(3), IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(4), + IEEE80211_CHANCTX_CHANGE_PUNCTURING = BIT(5), + IEEE80211_CHANCTX_CHANGE_MIN_DEF = BIT(6), }; enum ieee80211_frame_release_type { @@ -302,19 +387,11 @@ enum ieee80211_smps_mode { /* net80211::IEEE80211_S_* different but represents the state machine. */ /* Note: order here is important! */ enum ieee80211_sta_state { - IEEE80211_STA_NOTEXIST, - IEEE80211_STA_NONE, - IEEE80211_STA_AUTH, - IEEE80211_STA_ASSOC, - IEEE80211_STA_AUTHORIZED, /* 802.1x */ -}; - -enum ieee80211_sta_rx_bw { - IEEE80211_STA_RX_BW_20, - IEEE80211_STA_RX_BW_40, - IEEE80211_STA_RX_BW_80, - IEEE80211_STA_RX_BW_160, - IEEE80211_STA_RX_BW_320, + IEEE80211_STA_NOTEXIST = 0, + IEEE80211_STA_NONE = 1, + IEEE80211_STA_AUTH = 2, + IEEE80211_STA_ASSOC = 3, + IEEE80211_STA_AUTHORIZED = 4, /* 802.1x */ }; enum ieee80211_tx_info_flags { @@ -335,11 +412,24 @@ enum ieee80211_tx_info_flags { IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(13), IEEE80211_TX_CTL_NO_CCK_RATE = BIT(14), IEEE80211_TX_CTL_INJECTED = BIT(15), + IEEE80211_TX_CTL_HW_80211_ENCAP = BIT(16), + IEEE80211_TX_CTL_USE_MINRATE = BIT(17), + IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(18), + IEEE80211_TX_CTL_LDPC = BIT(19), + IEEE80211_TX_CTL_STBC = BIT(20), +} __packed; + +enum ieee80211_tx_status_flags { + IEEE80211_TX_STATUS_ACK_SIGNAL_VALID = BIT(0), }; enum ieee80211_tx_control_flags { /* XXX TODO .. right shift numbers */ IEEE80211_TX_CTRL_PORT_CTRL_PROTO = BIT(0), + IEEE80211_TX_CTRL_PS_RESPONSE = BIT(1), + IEEE80211_TX_CTRL_RATE_INJECT = BIT(2), + IEEE80211_TX_CTRL_DONT_USE_RATE_MASK = BIT(3), + IEEE80211_TX_CTRL_MLO_LINK = 0xF0000000, /* This is IEEE80211_LINK_UNSPECIFIED on the high bits. */ }; enum ieee80211_tx_rate_flags { @@ -354,6 +444,8 @@ enum ieee80211_tx_rate_flags { IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(7), }; +#define IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED -128 + #define IEEE80211_HT_CTL_LEN 4 struct ieee80211_hdr { /* net80211::ieee80211_frame_addr4 */ @@ -375,10 +467,35 @@ struct ieee80211_hdr_3addr { /* net80211::ieee80211_frame */ __le16 seq_ctrl; }; +struct ieee80211_qos_hdr { /* net80211:ieee80211_qosframe */ + __le16 frame_control; + __le16 duration_id; + uint8_t addr1[ETH_ALEN]; + uint8_t addr2[ETH_ALEN]; + uint8_t addr3[ETH_ALEN]; + __le16 seq_ctrl; + __le16 qos_ctrl; +}; + struct ieee80211_vendor_ie { }; -/* 9.3.3.2 Format of Management frames */ +/* 802.11-2020, Table 9-359-Block Ack Action field values */ +enum ieee80211_back { + WLAN_ACTION_ADDBA_REQ = 0, +}; + +enum ieee80211_sa_query { + WLAN_ACTION_SA_QUERY_RESPONSE = 1, +}; + +/* 802.11-2020, Table 9-51-Category values */ +enum ieee80211_category { + WLAN_CATEGORY_BACK = 3, + WLAN_CATEGORY_SA_QUERY = 8, /* net80211::IEEE80211_ACTION_CAT_SA_QUERY */ +}; + +/* 80211-2020 9.3.3.2 Format of Management frames */ struct ieee80211_mgmt { __le16 frame_control; __le16 duration_id; @@ -394,6 +511,12 @@ struct ieee80211_mgmt { uint16_t capab_info; uint8_t variable[0]; } beacon; + /* 9.3.3.5 Association Request frame format */ + struct { + uint16_t capab_info; + uint16_t listen_interval; + uint8_t variable[0]; + } assoc_req; /* 9.3.3.10 Probe Request frame format */ struct { uint8_t variable[0]; @@ -411,6 +534,16 @@ struct ieee80211_mgmt { uint8_t category; /* 9.6.8 Public Action details */ union { + /* 9.6.2.5 TPC Report frame format */ + struct { + uint8_t spec_mgmt; + uint8_t dialog_token; + /* uint32_t tpc_rep_elem:: */ + uint8_t tpc_elem_id; + uint8_t tpc_elem_length; + uint8_t tpc_elem_tx_power; + uint8_t tpc_elem_link_margin; + } tpc_report; /* 9.6.8.33 Fine Timing Measurement frame format */ struct { uint8_t dialog_token; @@ -421,11 +554,39 @@ struct ieee80211_mgmt { uint16_t toa_error; uint8_t variable[0]; } ftm; + /* 802.11-2016, 9.6.5.2 ADDBA Request frame format */ + struct { + uint8_t action_code; + uint8_t dialog_token; + uint16_t capab; + uint16_t timeout; + uint16_t start_seq_num; + /* Optional follows... */ + uint8_t variable[0]; + } addba_req; + /* XXX */ + struct { + uint8_t dialog_token; + } wnm_timing_msr; } u; } action; + DECLARE_FLEX_ARRAY(uint8_t, body); } u; }; +struct ieee80211_cts { /* net80211::ieee80211_frame_cts */ + __le16 frame_control; + __le16 duration; + uint8_t ra[ETH_ALEN]; +} __packed; + +struct ieee80211_rts { /* net80211::ieee80211_frame_rts */ + __le16 frame_control; + __le16 duration; + uint8_t ra[ETH_ALEN]; + uint8_t ta[ETH_ALEN]; +} __packed; + #define MHZ_TO_KHZ(_f) ((_f) * 1000) #define DBI_TO_MBI(_g) ((_g) * 100) #define MBI_TO_DBI(_x) ((_x) / 100) @@ -434,6 +595,8 @@ struct ieee80211_mgmt { #define IEEE80211_SEQ_TO_SN(_seqn) (((_seqn) & IEEE80211_SEQ_SEQ_MASK) >> \ IEEE80211_SEQ_SEQ_SHIFT) +#define IEEE80211_SN_TO_SEQ(_sn) (((_sn) << IEEE80211_SEQ_SEQ_SHIFT) & \ + IEEE80211_SEQ_SEQ_MASK) /* Time unit (TU) to .. See net80211: IEEE80211_DUR_TU */ #define TU_TO_JIFFIES(_tu) (usecs_to_jiffies(_tu) * 1024) @@ -449,17 +612,38 @@ enum ieee80211_eid { WLAN_EID_SUPP_RATES = 1, WLAN_EID_DS_PARAMS = 3, WLAN_EID_TIM = 5, - WLAN_EID_COUNTRY = 7, /* IEEE80211_ELEMID_COUNTRY */ + WLAN_EID_COUNTRY = 7, /* IEEE80211_ELEMID_COUNTRY */ WLAN_EID_REQUEST = 10, + WLAN_EID_QBSS_LOAD = 11, /* IEEE80211_ELEMID_BSSLOAD */ WLAN_EID_CHANNEL_SWITCH = 37, WLAN_EID_MEASURE_REPORT = 39, - WLAN_EID_RSN = 48, /* IEEE80211_ELEMID_RSN */ + WLAN_EID_HT_CAPABILITY = 45, /* IEEE80211_ELEMID_HTCAP */ + WLAN_EID_RSN = 48, /* IEEE80211_ELEMID_RSN */ WLAN_EID_EXT_SUPP_RATES = 50, + WLAN_EID_EXT_NON_INHERITANCE = 56, WLAN_EID_EXT_CHANSWITCH_ANN = 60, + WLAN_EID_MULTIPLE_BSSID = 71, /* IEEE80211_ELEMID_MULTIBSSID */ + WLAN_EID_MULTI_BSSID_IDX = 85, WLAN_EID_EXT_CAPABILITY = 127, - WLAN_EID_VENDOR_SPECIFIC = 221, + WLAN_EID_VHT_CAPABILITY = 191, /* IEEE80211_ELEMID_VHT_CAP */ + WLAN_EID_S1G_TWT = 216, + WLAN_EID_VENDOR_SPECIFIC = 221, /* IEEE80211_ELEMID_VENDOR */ +}; + +enum ieee80211_eid_ext { + WLAN_EID_EXT_HE_CAPABILITY = 35, }; +#define for_each_element(_elem, _data, _len) \ + for (_elem = (const struct element *)(_data); \ + (((const uint8_t *)(_data) + (_len) - (const uint8_t *)_elem) >= sizeof(*_elem)) && \ + (((const uint8_t *)(_data) + (_len) - (const uint8_t *)_elem) >= (sizeof(*_elem) + _elem->datalen)); \ + _elem = (const struct element *)(_elem->data + _elem->datalen)) + +#define for_each_element_id(_elem, _eid, _data, _len) \ + for_each_element(_elem, _data, _len) \ + if (_elem->id == (_eid)) + /* 9.4.1.7, Table 9-45. Reason codes. */ enum ieee80211_reason_code { /* reserved = 0, */ @@ -488,10 +672,10 @@ struct ieee80211_trigger { /* Table 9-29c-Trigger Type subfield encoding */ enum { IEEE80211_TRIGGER_TYPE_BASIC = 0x0, + IEEE80211_TRIGGER_TYPE_MU_BAR = 0x2, #if 0 /* Not seen yet. */ BFRP = 0x1, - MU-BAR = 0x2, MU-RTS = 0x3, BSRP = 0x4, GCR MU-BAR = 0x5, @@ -502,6 +686,120 @@ enum { IEEE80211_TRIGGER_TYPE_MASK = 0xf }; +#define IEEE80211_TRIGGER_ULBW_MASK 0xc0000 +#define IEEE80211_TRIGGER_ULBW_20MHZ 0x0 +#define IEEE80211_TRIGGER_ULBW_40MHZ 0x1 +#define IEEE80211_TRIGGER_ULBW_80MHZ 0x2 +#define IEEE80211_TRIGGER_ULBW_160_80P80MHZ 0x3 + +/* 802.11-2020, Figure 9-687-Control field format; 802.11ax-2021 */ +#define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3) +#define IEEE80211_TWT_CONTROL_RX_DISABLED BIT(4) +#define IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT BIT(5) + +/* 802.11-2020, Figure 9-688-Request Type field format; 802.11ax-2021 */ +#define IEEE80211_TWT_REQTYPE_SETUP_CMD (BIT(1) | BIT(2) | BIT(3)) +#define IEEE80211_TWT_REQTYPE_TRIGGER BIT(4) +#define IEEE80211_TWT_REQTYPE_IMPLICIT BIT(5) +#define IEEE80211_TWT_REQTYPE_FLOWTYPE BIT(6) +#define IEEE80211_TWT_REQTYPE_FLOWID (BIT(7) | BIT(8) | BIT(9)) +#define IEEE80211_TWT_REQTYPE_WAKE_INT_EXP (BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14)) +#define IEEE80211_TWT_REQTYPE_PROTECTION BIT(15) + +struct ieee80211_twt_params { + int mantissa, min_twt_dur, twt; + uint16_t req_type; +}; + +struct ieee80211_twt_setup { + int control; + struct ieee80211_twt_params *params; +}; + +/* 802.11-2020, Table 9-297-TWT Setup Command field values */ +enum ieee80211_twt_setup_cmd { + TWT_SETUP_CMD_REQUEST = 0, + TWT_SETUP_CMD_SUGGEST = 1, + /* DEMAND = 2, */ + /* GROUPING = 3, */ + TWT_SETUP_CMD_ACCEPT = 4, + /* ALTERNATE = 5 */ + TWT_SETUP_CMD_DICTATE = 6, + TWT_SETUP_CMD_REJECT = 7, +}; + +struct ieee80211_bssid_index { + int bssid_index; +}; + +enum ieee80211_ap_reg_power { + IEEE80211_REG_UNSET_AP, + IEEE80211_REG_LPI_AP, + IEEE80211_REG_SP_AP, + IEEE80211_REG_VLP_AP, +}; + +/* + * 802.11ax-2021, Table 9-277-Meaning of Maximum Transmit Power Count subfield + * if Maximum Transmit Power Interpretation subfield is 1 or 3 + */ +#define IEEE80211_MAX_NUM_PWR_LEVEL 8 + +/* + * 802.11ax-2021, Table 9-275a-Maximum Transmit Power Interpretation subfield + * encoding (4) * Table E-12-Regulatory Info subfield encoding in the + * United States (2) + */ +#define IEEE80211_TPE_MAX_IE_NUM 8 + +/* 802.11ax-2021, 9.4.2.161 Transmit Power Envelope element */ +struct ieee80211_tx_pwr_env { + uint8_t tx_power_info; + uint8_t tx_power[IEEE80211_MAX_NUM_PWR_LEVEL]; +}; + +/* 802.11ax-2021, Figure 9-617-Transmit Power Information field format */ +/* These are field masks (3bit/3bit/2bit). */ +#define IEEE80211_TX_PWR_ENV_INFO_COUNT 0x07 +#define IEEE80211_TX_PWR_ENV_INFO_INTERPRET 0x38 +#define IEEE80211_TX_PWR_ENV_INFO_CATEGORY 0xc0 + +/* + * 802.11ax-2021, Table 9-275a-Maximum Transmit Power Interpretation subfield + * encoding + */ +enum ieee80211_tx_pwr_interpretation_subfield_enc { + IEEE80211_TPE_LOCAL_EIRP, + IEEE80211_TPE_LOCAL_EIRP_PSD, + IEEE80211_TPE_REG_CLIENT_EIRP, + IEEE80211_TPE_REG_CLIENT_EIRP_PSD, +}; + +enum ieee80211_tx_pwr_category_6ghz { + IEEE80211_TPE_CAT_6GHZ_DEFAULT, +}; + +/* 802.11-2020, 9.4.2.27 BSS Load element */ +struct ieee80211_bss_load_elem { + uint16_t sta_count; + uint8_t channel_util; + uint16_t avail_adm_capa; +}; + +struct ieee80211_p2p_noa_desc { + uint32_t count; /* uint8_t ? */ + uint32_t duration; + uint32_t interval; + uint32_t start_time; +}; + +struct ieee80211_p2p_noa_attr { + uint8_t index; + uint8_t oppps_ctwindow; + struct ieee80211_p2p_noa_desc desc[4]; +}; + + /* net80211: IEEE80211_IS_CTL() */ static __inline bool ieee80211_is_ctl(__le16 fc) @@ -532,9 +830,8 @@ ieee80211_is_data_qos(__le16 fc) { __le16 v; - fc &= htole16(IEEE80211_FC0_SUBTYPE_QOS | IEEE80211_FC0_TYPE_MASK | - IEEE80211_FC0_VERSION_MASK); - v = htole16(IEEE80211_FC0_QOSDATA); + fc &= htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | IEEE80211_FC0_TYPE_DATA); return (fc == v); } @@ -574,9 +871,9 @@ ieee80211_hdrlen(__le16 fc) if ((fc & htole16(IEEE80211_FC1_DIR_MASK << 8)) == htole16(IEEE80211_FC1_DIR_DSTODS << 8)) size += IEEE80211_ADDR_LEN; - if ((fc & htole16(IEEE80211_FC0_SUBTYPE_QOS | + if ((fc & htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | IEEE80211_FC0_TYPE_MASK)) == - htole16(IEEE80211_FC0_SUBTYPE_QOS | + htole16(IEEE80211_FC0_SUBTYPE_QOS_DATA | IEEE80211_FC0_TYPE_DATA)) size += sizeof(uint16_t); } @@ -603,4 +900,346 @@ ieee80211_is_trigger(__le16 fc) return (fc == v); } +static __inline bool +ieee80211_is_action(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_ACTION | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_probe_resp(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_PROBE_RESP | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_auth(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_AUTH | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_assoc_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_ASSOC_REQ | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_assoc_resp(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_ASSOC_RESP | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_reassoc_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_REASSOC_REQ | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_reassoc_resp(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_REASSOC_RESP | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_disassoc(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_DISASSOC | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_data_present(__le16 fc) +{ + __le16 v; + + /* If it is a data frame and NODATA is not present. */ + fc &= htole16(IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_NODATA); + v = htole16(IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +static __inline bool +ieee80211_is_deauth(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_DEAUTH | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_is_beacon(__le16 fc) +{ + __le16 v; + + /* + * For as much as I get it this comes in LE and unlike FreeBSD + * where we get the entire frame header and u8[], here we get the + * 9.2.4.1 Frame Control field only. Mask and compare. + */ + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_BEACON | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + + +static __inline bool +ieee80211_is_probe_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_PROBE_REQ | IEEE80211_FC0_TYPE_MGT); + + return (fc == v); +} + +static __inline bool +ieee80211_has_protected(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_PROTECTED << 8)); +} + +static __inline bool +ieee80211_is_back_req(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_BAR | IEEE80211_FC0_TYPE_CTL); + + return (fc == v); +} + +static __inline bool +ieee80211_is_bufferable_mmpdu(struct sk_buff *skb) +{ + struct ieee80211_mgmt *mgmt; + __le16 fc; + + mgmt = (struct ieee80211_mgmt *)skb->data; + fc = mgmt->frame_control; + + /* 11.2.2 Bufferable MMPDUs, 80211-2020. */ + /* XXX we do not care about IBSS yet. */ + + if (!ieee80211_is_mgmt(fc)) + return (false); + if (ieee80211_is_action(fc)) /* XXX FTM? */ + return (true); /* XXX false? */ + if (ieee80211_is_disassoc(fc)) + return (true); + if (ieee80211_is_deauth(fc)) + return (true); + + TODO(); + + return (false); +} + +static __inline bool +ieee80211_is_nullfunc(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_NODATA | IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +static __inline bool +ieee80211_is_qos_nullfunc(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_QOS_NULL | IEEE80211_FC0_TYPE_DATA); + + return (fc == v); +} + +static __inline bool +ieee80211_is_any_nullfunc(__le16 fc) +{ + + return (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)); +} + +static inline bool +ieee80211_is_pspoll(__le16 fc) +{ + __le16 v; + + fc &= htole16(IEEE80211_FC0_SUBTYPE_MASK | IEEE80211_FC0_TYPE_MASK); + v = htole16(IEEE80211_FC0_SUBTYPE_PS_POLL | IEEE80211_FC0_TYPE_CTL); + + return (fc == v); +} + +static __inline bool +ieee80211_has_a4(__le16 fc) +{ + __le16 v; + + fc &= htole16((IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_DIR_FROMDS) << 8); + v = htole16((IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_DIR_FROMDS) << 8); + + return (fc == v); +} + +static __inline bool +ieee80211_has_order(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_ORDER << 8)); +} + +static __inline bool +ieee80211_has_retry(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_RETRY << 8)); +} + + +static __inline bool +ieee80211_has_fromds(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_DIR_FROMDS << 8)); +} + +static __inline bool +ieee80211_has_tods(__le16 fc) +{ + + return (fc & htole16(IEEE80211_FC1_DIR_TODS << 8)); +} + +static __inline uint8_t * +ieee80211_get_SA(struct ieee80211_hdr *hdr) +{ + + if (ieee80211_has_a4(hdr->frame_control)) + return (hdr->addr4); + if (ieee80211_has_fromds(hdr->frame_control)) + return (hdr->addr3); + return (hdr->addr2); +} + +static __inline uint8_t * +ieee80211_get_DA(struct ieee80211_hdr *hdr) +{ + + if (ieee80211_has_tods(hdr->frame_control)) + return (hdr->addr3); + return (hdr->addr1); +} + +static __inline bool +ieee80211_is_frag(struct ieee80211_hdr *hdr) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_first_frag(__le16 fc) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_ftm(struct sk_buff *skb) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_is_timing_measurement(struct sk_buff *skb) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_has_pm(__le16 fc) +{ + TODO(); + return (false); +} + +static __inline bool +ieee80211_has_morefrags(__le16 fc) +{ + + fc &= htole16(IEEE80211_FC1_MORE_FRAG << 8); + return (fc != 0); +} + +static __inline u8 * +ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr) +{ + if (ieee80211_has_a4(hdr->frame_control)) + return (u8 *)hdr + 30; + else + return (u8 *)hdr + 24; +} + #endif /* _LINUXKPI_LINUX_IEEE80211_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/if_arp.h b/sys/compat/linuxkpi/common/include/linux/if_arp.h index abd30eac49c9..6201c3a1c284 100644 --- a/sys/compat/linuxkpi/common/include/linux/if_arp.h +++ b/sys/compat/linuxkpi/common/include/linux/if_arp.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IF_ARP_H_ #define _LINUXKPI_LINUX_IF_ARP_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/if_ether.h b/sys/compat/linuxkpi/common/include/linux/if_ether.h index 178b778ec736..6676e8fc142f 100644 --- a/sys/compat/linuxkpi/common/include/linux/if_ether.h +++ b/sys/compat/linuxkpi/common/include/linux/if_ether.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2021-2022 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,13 +29,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IF_ETHER_H_ #define _LINUXKPI_LINUX_IF_ETHER_H_ #include <linux/types.h> +#include <linux/skbuff.h> #include <net/ethernet.h> @@ -55,6 +58,9 @@ #define ETH_P_8021AD ETHERTYPE_QINQ #define ETH_P_PAE ETHERTYPE_PAE #define ETH_P_802_2 ETHERTYPE_8023 +#define ETH_P_IPX ETHERTYPE_IPX +#define ETH_P_AARP ETHERTYPE_AARP +#define ETH_P_802_3_MIN 0x05DD /* See comment in sys/net/ethernet.h */ #define ETH_P_LINK_CTL 0x886C /* ITU-T G.989.2 */ #define ETH_P_TDLS 0x890D /* 802.11z-2010, see wpa. */ @@ -64,4 +70,13 @@ struct ethhdr { uint16_t h_proto; } __packed; +static inline struct ethhdr * +eth_hdr(const struct sk_buff *skb) +{ + struct ethhdr *hdr; + + hdr = (struct ethhdr *)skb_mac_header(skb); + return (hdr); +} + #endif /* _LINUXKPI_LINUX_IF_ETHER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/if_vlan.h b/sys/compat/linuxkpi/common/include/linux/if_vlan.h index 7c5531f6ec11..3d1c61db1882 100644 --- a/sys/compat/linuxkpi/common/include/linux/if_vlan.h +++ b/sys/compat/linuxkpi/common/include/linux/if_vlan.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IF_VLAN_H_ #define _LINUXKPI_LINUX_IF_VLAN_H_ @@ -44,7 +42,7 @@ static inline int is_vlan_dev(struct ifnet *ifp) { - return (ifp->if_type == IFT_L2VLAN); + return (if_gettype(ifp) == IFT_L2VLAN); } static inline uint16_t diff --git a/sys/compat/linuxkpi/common/include/linux/in.h b/sys/compat/linuxkpi/common/include/linux/in.h index ae2be5be1799..5cc92416c7da 100644 --- a/sys/compat/linuxkpi/common/include/linux/in.h +++ b/sys/compat/linuxkpi/common/include/linux/in.h @@ -25,15 +25,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IN_H_ #define _LINUXKPI_LINUX_IN_H_ #include "opt_inet.h" -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/systm.h> #include <netinet/in.h> diff --git a/sys/compat/linuxkpi/common/include/linux/in6.h b/sys/compat/linuxkpi/common/include/linux/in6.h index 5f5f548de06d..79be45b6819a 100644 --- a/sys/compat/linuxkpi/common/include/linux/in6.h +++ b/sys/compat/linuxkpi/common/include/linux/in6.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IN6_H_ #define _LINUXKPI_LINUX_IN6_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/interrupt.h b/sys/compat/linuxkpi/common/include/linux/interrupt.h index 905a29a77f91..dfd9816da8be 100644 --- a/sys/compat/linuxkpi/common/include/linux/interrupt.h +++ b/sys/compat/linuxkpi/common/include/linux/interrupt.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_INTERRUPT_H_ #define _LINUXKPI_LINUX_INTERRUPT_H_ @@ -42,7 +40,12 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); -#define IRQF_SHARED RF_SHAREABLE +#define IRQF_SHARED 0x0004 /* Historically */ +#define IRQF_NOBALANCING 0 + +#define IRQ_DISABLE_UNLAZY 0 + +#define IRQ_NOTCONNECTED (1U << 31) int lkpi_request_irq(struct device *, unsigned int, irq_handler_t, irq_handler_t, unsigned long, const char *, void *); @@ -71,6 +74,14 @@ request_threaded_irq(int irq, irq_handler_t handler, } static inline int +devm_request_irq(struct device *dev, int irq, + irq_handler_t handler, unsigned long flags, const char *name, void *arg) +{ + + return (lkpi_request_irq(dev, irq, handler, NULL, flags, name, arg)); +} + +static inline int devm_request_threaded_irq(struct device *dev, int irq, irq_handler_t handler, irq_handler_t thread_handler, unsigned long flags, const char *name, void *arg) @@ -92,6 +103,12 @@ disable_irq(unsigned int irq) lkpi_disable_irq(irq); } +static inline void +disable_irq_nosync(unsigned int irq) +{ + lkpi_disable_irq(irq); +} + static inline int bind_irq_to_cpu(unsigned int irq, int cpu_id) { @@ -111,7 +128,7 @@ devm_free_irq(struct device *xdev, unsigned int irq, void *p) } static inline int -irq_set_affinity_hint(int vector, cpumask_t *mask) +irq_set_affinity_hint(int vector, const cpumask_t *mask) { int error; @@ -123,10 +140,24 @@ irq_set_affinity_hint(int vector, cpumask_t *mask) return (-error); } +static inline struct msi_desc * +irq_get_msi_desc(unsigned int irq) +{ + + return (lkpi_pci_msi_desc_alloc(irq)); +} + +static inline void +irq_set_status_flags(unsigned int irq __unused, unsigned long flags __unused) +{ +} + /* * LinuxKPI tasklet support */ +struct tasklet_struct; typedef void tasklet_func_t(unsigned long); +typedef void tasklet_callback_t(struct tasklet_struct *); struct tasklet_struct { TAILQ_ENTRY(tasklet_struct) entry; @@ -135,6 +166,8 @@ struct tasklet_struct { volatile u_int tasklet_state; atomic_t count; unsigned long data; + tasklet_callback_t *callback; + bool use_callback; }; #define DECLARE_TASKLET(_name, _func, _data) \ @@ -142,6 +175,11 @@ struct tasklet_struct _name = { .func = (_func), .data = (_data) } #define tasklet_hi_schedule(t) tasklet_schedule(t) +/* Some other compat code in the tree has this defined as well. */ +#define from_tasklet(_dev, _t, _field) \ + container_of(_t, typeof(*(_dev)), _field) + +void tasklet_setup(struct tasklet_struct *, tasklet_callback_t *); extern void tasklet_schedule(struct tasklet_struct *); extern void tasklet_kill(struct tasklet_struct *); extern void tasklet_init(struct tasklet_struct *, tasklet_func_t *, @@ -152,5 +190,6 @@ extern void tasklet_disable_nosync(struct tasklet_struct *); extern int tasklet_trylock(struct tasklet_struct *); extern void tasklet_unlock(struct tasklet_struct *); extern void tasklet_unlock_wait(struct tasklet_struct *ts); +#define tasklet_unlock_spin_wait(ts) tasklet_unlock_wait(ts) #endif /* _LINUXKPI_LINUX_INTERRUPT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/interval_tree.h b/sys/compat/linuxkpi/common/include/linux/interval_tree.h index 3f8e0cb743d9..1eb8a2fb9181 100644 --- a/sys/compat/linuxkpi/common/include/linux/interval_tree.h +++ b/sys/compat/linuxkpi/common/include/linux/interval_tree.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> * diff --git a/sys/compat/linuxkpi/common/include/linux/interval_tree_generic.h b/sys/compat/linuxkpi/common/include/linux/interval_tree_generic.h index 2ee615fda159..3ed6e105cbda 100644 --- a/sys/compat/linuxkpi/common/include/linux/interval_tree_generic.h +++ b/sys/compat/linuxkpi/common/include/linux/interval_tree_generic.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2019 Mark Kettenis <kettenis@OpenBSD.org> * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> diff --git a/sys/compat/linuxkpi/common/include/linux/io-64-nonatomic-lo-hi.h b/sys/compat/linuxkpi/common/include/linux/io-64-nonatomic-lo-hi.h new file mode 100644 index 000000000000..844b3ef171d5 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/io-64-nonatomic-lo-hi.h @@ -0,0 +1,65 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Felix Palmen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _LINUXKPI_LINUX_IO_64_NONATOMIC_LO_HI_H_ +#define _LINUXKPI_LINUX_IO_64_NONATOMIC_LO_HI_H_ + +#include <linux/io.h> + +static inline uint64_t +lo_hi_readq(const volatile void *addr) +{ + const volatile uint32_t *p = addr; + uint32_t l, h; + + __io_br(); + l = le32toh(__raw_readl(p)); + h = le32toh(__raw_readl(p + 1)); + __io_ar(); + + return (l + ((uint64_t)h << 32)); +} + +static inline void +lo_hi_writeq(uint64_t v, volatile void *addr) +{ + volatile uint32_t *p = addr; + + __io_bw(); + __raw_writel(htole32(v), p); + __raw_writel(htole32(v >> 32), p + 1); + __io_aw(); +} + +#ifndef readq +#define readq(addr) lo_hi_readq(addr) +#endif + +#ifndef writeq +#define writeq(v, addr) lo_hi_writeq(v, addr) +#endif + +#endif /* _LINUXKPI_LINUX_IO_64_NONATOMIC_LO_HI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/io-mapping.h b/sys/compat/linuxkpi/common/include/linux/io-mapping.h index 5c24f1ff8659..f5f2fbc5c2cb 100644 --- a/sys/compat/linuxkpi/common/include/linux/io-mapping.h +++ b/sys/compat/linuxkpi/common/include/linux/io-mapping.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IO_MAPPING_H_ @@ -37,6 +35,7 @@ #include <linux/types.h> #include <linux/io.h> +#include <linux/mm.h> #include <linux/slab.h> struct io_mapping { @@ -93,6 +92,18 @@ io_mapping_unmap_atomic(void *vaddr) } static inline void * +io_mapping_map_local_wc(struct io_mapping *mapping, unsigned long offset) +{ + + return (io_mapping_map_atomic_wc(mapping, offset)); +} + +static inline void +io_mapping_unmap_local(void *vaddr __unused) +{ +} + +static inline void * io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset, unsigned long size) { @@ -100,6 +111,17 @@ io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset, return ((char *)mapping->mem + offset); } +int lkpi_io_mapping_map_user(struct io_mapping *iomap, + struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, + unsigned long size); + +static inline int +io_mapping_map_user(struct io_mapping *iomap, struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn, unsigned long size) +{ + return (lkpi_io_mapping_map_user(iomap, vma, addr, pfn, size)); +} + static inline void io_mapping_unmap(void *vaddr) { diff --git a/sys/compat/linuxkpi/common/include/linux/io.h b/sys/compat/linuxkpi/common/include/linux/io.h index 0790e518a1a3..2d6fef4e7c52 100644 --- a/sys/compat/linuxkpi/common/include/linux/io.h +++ b/sys/compat/linuxkpi/common/include/linux/io.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IO_H_ #define _LINUXKPI_LINUX_IO_H_ @@ -37,7 +35,12 @@ #include <machine/vm.h> #include <linux/compiler.h> +#include <linux/err.h> +#include <asm-generic/io.h> #include <linux/types.h> +#if !defined(__arm__) +#include <asm/set_memory.h> +#endif /* * XXX This is all x86 specific. It should be bus space access. @@ -348,6 +351,16 @@ ioread32be(const volatile void *addr) } #define ioread32be(addr) ioread32be(addr) +#ifdef __LP64__ +#undef ioread64 +static inline uint64_t +ioread64(const volatile void *addr) +{ + return (readq(addr)); +} +#define ioread64(addr) ioread64(addr) +#endif + #undef iowrite8 static inline void iowrite8(uint8_t v, volatile void *addr) @@ -383,11 +396,7 @@ iowrite32be(uint32_t v, volatile void *addr) #define iowrite32be(v, addr) iowrite32be(v, addr) #if defined(__i386__) || defined(__amd64__) -static inline void -_outb(u_char data, u_int port) -{ - __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); -} +#define _outb(data, port) outb((data), (port)) #endif #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || defined(__aarch64__) || defined(__riscv) @@ -400,6 +409,13 @@ _ioremap_attr(vm_paddr_t _phys_addr, unsigned long _size, int _attr) } #endif +struct device; +static inline void * +devm_ioremap(struct device *dev, resource_size_t offset, resource_size_t size) +{ + return (NULL); +} + #ifdef VM_MEMATTR_DEVICE #define ioremap_nocache(addr, size) \ _ioremap_attr((addr), (size), VM_MEMATTR_DEVICE) @@ -421,7 +437,7 @@ _ioremap_attr(vm_paddr_t _phys_addr, unsigned long _size, int _attr) #else #define ioremap_wc(addr, size) ioremap_nocache(addr, size) #endif -#define ioremap_wb(addr, size) \ +#define ioremap_cache(addr, size) \ _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_BACK) void iounmap(void *addr); @@ -430,9 +446,9 @@ void iounmap(void *addr); #define memcpy_toio(a, b, c) memcpy((a), (b), (c)) static inline void -__iowrite32_copy(void *to, void *from, size_t count) +__iowrite32_copy(void *to, const void *from, size_t count) { - uint32_t *src; + const uint32_t *src; uint32_t *dst; int i; @@ -441,10 +457,10 @@ __iowrite32_copy(void *to, void *from, size_t count) } static inline void -__iowrite64_copy(void *to, void *from, size_t count) +__iowrite64_copy(void *to, const void *from, size_t count) { #ifdef __LP64__ - uint64_t *src; + const uint64_t *src; uint64_t *dst; int i; @@ -455,6 +471,32 @@ __iowrite64_copy(void *to, void *from, size_t count) #endif } +static inline void +__ioread32_copy(void *to, const void *from, size_t count) +{ + const uint32_t *src; + uint32_t *dst; + int i; + + for (i = 0, src = from, dst = to; i < count; i++, src++, dst++) + *dst = __raw_readl(src); +} + +static inline void +__ioread64_copy(void *to, const void *from, size_t count) +{ +#ifdef __LP64__ + const uint64_t *src; + uint64_t *dst; + int i; + + for (i = 0, src = from, dst = to; i < count; i++, src++, dst++) + *dst = __raw_readq(src); +#else + __ioread32_copy(to, from, count * 2); +#endif +} + enum { MEMREMAP_WB = 1 << 0, MEMREMAP_WT = 1 << 1, @@ -467,7 +509,7 @@ memremap(resource_size_t offset, size_t size, unsigned long flags) void *addr = NULL; if ((flags & MEMREMAP_WB) && - (addr = ioremap_wb(offset, size)) != NULL) + (addr = ioremap_cache(offset, size)) != NULL) goto done; if ((flags & MEMREMAP_WT) && (addr = ioremap_wt(offset, size)) != NULL) @@ -486,6 +528,8 @@ memunmap(void *addr) iounmap(addr); } +#define IOMEM_ERR_PTR(err) (void __iomem *)ERR_PTR(err) + #define __MTRR_ID_BASE 1 int lkpi_arch_phys_wc_add(unsigned long, unsigned long); void lkpi_arch_phys_wc_del(int); @@ -494,4 +538,29 @@ void lkpi_arch_phys_wc_del(int); #define arch_phys_wc_index(x) \ (((x) < __MTRR_ID_BASE) ? -1 : ((x) - __MTRR_ID_BASE)) +static inline int +arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size) +{ +#if defined(__amd64__) + vm_offset_t va; + + va = PHYS_TO_DMAP(start); + return (-pmap_change_attr(va, size, VM_MEMATTR_WRITE_COMBINING)); +#else + return (0); +#endif +} + +static inline void +arch_io_free_memtype_wc(resource_size_t start, resource_size_t size) +{ +#if defined(__amd64__) + vm_offset_t va; + + va = PHYS_TO_DMAP(start); + + pmap_change_attr(va, size, VM_MEMATTR_WRITE_BACK); +#endif +} + #endif /* _LINUXKPI_LINUX_IO_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ioctl.h b/sys/compat/linuxkpi/common/include/linux/ioctl.h index b1b5443fa150..77c01224e6a5 100644 --- a/sys/compat/linuxkpi/common/include/linux/ioctl.h +++ b/sys/compat/linuxkpi/common/include/linux/ioctl.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IOCTL_H_ #define _LINUXKPI_LINUX_IOCTL_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/iommu.h b/sys/compat/linuxkpi/common/include/linux/iommu.h new file mode 100644 index 000000000000..391d9778a0c8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/iommu.h @@ -0,0 +1,29 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_IOMMU_H_ +#define _LINUXKPI_LINUX_IOMMU_H_ + +#include <linux/device.h> + +#define __IOMMU_DOMAIN_PAGING (1U << 0) +#define __IOMMU_DOMAIN_DMA_API (1U << 1) +#define __IOMMU_DOMAIN_PT (1U << 2) +#define __IOMMU_DOMAIN_DMA_FQ (1U << 3) + +#define IOMMU_DOMAIN_BLOCKED (0U) +#define IOMMU_DOMAIN_IDENTITY (__IOMMU_DOMAIN_PT) +#define IOMMU_DOMAIN_UNMANAGED (__IOMMU_DOMAIN_PAGING) +#define IOMMU_DOMAIN_DMA (__IOMMU_DOMAIN_PAGING | __IOMMU_DOMAIN_DMA_API) +#define IOMMU_DOMAIN_DMA_FQ (__IOMMU_DOMAIN_PAGING | __IOMMU_DOMAIN_DMA_API | __IOMMU_DOMAIN_DMA_FQ) + +struct iommu_domain { + unsigned int type; +}; + +static inline struct iommu_domain * +iommu_get_domain_for_dev(struct device *dev __unused) +{ + return (NULL); +} + +#endif /* _LINUXKPI_LINUX_IOMMU_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/iopoll.h b/sys/compat/linuxkpi/common/include/linux/iopoll.h index 478d875c846c..8d0498a26da1 100644 --- a/sys/compat/linuxkpi/common/include/linux/iopoll.h +++ b/sys/compat/linuxkpi/common/include/linux/iopoll.h @@ -23,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IOPOLL_H diff --git a/sys/compat/linuxkpi/common/include/linux/ioport.h b/sys/compat/linuxkpi/common/include/linux/ioport.h new file mode 100644 index 000000000000..444f3ad94602 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ioport.h @@ -0,0 +1,57 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_IOPORT_H +#define _LINUXKPI_LINUX_IOPORT_H + +#include <linux/compiler.h> +#include <linux/types.h> + +#define DEFINE_RES_MEM(_start, _size) \ + (struct resource) { \ + .start = (_start), \ + .end = (_start) + (_size) - 1, \ + } + +struct resource { + resource_size_t start; + resource_size_t end; +}; + +static inline resource_size_t +resource_size(const struct resource *r) +{ + return (r->end - r->start + 1); +} + +static inline bool +resource_contains(struct resource *a, struct resource *b) +{ + return (a->start <= b->start && a->end >= b->end); +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/iosys-map.h b/sys/compat/linuxkpi/common/include/linux/iosys-map.h new file mode 100644 index 000000000000..66c442b8668f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/iosys-map.h @@ -0,0 +1,161 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_IOSYS_MAP_H +#define _LINUXKPI_LINUX_IOSYS_MAP_H + +#include <linux/io.h> +#include <linux/string.h> + +struct iosys_map { + union { + void *vaddr_iomem; + void *vaddr; + }; + bool is_iomem; +#ifdef __OpenBSD__ + bus_space_handle_t bsh; + bus_size_t size; +#endif +}; + +#define IOSYS_MAP_INIT_OFFSET(_ism_src_p, _off) ({ \ + struct iosys_map ism_dst = *(_ism_src_p); \ + iosys_map_incr(&ism_dst, _off); \ + ism_dst; \ +}) + +static inline void +iosys_map_incr(struct iosys_map *ism, size_t n) +{ + if (ism->is_iomem) + ism->vaddr_iomem += n; + else + ism->vaddr += n; +} + +static inline void +iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src, + size_t len) +{ + if (ism->is_iomem) + memcpy_toio(ism->vaddr_iomem + off, src, len); + else + memcpy(ism->vaddr + off, src, len); +} + +static inline bool +iosys_map_is_null(const struct iosys_map *ism) +{ + if (ism->is_iomem) + return (ism->vaddr_iomem == NULL); + else + return (ism->vaddr == NULL); +} + +static inline bool +iosys_map_is_set(const struct iosys_map *ism) +{ + if (ism->is_iomem) + return (ism->vaddr_iomem != NULL); + else + return (ism->vaddr != NULL); +} + +static inline bool +iosys_map_is_equal(const struct iosys_map *ism_a, + const struct iosys_map *ism_b) +{ + if (ism_a->is_iomem != ism_b->is_iomem) + return (false); + + if (ism_a->is_iomem) + return (ism_a->vaddr_iomem == ism_b->vaddr_iomem); + else + return (ism_a->vaddr == ism_b->vaddr); +} + +static inline void +iosys_map_clear(struct iosys_map *ism) +{ + if (ism->is_iomem) { + ism->vaddr_iomem = NULL; + ism->is_iomem = false; + } else { + ism->vaddr = NULL; + } +} + +static inline void +iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr) +{ + ism->vaddr_iomem = addr; + ism->is_iomem = true; +} + +static inline void +iosys_map_set_vaddr(struct iosys_map *ism, void *addr) +{ + ism->vaddr = addr; + ism->is_iomem = false; +} + +static inline void +iosys_map_memset(struct iosys_map *ism, size_t off, int value, size_t len) +{ + if (ism->is_iomem) + memset_io(ism->vaddr_iomem + off, value, len); + else + memset(ism->vaddr + off, value, len); +} + +#ifdef __LP64__ +#define _iosys_map_readq(_addr) readq(_addr) +#define _iosys_map_writeq(_val, _addr) writeq(_val, _addr) +#else +#define _iosys_map_readq(_addr) ({ \ + uint64_t val; \ + memcpy_fromio(&val, _addr, sizeof(uint64_t)); \ + val; \ +}) +#define _iosys_map_writeq(_val, _addr) \ + memcpy_toio(_addr, &(_val), sizeof(uint64_t)) +#endif + +#define iosys_map_rd(_ism, _off, _type) ({ \ + _type val; \ + if ((_ism)->is_iomem) { \ + void *addr = (_ism)->vaddr_iomem + (_off); \ + val = _Generic(val, \ + uint8_t : readb(addr), \ + uint16_t: readw(addr), \ + uint32_t: readl(addr), \ + uint64_t: _iosys_map_readq(addr)); \ + } else \ + val = READ_ONCE(*(_type *)((_ism)->vaddr + (_off))); \ + val; \ +}) +#define iosys_map_wr(_ism, _off, _type, _val) ({ \ + _type val = (_val); \ + if ((_ism)->is_iomem) { \ + void *addr = (_ism)->vaddr_iomem + (_off); \ + _Generic(val, \ + uint8_t : writeb(val, addr), \ + uint16_t: writew(val, addr), \ + uint32_t: writel(val, addr), \ + uint64_t: _iosys_map_writeq(val, addr)); \ + } else \ + WRITE_ONCE(*(_type *)((_ism)->vaddr + (_off)), val); \ +}) + +#define iosys_map_rd_field(_ism, _off, _type, _field) ({ \ + _type *s; \ + iosys_map_rd(_ism, (_off) + offsetof(_type, _field), \ + __typeof(s->_field)); \ +}) +#define iosys_map_wr_field(_ism, _off, _type, _field, _val) ({ \ + _type *s; \ + iosys_map_wr(_ism, (_off) + offsetof(_type, _field), \ + __typeof(s->_field), _val); \ +}) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/ip.h b/sys/compat/linuxkpi/common/include/linux/ip.h index 11f4aed180d1..137cf89e7dcb 100644 --- a/sys/compat/linuxkpi/common/include/linux/ip.h +++ b/sys/compat/linuxkpi/common/include/linux/ip.h @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IP_H diff --git a/sys/compat/linuxkpi/common/include/linux/irq_work.h b/sys/compat/linuxkpi/common/include/linux/irq_work.h index ec71a7ee094f..7c4019bc0242 100644 --- a/sys/compat/linuxkpi/common/include/linux/irq_work.h +++ b/sys/compat/linuxkpi/common/include/linux/irq_work.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IRQ_WORK_H_ @@ -51,7 +49,12 @@ typedef void (*irq_work_func_t)(struct irq_work *); struct irq_work { struct task irq_task; - struct llist_node llnode; + union { + struct llist_node llnode; + struct { + struct llist_node llist; + } node; + }; irq_work_func_t func; }; diff --git a/sys/compat/linuxkpi/common/include/linux/irqdomain.h b/sys/compat/linuxkpi/common/include/linux/irqdomain.h new file mode 100644 index 000000000000..c7788e51cc89 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/irqdomain.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_IRQDOMAIN_H +#define _LINUXKPI_LINUX_IRQDOMAIN_H + +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/radix-tree.h> + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/irqreturn.h b/sys/compat/linuxkpi/common/include/linux/irqreturn.h index 8fbb0217573d..ff2618449d5e 100644 --- a/sys/compat/linuxkpi/common/include/linux/irqreturn.h +++ b/sys/compat/linuxkpi/common/include/linux/irqreturn.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_IRQRETURN_H diff --git a/sys/compat/linuxkpi/common/include/linux/jhash.h b/sys/compat/linuxkpi/common/include/linux/jhash.h index 1bab37f22b5d..25e2c04f1965 100644 --- a/sys/compat/linuxkpi/common/include/linux/jhash.h +++ b/sys/compat/linuxkpi/common/include/linux/jhash.h @@ -20,8 +20,6 @@ * * I've modified Bob's hash to be useful in the Linux kernel, and * any bugs present are surely my fault. -DaveM - * - * $FreeBSD$ */ /* NOTE: Arguments are modified. */ diff --git a/sys/compat/linuxkpi/common/include/linux/jiffies.h b/sys/compat/linuxkpi/common/include/linux/jiffies.h index 76c9c6a749c1..c2409726e874 100644 --- a/sys/compat/linuxkpi/common/include/linux/jiffies.h +++ b/sys/compat/linuxkpi/common/include/linux/jiffies.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_JIFFIES_H_ #define _LINUXKPI_LINUX_JIFFIES_H_ @@ -34,26 +32,27 @@ #include <linux/types.h> #include <linux/time.h> -#include <sys/time.h> #include <sys/kernel.h> #include <sys/limits.h> +#include <sys/time.h> -#define jiffies ticks -#define jiffies_64 ticks -#define jiffies_to_msecs(x) (((int64_t)(int)(x)) * 1000 / hz) +extern unsigned long jiffies; /* defined in sys/kern/subr_ticks.S */ +#define jiffies_64 jiffies /* XXX-MJ wrong on 32-bit platforms */ +#define jiffies_to_msecs(x) ((unsigned int)(((int64_t)(int)(x)) * 1000 / hz)) -#define MAX_JIFFY_OFFSET ((INT_MAX >> 1) - 1) +#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1) - 1) -#define time_after(a, b) ((int)((b) - (a)) < 0) +#define time_after(a, b) ((long)((b) - (a)) < 0) #define time_after32(a, b) ((int32_t)((uint32_t)(b) - (uint32_t)(a)) < 0) #define time_before(a, b) time_after(b,a) #define time_before32(a, b) time_after32(b, a) -#define time_after_eq(a, b) ((int)((a) - (b)) >= 0) +#define time_after_eq(a, b) ((long)((a) - (b)) >= 0) #define time_before_eq(a, b) time_after_eq(b, a) #define time_in_range(a,b,c) \ (time_after_eq(a,b) && time_before_eq(a,c)) #define time_is_after_eq_jiffies(a) time_after_eq(a, jiffies) #define time_is_after_jiffies(a) time_after(a, jiffies) +#define time_is_before_jiffies(a) time_before(a, jiffies) #define HZ hz @@ -69,20 +68,7 @@ extern uint64_t lkpi_msec2hz_rem; extern uint64_t lkpi_msec2hz_div; extern uint64_t lkpi_msec2hz_max; -static inline int -timespec_to_jiffies(const struct timespec *ts) -{ - u64 result; - - result = ((u64)hz * ts->tv_sec) + - (((u64)hz * ts->tv_nsec + NSEC_PER_SEC - 1) / NSEC_PER_SEC); - if (result > MAX_JIFFY_OFFSET) - result = MAX_JIFFY_OFFSET; - - return ((int)result); -} - -static inline int +static inline unsigned long msecs_to_jiffies(uint64_t msec) { uint64_t result; @@ -93,10 +79,10 @@ msecs_to_jiffies(uint64_t msec) if (result > MAX_JIFFY_OFFSET) result = MAX_JIFFY_OFFSET; - return ((int)result); + return ((unsigned long)result); } -static inline int +static inline unsigned long usecs_to_jiffies(uint64_t usec) { uint64_t result; @@ -107,7 +93,7 @@ usecs_to_jiffies(uint64_t usec) if (result > MAX_JIFFY_OFFSET) result = MAX_JIFFY_OFFSET; - return ((int)result); + return ((unsigned long)result); } static inline uint64_t @@ -134,34 +120,24 @@ nsecs_to_jiffies(uint64_t nsec) } static inline uint64_t -jiffies_to_nsecs(int j) +jiffies_to_nsecs(unsigned long j) { - return ((1000000000ULL / hz) * (uint64_t)(unsigned int)j); + return ((1000000000ULL / hz) * (uint64_t)j); } static inline uint64_t -jiffies_to_usecs(int j) +jiffies_to_usecs(unsigned long j) { - return ((1000000ULL / hz) * (uint64_t)(unsigned int)j); + return ((1000000ULL / hz) * (uint64_t)j); } static inline uint64_t get_jiffies_64(void) { - return ((uint64_t)(unsigned int)ticks); -} - -static inline int -linux_timer_jiffies_until(int expires) -{ - int delta = expires - jiffies; - /* guard against already expired values */ - if (delta < 1) - delta = 1; - return (delta); + return ((uint64_t)jiffies); } #endif /* _LINUXKPI_LINUX_JIFFIES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kconfig.h b/sys/compat/linuxkpi/common/include/linux/kconfig.h new file mode 100644 index 000000000000..c1d186b56e1f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kconfig.h @@ -0,0 +1,76 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_KCONFIG_H_ +#define _LINUXKPI_LINUX_KCONFIG_H_ + +/* + * Checking if an option is defined would be easy if we could do CPP inside CPP. + * The defined case whether -Dxxx or -Dxxx=1 are easy to deal with. In either + * case the defined value is "1". A more general -Dxxx=<c> case will require + * more effort to deal with all possible "true" values. Hope we do not have + * to do this as well. + * The real problem is the undefined case. To avoid this problem we do the + * concat/varargs trick: "yyy" ## xxx can make two arguments if xxx is "1" + * by having a #define for yyy_1 which is "ignore,". + * Otherwise we will just get "yyy". + * Need to be careful about variable substitutions in macros though. + * This way we make a (true, false) problem a (don't care, true, false) or a + * (don't care true, false). Then we can use a variadic macro to only select + * the always well known and defined argument #2. And that seems to be + * exactly what we need. Use 1 for true and 0 for false to also allow + * #if IS_*() checks pre-compiler checks which do not like #if true. + */ +#define ___XAB_1 dontcare, +#define ___IS_XAB(_ignore, _x, ...) (_x) +#define __IS_XAB(_x) ___IS_XAB(_x 1, 0) +#define _IS_XAB(_x) __IS_XAB(__CONCAT(___XAB_, _x)) + +/* This is if CONFIG_ccc=y. */ +#define IS_BUILTIN(_x) _IS_XAB(_x) +/* This is if CONFIG_ccc=m. */ +#define IS_MODULE(_x) _IS_XAB(_x ## _MODULE) +/* This is if CONFIG_ccc is compiled in(=y) or a module(=m). */ +#define IS_ENABLED(_x) (IS_BUILTIN(_x) || IS_MODULE(_x)) +/* + * This is weird case. If the CONFIG_ccc is builtin (=y) this returns true; + * or if the CONFIG_ccc is a module (=m) and the caller is built as a module + * (-DMODULE defined) this returns true, but if the callers is not a module + * (-DMODULE not defined, which means caller is BUILTIN) then it returns + * false. In other words, a module can reach the kernel, a module can reach + * a module, but the kernel cannot reach a module, and code never compiled + * cannot be reached either. + * XXX -- I'd hope the module-to-module case would be handled by a proper + * module dependency definition (MODULE_DEPEND() in FreeBSD). + */ +#define IS_REACHABLE(_x) (IS_BUILTIN(_x) || \ + (IS_MODULE(_x) && IS_BUILTIN(MODULE))) + +#endif /* _LINUXKPI_LINUX_KCONFIG_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kdev_t.h b/sys/compat/linuxkpi/common/include/linux/kdev_t.h index f2a5b53effec..988dd771254a 100644 --- a/sys/compat/linuxkpi/common/include/linux/kdev_t.h +++ b/sys/compat/linuxkpi/common/include/linux/kdev_t.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_KDEV_T_H_ #define _LINUXKPI_LINUX_KDEV_T_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/kernel.h b/sys/compat/linuxkpi/common/include/linux/kernel.h index 4987c582f0f3..11a13cbd49b4 100644 --- a/sys/compat/linuxkpi/common/include/linux/kernel.h +++ b/sys/compat/linuxkpi/common/include/linux/kernel.h @@ -26,13 +26,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_KERNEL_H_ #define _LINUXKPI_LINUX_KERNEL_H_ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/systm.h> #include <sys/param.h> @@ -44,18 +41,27 @@ #include <sys/time.h> #include <linux/bitops.h> +#include <linux/build_bug.h> #include <linux/compiler.h> +#include <linux/container_of.h> +#include <linux/kstrtox.h> +#include <linux/limits.h> +#include <linux/math.h> +#include <linux/minmax.h> #include <linux/stringify.h> #include <linux/errno.h> -#include <linux/sched.h> #include <linux/types.h> +#include <linux/typecheck.h> #include <linux/jiffies.h> #include <linux/log2.h> +#include <linux/kconfig.h> #include <asm/byteorder.h> +#include <asm/cpufeature.h> +#include <asm/processor.h> #include <asm/uaccess.h> -#include <machine/stdarg.h> +#include <linux/stdarg.h> #define KERN_CONT "" #define KERN_EMERG "<0>" @@ -67,19 +73,6 @@ #define KERN_INFO "<6>" #define KERN_DEBUG "<7>" -#define U8_MAX ((u8)~0U) -#define S8_MAX ((s8)(U8_MAX >> 1)) -#define S8_MIN ((s8)(-S8_MAX - 1)) -#define U16_MAX ((u16)~0U) -#define S16_MAX ((s16)(U16_MAX >> 1)) -#define S16_MIN ((s16)(-S16_MAX - 1)) -#define U32_MAX ((u32)~0U) -#define S32_MAX ((s32)(U32_MAX >> 1)) -#define S32_MIN ((s32)(-S32_MAX - 1)) -#define U64_MAX ((u64)~0ULL) -#define S64_MAX ((s64)(U64_MAX >> 1)) -#define S64_MIN ((s64)(-S64_MAX - 1)) - #define S8_C(x) x #define U8_C(x) x ## U #define S16_C(x) x @@ -89,28 +82,6 @@ #define S64_C(x) x ## LL #define U64_C(x) x ## ULL -/* - * BUILD_BUG_ON() can happen inside functions where _Static_assert() does not - * seem to work. Use old-schoold-ish CTASSERT from before commit - * a3085588a88fa58eb5b1eaae471999e1995a29cf but also make sure we do not - * end up with an unused typedef or variable. The compiler should optimise - * it away entirely. - */ -#define _O_CTASSERT(x) _O__CTASSERT(x, __LINE__) -#define _O__CTASSERT(x, y) _O___CTASSERT(x, y) -#define _O___CTASSERT(x, y) while (0) { \ - typedef char __assert_line_ ## y[(x) ? 1 : -1]; \ - __assert_line_ ## y _x; \ - _x[0] = '\0'; \ -} - -#define BUILD_BUG() do { CTASSERT(0); } while (0) -#define BUILD_BUG_ON(x) do { _O_CTASSERT(!(x)) } while (0) -#define BUILD_BUG_ON_MSG(x, msg) BUILD_BUG_ON(x) -#define BUILD_BUG_ON_NOT_POWER_OF_2(x) BUILD_BUG_ON(!powerof2(x)) -#define BUILD_BUG_ON_INVALID(expr) while (0) { (void)(expr); } -#define BUILD_BUG_ON_ZERO(x) ((int)sizeof(struct { int:-((x) != 0); })) - #define BUG() panic("BUG at %s:%d", __FILE__, __LINE__) #define BUG_ON(cond) do { \ if (cond) { \ @@ -154,15 +125,14 @@ extern int linuxkpi_warn_dump_stack; #undef PTR_ALIGN #define PTR_ALIGN(p, a) ((__typeof(p))ALIGN((uintptr_t)(p), (a))) #define IS_ALIGNED(x, a) (((x) & ((__typeof(x))(a) - 1)) == 0) -#define DIV_ROUND_UP(x, n) howmany(x, n) #define __KERNEL_DIV_ROUND_UP(x, n) howmany(x, n) -#define DIV_ROUND_UP_ULL(x, n) DIV_ROUND_UP((unsigned long long)(x), (n)) -#define DIV_ROUND_DOWN_ULL(x, n) (((unsigned long long)(x) / (n)) * (n)) #define FIELD_SIZEOF(t, f) sizeof(((t *)0)->f) #define printk(...) printf(__VA_ARGS__) #define vprintk(f, a) vprintf(f, a) +#define PTR_IF(x, p) ((x) ? (p) : NULL) + #define asm __asm extern void linux_dump_stack(void); @@ -293,301 +263,15 @@ extern int linuxkpi_debug; }) #endif -#define container_of(ptr, type, member) \ -({ \ - const __typeof(((type *)0)->member) *__p = (ptr); \ - (type *)((uintptr_t)__p - offsetof(type, member)); \ -}) - #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define u64_to_user_ptr(val) ((void *)(uintptr_t)(val)) #define _RET_IP_ __builtin_return_address(0) -static inline unsigned long long -simple_strtoull(const char *cp, char **endp, unsigned int base) -{ - return (strtouq(cp, endp, base)); -} - -static inline long long -simple_strtoll(const char *cp, char **endp, unsigned int base) -{ - return (strtoq(cp, endp, base)); -} - -static inline unsigned long -simple_strtoul(const char *cp, char **endp, unsigned int base) -{ - return (strtoul(cp, endp, base)); -} - -static inline long -simple_strtol(const char *cp, char **endp, unsigned int base) -{ - return (strtol(cp, endp, base)); -} - -static inline int -kstrtoul(const char *cp, unsigned int base, unsigned long *res) -{ - char *end; - - *res = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - return (0); -} - -static inline int -kstrtol(const char *cp, unsigned int base, long *res) -{ - char *end; - - *res = strtol(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - return (0); -} - -static inline int -kstrtoint(const char *cp, unsigned int base, int *res) -{ - char *end; - long temp; - - *res = temp = strtol(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (int)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtouint(const char *cp, unsigned int base, unsigned int *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (unsigned int)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou8(const char *cp, unsigned int base, u8 *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (u8)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou16(const char *cp, unsigned int base, u16 *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (u16)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou32(const char *cp, unsigned int base, u32 *res) -{ - char *end; - unsigned long temp; - - *res = temp = strtoul(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - if (temp != (u32)temp) - return (-ERANGE); - return (0); -} - -static inline int -kstrtou64(const char *cp, unsigned int base, u64 *res) -{ - char *end; - - *res = strtouq(cp, &end, base); - - /* skip newline character, if any */ - if (*end == '\n') - end++; - if (*cp == 0 || *end != 0) - return (-EINVAL); - return (0); -} - -static inline int -kstrtoull(const char *cp, unsigned int base, unsigned long long *res) -{ - return (kstrtou64(cp, base, (u64 *)res)); -} - -static inline int -kstrtobool(const char *s, bool *res) -{ - int len; - - if (s == NULL || (len = strlen(s)) == 0 || res == NULL) - return (-EINVAL); - - /* skip newline character, if any */ - if (s[len - 1] == '\n') - len--; - - if (len == 1 && strchr("yY1", s[0]) != NULL) - *res = true; - else if (len == 1 && strchr("nN0", s[0]) != NULL) - *res = false; - else if (strncasecmp("on", s, len) == 0) - *res = true; - else if (strncasecmp("off", s, len) == 0) - *res = false; - else - return (-EINVAL); - - return (0); -} - -static inline int -kstrtobool_from_user(const char __user *s, size_t count, bool *res) -{ - char buf[8] = {}; - - if (count > (sizeof(buf) - 1)) - count = (sizeof(buf) - 1); - - if (copy_from_user(buf, s, count)) - return (-EFAULT); - - return (kstrtobool(buf, res)); -} - -static inline int -kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, - int *p) -{ - char buf[36] = {}; - - if (count > (sizeof(buf) - 1)) - count = (sizeof(buf) - 1); - - if (copy_from_user(buf, s, count)) - return (-EFAULT); - - return (kstrtoint(buf, base, p)); -} - -static inline int -kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, - int *p) -{ - char buf[36] = {}; - - if (count > (sizeof(buf) - 1)) - count = (sizeof(buf) - 1); - - if (copy_from_user(buf, s, count)) - return (-EFAULT); - - return (kstrtouint(buf, base, p)); -} - -static inline int -kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, - u8 *p) -{ - char buf[8] = {}; - - if (count > (sizeof(buf) - 1)) - count = (sizeof(buf) - 1); - - if (copy_from_user(buf, s, count)) - return (-EFAULT); - - return (kstrtou8(buf, base, p)); -} - -#define min(x, y) ((x) < (y) ? (x) : (y)) -#define max(x, y) ((x) > (y) ? (x) : (y)) - -#define min3(a, b, c) min(a, min(b,c)) -#define max3(a, b, c) max(a, max(b,c)) - -#define min_t(type, x, y) ({ \ - type __min1 = (x); \ - type __min2 = (y); \ - __min1 < __min2 ? __min1 : __min2; }) - -#define max_t(type, x, y) ({ \ - type __max1 = (x); \ - type __max2 = (y); \ - __max1 > __max2 ? __max1 : __max2; }) - #define offsetofend(t, m) \ (offsetof(t, m) + sizeof((((t *)0)->m))) -#define clamp_t(type, _x, min, max) min_t(type, max_t(type, _x, min), max) -#define clamp(x, lo, hi) min( max(x,lo), hi) -#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi) - -/* - * This looks more complex than it should be. But we need to - * get the type for the ~ right in round_down (it needs to be - * as wide as the result!), and we want to evaluate the macro - * arguments just once each. - */ -#define __round_mask(x, y) ((__typeof__(x))((y)-1)) -#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) -#define round_down(x, y) ((x) & ~__round_mask(x, y)) - #define smp_processor_id() PCPU_GET(cpuid) #define num_possible_cpus() mp_ncpus #define num_online_cpus() mp_ncpus @@ -597,37 +281,6 @@ extern bool linux_cpu_has_clflush; #define cpu_has_clflush linux_cpu_has_clflush #endif -/* Swap values of a and b */ -#define swap(a, b) do { \ - typeof(a) _swap_tmp = a; \ - a = b; \ - b = _swap_tmp; \ -} while (0) - -#define DIV_ROUND_CLOSEST(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) - -#define DIV_ROUND_CLOSEST_ULL(x, divisor) ({ \ - __typeof(divisor) __d = (divisor); \ - unsigned long long __ret = (x) + (__d) / 2; \ - __ret /= __d; \ - __ret; \ -}) - -static inline uintmax_t -mult_frac(uintmax_t x, uintmax_t multiplier, uintmax_t divisor) -{ - uintmax_t q = (x / divisor); - uintmax_t r = (x % divisor); - - return ((q * multiplier) + ((r * multiplier) / divisor)); -} - -static inline int64_t -abs64(int64_t x) -{ - return (x < 0 ? -x : x); -} - typedef struct linux_ratelimit { struct timeval lasttime; int counter; @@ -639,12 +292,6 @@ linux_ratelimited(linux_ratelimit_t *rl) return (ppsratecheck(&rl->lasttime, &rl->counter, 1)); } -#define struct_size(ptr, field, num) ({ \ - const size_t __size = offsetof(__typeof(*(ptr)), field); \ - const size_t __max = (SIZE_MAX - __size) / sizeof((ptr)->field[0]); \ - ((num) > __max) ? SIZE_MAX : (__size + sizeof((ptr)->field[0]) * (num)); \ -}) - #define __is_constexpr(x) \ __builtin_constant_p(x) @@ -654,31 +301,10 @@ linux_ratelimited(linux_ratelimit_t *rl) */ #define is_signed(datatype) (((datatype)-1 / (datatype)2) == (datatype)0) -/* - * The type_max() macro below returns the maxium positive value the - * passed data type can hold. - */ -#define type_max(datatype) ( \ - (sizeof(datatype) >= 8) ? (is_signed(datatype) ? INT64_MAX : UINT64_MAX) : \ - (sizeof(datatype) >= 4) ? (is_signed(datatype) ? INT32_MAX : UINT32_MAX) : \ - (sizeof(datatype) >= 2) ? (is_signed(datatype) ? INT16_MAX : UINT16_MAX) : \ - (is_signed(datatype) ? INT8_MAX : UINT8_MAX) \ -) - -/* - * The type_min() macro below returns the minimum value the passed - * data type can hold. For unsigned types the minimum value is always - * zero. For signed types it may vary. - */ -#define type_min(datatype) ( \ - (sizeof(datatype) >= 8) ? (is_signed(datatype) ? INT64_MIN : 0) : \ - (sizeof(datatype) >= 4) ? (is_signed(datatype) ? INT32_MIN : 0) : \ - (sizeof(datatype) >= 2) ? (is_signed(datatype) ? INT16_MIN : 0) : \ - (is_signed(datatype) ? INT8_MIN : 0) \ -) - #define TAINT_WARN 0 #define test_taint(x) (0) +#define add_taint(x,y) do { \ + } while (0) static inline int _h2b(const char c) @@ -711,49 +337,49 @@ hex2bin(uint8_t *bindst, const char *hexsrc, size_t binlen) return (0); } +static inline bool +mac_pton(const char *macin, uint8_t *macout) +{ + const char *s, *d; + uint8_t mac[6], hx, lx; + int i; + + if (strlen(macin) < (3 * 6 - 1)) + return (false); + + i = 0; + s = macin; + do { + /* Should we also support '-'-delimiters? */ + d = strchrnul(s, ':'); + hx = lx = 0; + while (s < d) { + /* Fail on abc:123:xxx:... */ + if ((d - s) > 2) + return (false); + /* We do support non-well-formed strings: 3:45:6:... */ + if ((d - s) > 1) { + hx = _h2b(*s); + if (hx < 0) + return (false); + s++; + } + lx = _h2b(*s); + if (lx < 0) + return (false); + s++; + } + mac[i] = (hx << 4) | lx; + i++; + if (i >= 6) + return (false); + } while (d != NULL && *d != '\0'); + + memcpy(macout, mac, 6); + return (true); +} + #define DECLARE_FLEX_ARRAY(_t, _n) \ struct { struct { } __dummy_ ## _n; _t _n[0]; } -/* - * Checking if an option is defined would be easy if we could do CPP inside CPP. - * The defined case whether -Dxxx or -Dxxx=1 are easy to deal with. In either - * case the defined value is "1". A more general -Dxxx=<c> case will require - * more effort to deal with all possible "true" values. Hope we do not have - * to do this as well. - * The real problem is the undefined case. To avoid this problem we do the - * concat/varargs trick: "yyy" ## xxx can make two arguments if xxx is "1" - * by having a #define for yyy_1 which is "ignore,". - * Otherwise we will just get "yyy". - * Need to be careful about variable substitutions in macros though. - * This way we make a (true, false) problem a (don't care, true, false) or a - * (don't care true, false). Then we can use a variadic macro to only select - * the always well known and defined argument #2. And that seems to be - * exactly what we need. Use 1 for true and 0 for false to also allow - * #if IS_*() checks pre-compiler checks which do not like #if true. - */ -#define ___XAB_1 dontcare, -#define ___IS_XAB(_ignore, _x, ...) (_x) -#define __IS_XAB(_x) ___IS_XAB(_x 1, 0) -#define _IS_XAB(_x) __IS_XAB(__CONCAT(___XAB_, _x)) - -/* This is if CONFIG_ccc=y. */ -#define IS_BUILTIN(_x) _IS_XAB(_x) -/* This is if CONFIG_ccc=m. */ -#define IS_MODULE(_x) _IS_XAB(_x ## _MODULE) -/* This is if CONFIG_ccc is compiled in(=y) or a module(=m). */ -#define IS_ENABLED(_x) (IS_BUILTIN(_x) || IS_MODULE(_x)) -/* - * This is weird case. If the CONFIG_ccc is builtin (=y) this returns true; - * or if the CONFIG_ccc is a module (=m) and the caller is built as a module - * (-DMODULE defined) this returns true, but if the callers is not a module - * (-DMODULE not defined, which means caller is BUILTIN) then it returns - * false. In other words, a module can reach the kernel, a module can reach - * a module, but the kernel cannot reach a module, and code never compiled - * cannot be reached either. - * XXX -- I'd hope the module-to-module case would be handled by a proper - * module dependency definition (MODULE_DEPEND() in FreeBSD). - */ -#define IS_REACHABLE(_x) (IS_BUILTIN(_x) || \ - (IS_MODULE(_x) && IS_BUILTIN(MODULE))) - #endif /* _LINUXKPI_LINUX_KERNEL_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kernel_stat.h b/sys/compat/linuxkpi/common/include/linux/kernel_stat.h new file mode 100644 index 000000000000..c960b4ad2cff --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kernel_stat.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_KERNEL_STAT_H_ +#define _LINUXKPI_LINUX_KERNEL_STAT_H_ + +#include <linux/interrupt.h> + +#endif /* _LINUXKPI_LINUX_KERNEL_STAT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kfifo.h b/sys/compat/linuxkpi/common/include/linux/kfifo.h index 6ba1528d965c..d2f570781661 100644 --- a/sys/compat/linuxkpi/common/include/linux/kfifo.h +++ b/sys/compat/linuxkpi/common/include/linux/kfifo.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * Copyright (c) 2022 Bjoern A. Zeeb * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,7 +28,95 @@ #ifndef _LINUXKPI_LINUX_KFIFO_H_ #define _LINUXKPI_LINUX_KFIFO_H_ +#include <sys/types.h> + +#include <linux/slab.h> +#include <linux/gfp.h> + #define INIT_KFIFO(x) 0 #define DECLARE_KFIFO(x, y, z) +#define DECLARE_KFIFO_PTR(_name, _type) \ + struct kfifo_ ## _name { \ + size_t total; \ + size_t count; \ + size_t first; \ + size_t last; \ + _type *head; \ + } _name + +#define kfifo_len(_kf) \ +({ \ + (_kf)->count; \ +}) + +#define kfifo_is_empty(_kf) \ +({ \ + ((_kf)->count == 0) ? true : false; \ +}) + +#define kfifo_is_full(_kf) \ +({ \ + ((_kf)->count == (_kf)->total) ? true : false; \ +}) + +#define kfifo_put(_kf, _e) \ +({ \ + bool _rc; \ + \ + /* Would overflow. */ \ + if (kfifo_is_full(_kf)) { \ + _rc = false; \ + } else { \ + (_kf)->head[(_kf)->last] = (_e); \ + (_kf)->count++; \ + (_kf)->last++; \ + if ((_kf)->last > (_kf)->total) \ + (_kf)->last = 0; \ + _rc = true; \ + } \ + \ + _rc; \ +}) + +#define kfifo_get(_kf, _e) \ +({ \ + bool _rc; \ + \ + if (kfifo_is_empty(_kf)) { \ + _rc = false; \ + } else { \ + *(_e) = (_kf)->head[(_kf)->first]; \ + (_kf)->count--; \ + (_kf)->first++; \ + if ((_kf)->first > (_kf)->total) \ + (_kf)->first = 0; \ + _rc = true; \ + } \ + \ + _rc; \ +}) + +#define kfifo_alloc(_kf, _s, _gfp) \ +({ \ + int _error; \ + \ + (_kf)->head = kmalloc(sizeof(__typeof(*(_kf)->head)) * (_s), _gfp); \ + if ((_kf)->head == NULL) \ + _error = ENOMEM; \ + else { \ + (_kf)->total = (_s); \ + _error = 0; \ + } \ + \ + _error; \ +}) + +#define kfifo_free(_kf) \ +({ \ + kfree((_kf)->head); \ + (_kf)->head = NULL; \ + (_kf)->total = (_kf)->count = (_kf)->first = (_kf)->last = 0; \ +}) + #endif /* _LINUXKPI_LINUX_KFIFO_H_*/ diff --git a/sys/compat/linuxkpi/common/include/linux/kmod.h b/sys/compat/linuxkpi/common/include/linux/kmod.h index b8e8a483210f..8f9f034aabd8 100644 --- a/sys/compat/linuxkpi/common/include/linux/kmod.h +++ b/sys/compat/linuxkpi/common/include/linux/kmod.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_KMOD_H_ #define _LINUXKPI_LINUX_KMOD_H_ @@ -35,15 +33,14 @@ #include <sys/syscallsubr.h> #include <sys/refcount.h> #include <sys/sbuf.h> -#include <machine/stdarg.h> +#include <sys/stdarg.h> #include <sys/proc.h> #define request_module(...) \ ({\ char modname[128]; \ - int fileid; \ snprintf(modname, sizeof(modname), __VA_ARGS__); \ - kern_kldload(curthread, modname, &fileid); \ + kern_kldload(curthread, modname, NULL); \ }) #define request_module_nowait request_module diff --git a/sys/compat/linuxkpi/common/include/linux/kobject.h b/sys/compat/linuxkpi/common/include/linux/kobject.h index ad25058028fc..98f55d1234c4 100644 --- a/sys/compat/linuxkpi/common/include/linux/kobject.h +++ b/sys/compat/linuxkpi/common/include/linux/kobject.h @@ -25,20 +25,22 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_KOBJECT_H_ #define _LINUXKPI_LINUX_KOBJECT_H_ -#include <machine/stdarg.h> +#include <sys/stdarg.h> #include <linux/kernel.h> #include <linux/kref.h> #include <linux/list.h> #include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/wait.h> +#include <linux/workqueue.h> struct kobject; +struct kset; struct sysctl_oid; #define KOBJ_CHANGE 0x01 @@ -47,6 +49,7 @@ struct kobj_type { void (*release)(struct kobject *kobj); const struct sysfs_ops *sysfs_ops; struct attribute **default_attrs; + const struct attribute_group **default_groups; }; extern const struct kobj_type linux_kfree_type; @@ -58,6 +61,7 @@ struct kobject { const struct kobj_type *ktype; struct list_head entry; struct sysctl_oid *oidp; + struct kset *kset; }; extern struct kobject *mm_kobj; @@ -78,6 +82,17 @@ struct kobj_attribute { const char *buf, size_t count); }; +struct kset_uevent_ops { + /* TODO */ +}; + +struct kset { + struct list_head list; + spinlock_t list_lock; + struct kobject kobj; + const struct kset_uevent_ops *uevent_ops; +}; + static inline void kobject_init(struct kobject *kobj, const struct kobj_type *ktype) { @@ -155,4 +170,41 @@ kobject_uevent_env(struct kobject *kobj, int action, char *envp[]) */ } +void kset_init(struct kset *kset); +int kset_register(struct kset *kset); +void kset_unregister(struct kset *kset); +struct kset * kset_create_and_add(const char *name, + const struct kset_uevent_ops *u, struct kobject *parent_kobj); + +static inline struct kset * +to_kset(struct kobject *kobj) +{ + if (kobj != NULL) + return container_of(kobj, struct kset, kobj); + else + return NULL; +} + +static inline struct kset * +kset_get(struct kset *kset) +{ + if (kset != NULL) { + struct kobject *kobj; + + kobj = kobject_get(&kset->kobj); + return to_kset(kobj); + } else { + return NULL; + } +} + +static inline void +kset_put(struct kset *kset) +{ + if (kset != NULL) + kobject_put(&kset->kobj); +} + +void linux_kobject_kfree_name(struct kobject *kobj); + #endif /* _LINUXKPI_LINUX_KOBJECT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kref.h b/sys/compat/linuxkpi/common/include/linux/kref.h index 2c59794f4ddc..b2fba468f7df 100644 --- a/sys/compat/linuxkpi/common/include/linux/kref.h +++ b/sys/compat/linuxkpi/common/include/linux/kref.h @@ -26,8 +26,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_KREF_H_ #define _LINUXKPI_LINUX_KREF_H_ @@ -43,35 +41,35 @@ #include <asm/atomic.h> struct kref { - atomic_t refcount; + refcount_t refcount; }; static inline void kref_init(struct kref *kref) { - refcount_init(&kref->refcount.counter, 1); + refcount_init((uint32_t *)&kref->refcount, 1); } static inline unsigned int kref_read(const struct kref *kref) { - return (atomic_read(&kref->refcount)); + return (refcount_load(__DECONST(u_int32_t *, &kref->refcount))); } static inline void kref_get(struct kref *kref) { - refcount_acquire(&kref->refcount.counter); + refcount_acquire((uint32_t *)&kref->refcount); } static inline int kref_put(struct kref *kref, void (*rel)(struct kref *kref)) { - if (refcount_release(&kref->refcount.counter)) { + if (refcount_release((uint32_t *)&kref->refcount)) { rel(kref); return 1; } @@ -83,7 +81,7 @@ kref_put_lock(struct kref *kref, void (*rel)(struct kref *kref), spinlock_t *lock) { - if (refcount_release(&kref->refcount.counter)) { + if (refcount_release((uint32_t *)&kref->refcount)) { spin_lock(lock); rel(kref); return (1); @@ -97,7 +95,7 @@ kref_sub(struct kref *kref, unsigned int count, { while (count--) { - if (refcount_release(&kref->refcount.counter)) { + if (refcount_release((uint32_t *)&kref->refcount)) { rel(kref); return 1; } @@ -109,16 +107,16 @@ static inline int __must_check kref_get_unless_zero(struct kref *kref) { - return atomic_add_unless(&kref->refcount, 1, 0); + return refcount_acquire_if_not_zero((uint32_t *)&kref->refcount); } static inline int kref_put_mutex(struct kref *kref, void (*release)(struct kref *kref), struct mutex *lock) { WARN_ON(release == NULL); - if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) { + if (unlikely(!refcount_release_if_not_last((uint32_t *)&kref->refcount))) { mutex_lock(lock); - if (unlikely(!atomic_dec_and_test(&kref->refcount))) { + if (unlikely(!refcount_release((uint32_t *)&kref->refcount))) { mutex_unlock(lock); return 0; } diff --git a/sys/compat/linuxkpi/common/include/linux/kstrtox.h b/sys/compat/linuxkpi/common/include/linux/kstrtox.h new file mode 100644 index 000000000000..5da99de24197 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/kstrtox.h @@ -0,0 +1,324 @@ +/*- + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2017-2018 Mellanox Technologies, Ltd. + * All rights reserved. + * Copyright (c) 2018 Johannes Lundberg <johalun0@gmail.com> + * Copyright (c) 2020-2022 The FreeBSD Foundation + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC + * + * Portions of this software were developed by Bjoern A. Zeeb and + * Emmanuel Vadot under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_KSTRTOX_H_ +#define _LINUXKPI_LINUX_KSTRTOX_H_ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/libkern.h> + +#include <linux/compiler.h> +#include <linux/types.h> + +#include <asm/uaccess.h> + +static inline unsigned long long +simple_strtoull(const char *cp, char **endp, unsigned int base) +{ + return (strtouq(cp, endp, base)); +} + +static inline long long +simple_strtoll(const char *cp, char **endp, unsigned int base) +{ + return (strtoq(cp, endp, base)); +} + +static inline unsigned long +simple_strtoul(const char *cp, char **endp, unsigned int base) +{ + return (strtoul(cp, endp, base)); +} + +static inline long +simple_strtol(const char *cp, char **endp, unsigned int base) +{ + return (strtol(cp, endp, base)); +} + +static inline int +kstrtoul(const char *cp, unsigned int base, unsigned long *res) +{ + char *end; + + *res = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtol(const char *cp, unsigned int base, long *res) +{ + char *end; + + *res = strtol(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtoint(const char *cp, unsigned int base, int *res) +{ + char *end; + long temp; + + *res = temp = strtol(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (int)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtouint(const char *cp, unsigned int base, unsigned int *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (unsigned int)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtou8(const char *cp, unsigned int base, uint8_t *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (uint8_t)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtou16(const char *cp, unsigned int base, uint16_t *res) +{ + char *end; + unsigned long temp; + + *res = temp = strtoul(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + if (temp != (uint16_t)temp) + return (-ERANGE); + return (0); +} + +static inline int +kstrtou32(const char *cp, unsigned int base, uint32_t *res) +{ + + return (kstrtouint(cp, base, res)); +} + +static inline int +kstrtos32(const char *cp, unsigned int base, int32_t *res) +{ + + return (kstrtoint(cp, base, res)); +} + +static inline int +kstrtos64(const char *cp, unsigned int base, int64_t *res) +{ + char *end; + + *res = strtoq(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtoll(const char *cp, unsigned int base, long long *res) +{ + return (kstrtos64(cp, base, (int64_t *)res)); +} + +static inline int +kstrtou64(const char *cp, unsigned int base, u64 *res) +{ + char *end; + + *res = strtouq(cp, &end, base); + + /* skip newline character, if any */ + if (*end == '\n') + end++; + if (*cp == 0 || *end != 0) + return (-EINVAL); + return (0); +} + +static inline int +kstrtoull(const char *cp, unsigned int base, unsigned long long *res) +{ + return (kstrtou64(cp, base, (uint64_t *)res)); +} + +static inline int +kstrtobool(const char *s, bool *res) +{ + int len; + + if (s == NULL || (len = strlen(s)) == 0 || res == NULL) + return (-EINVAL); + + /* skip newline character, if any */ + if (s[len - 1] == '\n') + len--; + + if (len == 1 && strchr("yY1", s[0]) != NULL) + *res = true; + else if (len == 1 && strchr("nN0", s[0]) != NULL) + *res = false; + else if (strncasecmp("on", s, len) == 0) + *res = true; + else if (strncasecmp("off", s, len) == 0) + *res = false; + else + return (-EINVAL); + + return (0); +} + +static inline int +kstrtobool_from_user(const char __user *s, size_t count, bool *res) +{ + char buf[8] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtobool(buf, res)); +} + +static inline int +kstrtoint_from_user(const char __user *s, size_t count, unsigned int base, + int *p) +{ + char buf[36] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtoint(buf, base, p)); +} + +static inline int +kstrtouint_from_user(const char __user *s, size_t count, unsigned int base, + unsigned int *p) +{ + char buf[36] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtouint(buf, base, p)); +} + +static inline int +kstrtou32_from_user(const char __user *s, size_t count, unsigned int base, + unsigned int *p) +{ + + return (kstrtouint_from_user(s, count, base, p)); +} + +static inline int +kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, + uint8_t *p) +{ + char buf[8] = {}; + + if (count > (sizeof(buf) - 1)) + count = (sizeof(buf) - 1); + + if (copy_from_user(buf, s, count)) + return (-EFAULT); + + return (kstrtou8(buf, base, p)); +} + +#endif /* _LINUXKPI_LINUX_KSTRTOX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/kthread.h b/sys/compat/linuxkpi/common/include/linux/kthread.h index 49309cd47a40..1fde734fd767 100644 --- a/sys/compat/linuxkpi/common/include/linux/kthread.h +++ b/sys/compat/linuxkpi/common/include/linux/kthread.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_KTHREAD_H_ #define _LINUXKPI_LINUX_KTHREAD_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/ktime.h b/sys/compat/linuxkpi/common/include/linux/ktime.h index e0722aa2589b..6a2f04f3d789 100644 --- a/sys/compat/linuxkpi/common/include/linux/ktime.h +++ b/sys/compat/linuxkpi/common/include/linux/ktime.h @@ -24,8 +24,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_KTIME_H @@ -71,6 +69,12 @@ ktime_to_ms(ktime_t kt) return (ktime_divns(kt, NSEC_PER_MSEC)); } +static inline ktime_t +ms_to_ktime(uint64_t ms) +{ + return (ms * NSEC_PER_MSEC); +} + static inline struct timeval ktime_to_timeval(ktime_t kt) { @@ -190,6 +194,7 @@ timespec64_to_ns(struct timespec64 *ts) #define ktime_get_ts(ts) getnanouptime(ts) #define ktime_get_ts64(ts) getnanouptime(ts) #define ktime_get_raw_ts64(ts) getnanouptime(ts) +#define ktime_get_real_ts64(ts) getnanotime(ts) #define getrawmonotonic64(ts) getnanouptime(ts) static inline int64_t @@ -227,6 +232,13 @@ ktime_get_boottime_ns(void) return (ktime_to_ns(ktime_get_boottime())); } +static inline uint64_t +ktime_get_boottime_seconds(void) +{ + + return (ktime_divns(ktime_get_boottime(), NSEC_PER_SEC)); +} + static inline ktime_t ktime_get_real(void) { @@ -263,4 +275,13 @@ ktime_get_raw_ns(void) return (ktime_to_ns(timespec_to_ktime(ts))); } +static inline uint64_t +ktime_get_raw_fast_ns(void) +{ + struct timespec ts; + + getnanouptime(&ts); + return (ktime_to_ns(timespec_to_ktime(ts))); +} + #endif /* _LINUXKPI_LINUX_KTIME_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/leds.h b/sys/compat/linuxkpi/common/include/linux/leds.h new file mode 100644 index 000000000000..89f7286f6800 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/leds.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_LEDS_H +#define _LINUXKPI_LINUX_LEDS_H + +enum led_brightness { + LED_OFF, +}; + +struct led_classdev { + const char *name; + const char *default_trigger; + int (*blink_set)(struct led_classdev *, unsigned long *, unsigned long *); + void (*brightness_set)(struct led_classdev *, enum led_brightness); + void (*led_set)(struct led_classdev *, enum led_brightness); +}; + +#endif /* _LINUXKPI_LINUX_LEDS_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/limits.h b/sys/compat/linuxkpi/common/include/linux/limits.h new file mode 100644 index 000000000000..716366033bb3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/limits.h @@ -0,0 +1,47 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_LIMITS_H +#define _LINUXKPI_LINUX_LIMITS_H + +#include <sys/types.h> +#include <sys/stdint.h> + +#define U8_MAX UINT8_MAX +#define S8_MAX INT8_MAX +#define S8_MIN INT8_MIN +#define U16_MAX UINT16_MAX +#define S16_MAX INT16_MAX +#define S16_MIN INT16_MIN +#define U32_MAX UINT32_MAX +#define S32_MAX INT32_MAX +#define S32_MIN INT32_MIN +#define U64_MAX UINT64_MAX +#define S64_MAX INT64_MAX +#define S64_MIN INT64_MIN + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/list.h b/sys/compat/linuxkpi/common/include/linux/list.h index 80ac57fecf6d..a6c74a324dac 100644 --- a/sys/compat/linuxkpi/common/include/linux/list.h +++ b/sys/compat/linuxkpi/common/include/linux/list.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_LIST_H_ #define _LINUXKPI_LINUX_LIST_H_ @@ -86,14 +84,6 @@ #define LINUX_LIST_HEAD(name) \ struct list_head name = LINUX_LIST_HEAD_INIT(name) -#ifndef LIST_HEAD_DEF -#define LIST_HEAD_DEF -struct list_head { - struct list_head *next; - struct list_head *prev; -}; -#endif - static inline void INIT_LIST_HEAD(struct list_head *list) { @@ -154,7 +144,7 @@ list_replace_init(struct list_head *old, struct list_head *new) } static inline void -linux_list_add(struct list_head *new, struct list_head *prev, +__list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { @@ -235,22 +225,32 @@ list_del_init(struct list_head *entry) #define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev) +#define list_for_each_prev_safe(p, n, h) \ + for (p = (h)->prev, n = (p)->prev; \ + p != (h); \ + p = n, n = (p)->prev) + #define list_for_each_entry_from_reverse(p, h, field) \ for (; &p->field != (h); \ p = list_prev_entry(p, field)) +#define list_for_each_rcu(p, head) \ + for (p = rcu_dereference((head)->next); \ + p != (head); \ + p = rcu_dereference((p)->next)) + static inline void list_add(struct list_head *new, struct list_head *head) { - linux_list_add(new, head, head->next); + __list_add(new, head, head->next); } static inline void list_add_tail(struct list_head *new, struct list_head *head) { - linux_list_add(new, head->prev, head); + __list_add(new, head->prev, head); } static inline void @@ -474,6 +474,20 @@ static inline int list_is_last(const struct list_head *list, return list->next == head; } +static inline size_t +list_count_nodes(const struct list_head *list) +{ + const struct list_head *lh; + size_t count; + + count = 0; + list_for_each(lh, list) { + count++; + } + + return (count); +} + #define hlist_entry(ptr, type, field) container_of(ptr, type, field) #define hlist_for_each(p, head) \ @@ -504,7 +518,12 @@ static inline int list_is_last(const struct list_head *list, (pos) && ({ n = (pos)->member.next; 1; }); \ pos = hlist_entry_safe(n, typeof(*(pos)), member)) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 +extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, + const struct list_head *a, const struct list_head *b)); +#else extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, struct list_head *a, struct list_head *b)); +#endif #endif /* _LINUXKPI_LINUX_LIST_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/lockdep.h b/sys/compat/linuxkpi/common/include/linux/lockdep.h index 2289db7756d4..93fe445f7057 100644 --- a/sys/compat/linuxkpi/common/include/linux/lockdep.h +++ b/sys/compat/linuxkpi/common/include/linux/lockdep.h @@ -25,13 +25,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_LOCKDEP_H_ #define _LINUXKPI_LINUX_LOCKDEP_H_ +#include <sys/systm.h> #include <sys/types.h> #include <sys/lock.h> @@ -48,8 +47,13 @@ struct pin_cookie { #define lockdep_set_current_reclaim_state(g) do { } while (0) #define lockdep_clear_current_reclaim_state() do { } while (0) #define lockdep_init_map(_map, _name, _key, _x) do { } while(0) +#define lockdep_register_key(key) do { } while(0) +#define lockdep_unregister_key(key) do { } while(0) #ifdef INVARIANTS +#define lockdep_assert(cond) do { WARN_ON(!(cond)); } while (0) +#define lockdep_assert_once(cond) do { WARN_ON_ONCE(!(cond)); } while (0) + #define lockdep_assert_not_held(m) do { \ struct lock_object *__lock = (struct lock_object *)(m); \ LOCK_CLASS(__lock)->lc_assert(__lock, LA_UNLOCKED); \ @@ -65,26 +69,34 @@ struct pin_cookie { LOCK_CLASS(__lock)->lc_assert(__lock, LA_LOCKED | LA_NOTRECURSED); \ } while (0) +#define lockdep_assert_none_held_once() do { } while (0) + +#else +#define lockdep_assert(cond) do { } while (0) +#define lockdep_assert_once(cond) do { } while (0) + +#define lockdep_assert_not_held(m) do { (void)(m); } while (0) +#define lockdep_assert_held(m) do { (void)(m); } while (0) +#define lockdep_assert_none_held_once() do { } while (0) + +#define lockdep_assert_held_once(m) do { (void)(m); } while (0) + +#endif + static __inline bool -lockdep_is_held(void *__m) +lockdep_is_held(void *__m __diagused) { +#ifdef INVARIANTS struct lock_object *__lock; struct thread *__td; __lock = __m; return (LOCK_CLASS(__lock)->lc_owner(__lock, &__td) != 0); -} -#define lockdep_is_held_type(_m, _t) lockdep_is_held(_m) - #else -#define lockdep_assert_not_held(m) do { (void)(m); } while (0) -#define lockdep_assert_held(m) do { (void)(m); } while (0) - -#define lockdep_assert_held_once(m) do { (void)(m); } while (0) - -#define lockdep_is_held(m) 1 -#define lockdep_is_held_type(_m, _t) 1 + return (true); #endif +} +#define lockdep_is_held_type(_m, _t) lockdep_is_held(_m) #define might_lock(m) do { } while (0) #define might_lock_read(m) do { } while (0) diff --git a/sys/compat/linuxkpi/common/include/linux/log2.h b/sys/compat/linuxkpi/common/include/linux/log2.h index 4c356136ca98..660e9adb6fa9 100644 --- a/sys/compat/linuxkpi/common/include/linux/log2.h +++ b/sys/compat/linuxkpi/common/include/linux/log2.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_LOG2_H_ #define _LINUXKPI_LINUX_LOG2_H_ @@ -35,97 +33,9 @@ #include <sys/libkern.h> -static inline unsigned long -roundup_pow_of_two(unsigned long x) -{ - return (1UL << flsl(x - 1)); -} - -static inline int -is_power_of_2(unsigned long n) -{ - return (n == roundup_pow_of_two(n)); -} - -static inline unsigned long -rounddown_pow_of_two(unsigned long x) -{ - return (1UL << (flsl(x) - 1)); -} - -#define ilog2(n) \ -( \ - __builtin_constant_p(n) ? ( \ - (n) < 1 ? -1 : \ - (n) & (1ULL << 63) ? 63 : \ - (n) & (1ULL << 62) ? 62 : \ - (n) & (1ULL << 61) ? 61 : \ - (n) & (1ULL << 60) ? 60 : \ - (n) & (1ULL << 59) ? 59 : \ - (n) & (1ULL << 58) ? 58 : \ - (n) & (1ULL << 57) ? 57 : \ - (n) & (1ULL << 56) ? 56 : \ - (n) & (1ULL << 55) ? 55 : \ - (n) & (1ULL << 54) ? 54 : \ - (n) & (1ULL << 53) ? 53 : \ - (n) & (1ULL << 52) ? 52 : \ - (n) & (1ULL << 51) ? 51 : \ - (n) & (1ULL << 50) ? 50 : \ - (n) & (1ULL << 49) ? 49 : \ - (n) & (1ULL << 48) ? 48 : \ - (n) & (1ULL << 47) ? 47 : \ - (n) & (1ULL << 46) ? 46 : \ - (n) & (1ULL << 45) ? 45 : \ - (n) & (1ULL << 44) ? 44 : \ - (n) & (1ULL << 43) ? 43 : \ - (n) & (1ULL << 42) ? 42 : \ - (n) & (1ULL << 41) ? 41 : \ - (n) & (1ULL << 40) ? 40 : \ - (n) & (1ULL << 39) ? 39 : \ - (n) & (1ULL << 38) ? 38 : \ - (n) & (1ULL << 37) ? 37 : \ - (n) & (1ULL << 36) ? 36 : \ - (n) & (1ULL << 35) ? 35 : \ - (n) & (1ULL << 34) ? 34 : \ - (n) & (1ULL << 33) ? 33 : \ - (n) & (1ULL << 32) ? 32 : \ - (n) & (1ULL << 31) ? 31 : \ - (n) & (1ULL << 30) ? 30 : \ - (n) & (1ULL << 29) ? 29 : \ - (n) & (1ULL << 28) ? 28 : \ - (n) & (1ULL << 27) ? 27 : \ - (n) & (1ULL << 26) ? 26 : \ - (n) & (1ULL << 25) ? 25 : \ - (n) & (1ULL << 24) ? 24 : \ - (n) & (1ULL << 23) ? 23 : \ - (n) & (1ULL << 22) ? 22 : \ - (n) & (1ULL << 21) ? 21 : \ - (n) & (1ULL << 20) ? 20 : \ - (n) & (1ULL << 19) ? 19 : \ - (n) & (1ULL << 18) ? 18 : \ - (n) & (1ULL << 17) ? 17 : \ - (n) & (1ULL << 16) ? 16 : \ - (n) & (1ULL << 15) ? 15 : \ - (n) & (1ULL << 14) ? 14 : \ - (n) & (1ULL << 13) ? 13 : \ - (n) & (1ULL << 12) ? 12 : \ - (n) & (1ULL << 11) ? 11 : \ - (n) & (1ULL << 10) ? 10 : \ - (n) & (1ULL << 9) ? 9 : \ - (n) & (1ULL << 8) ? 8 : \ - (n) & (1ULL << 7) ? 7 : \ - (n) & (1ULL << 6) ? 6 : \ - (n) & (1ULL << 5) ? 5 : \ - (n) & (1ULL << 4) ? 4 : \ - (n) & (1ULL << 3) ? 3 : \ - (n) & (1ULL << 2) ? 2 : \ - (n) & (1ULL << 1) ? 1 : \ - (n) & (1ULL << 0) ? 0 : \ - -1) : \ - (sizeof(n) <= 4) ? \ - fls((u32)(n)) - 1 : flsll((u64)(n)) - 1 \ -) - -#define order_base_2(x) ilog2(roundup_pow_of_two(x)) +#define is_power_of_2(n) ({ \ + __typeof(n) _n = (n); \ + _n != 0 && (_n & (_n - 1)) == 0; \ +}) #endif /* _LINUXKPI_LINUX_LOG2_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/math.h b/sys/compat/linuxkpi/common/include/linux/math.h new file mode 100644 index 000000000000..5a348a57747b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/math.h @@ -0,0 +1,76 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2013-2015 Mellanox Technologies, Ltd. + * Copyright (c) 2014-2015 François Tigeot + * Copyright (c) 2016 Matt Macy <mmacy@FreeBSD.org> + * Copyright (c) 2019 Johannes Lundberg <johalun@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MATH_H_ +#define _LINUXKPI_LINUX_MATH_H_ + +#include <linux/types.h> + +/* + * This looks more complex than it should be. But we need to + * get the type for the ~ right in round_down (it needs to be + * as wide as the result!), and we want to evaluate the macro + * arguments just once each. + */ +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + +#define DIV_ROUND_UP(x, n) howmany(x, n) +#define DIV_ROUND_UP_ULL(x, n) DIV_ROUND_UP((unsigned long long)(x), (n)) +#define DIV_ROUND_DOWN_ULL(x, n) ((unsigned long long)(x) / (n)) + +#define DIV_ROUND_CLOSEST(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) +#define DIV_ROUND_CLOSEST_ULL(x, divisor) ({ \ + __typeof(divisor) __d = (divisor); \ + unsigned long long __ret = (x) + (__d) / 2; \ + __ret /= __d; \ + __ret; \ +}) + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60600 +#define abs_diff(x, y) ({ \ + __typeof(x) _x = (x); \ + __typeof(y) _y = (y); \ + _x > _y ? _x - _y : _y - _x; \ +}) +#endif + +static inline uintmax_t +mult_frac(uintmax_t x, uintmax_t multiplier, uintmax_t divisor) +{ + uintmax_t q = (x / divisor); + uintmax_t r = (x % divisor); + + return ((q * multiplier) + ((r * multiplier) / divisor)); +} + +#endif /* _LINUXKPI_LINUX_MATH_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/math64.h b/sys/compat/linuxkpi/common/include/linux/math64.h index da8b19d37efe..a216d350570f 100644 --- a/sys/compat/linuxkpi/common/include/linux/math64.h +++ b/sys/compat/linuxkpi/common/include/linux/math64.h @@ -23,14 +23,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MATH64_H #define _LINUXKPI_LINUX_MATH64_H #include <sys/stdint.h> +#include <sys/systm.h> #define do_div(n, base) ({ \ uint32_t __base = (base); \ @@ -62,6 +61,8 @@ div64_u64(uint64_t dividend, uint64_t divisor) return (dividend / divisor); } +#define div64_ul(x, y) div64_u64((x), (y)) + static inline uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder) { @@ -100,4 +101,71 @@ div64_u64_round_up(uint64_t dividend, uint64_t divisor) #define DIV64_U64_ROUND_UP(...) \ div64_u64_round_up(__VA_ARGS__) +static inline uint64_t +mul_u64_u32_div(uint64_t x, uint32_t y, uint32_t div) +{ + const uint64_t rem = x % div; + + return ((x / div) * y + (rem * y) / div); +} + +static inline uint64_t +mul_u64_u64_div_u64(uint64_t x, uint64_t y, uint64_t z) +{ + uint64_t res, rem; + uint64_t x1, y1, y1z; + + res = rem = 0; + x1 = x; + y1z = y / z; + y1 = y - y1z * z; + + /* + * INVARIANT: x * y = res * z + rem + (y1 + y1z * z) * x1 + * INVARIANT: y1 < z + * INVARIANT: rem < z + */ + while (x1 > 0) { + /* Handle low bit. */ + if (x1 & 1) { + x1 &= ~1; + res += y1z; + rem += y1; + if ((rem < y1) || (rem >= z)) { + res += 1; + rem -= z; + } + } + + /* Shift x1 right and (y1 + y1z * z) left */ + x1 >>= 1; + if ((y1 * 2 < y1) || (y1 * 2 >= z)) { + y1z = y1z * 2 + 1; + y1 = y1 * 2 - z; + } else { + y1z *= 2; + y1 *= 2; + } + } + + KASSERT(res * z + rem == x * y, ("%s: res %ju * z %ju + rem %ju != " + "x %ju * y %ju", __func__, (uintmax_t)res, (uintmax_t)z, + (uintmax_t)rem, (uintmax_t)x, (uintmax_t)y)); + KASSERT(rem < z, ("%s: rem %ju >= z %ju\n", __func__, + (uintmax_t)rem, (uintmax_t)z)); + + return (res); +} + +static inline uint64_t +mul_u64_u32_shr(uint64_t x, uint32_t y, unsigned int shift) +{ + uint32_t hi, lo; + hi = x >> 32; + lo = x & 0xffffffff; + + return (mul_u32_u32(lo, y) >> shift) + + (mul_u32_u32(hi, y) << (32 - shift)); +} + #endif /* _LINUXKPI_LINUX_MATH64_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/mhi.h b/sys/compat/linuxkpi/common/include/linux/mhi.h new file mode 100644 index 000000000000..24b3205d6f5a --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mhi.h @@ -0,0 +1,222 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MHI_H +#define _LINUXKPI_LINUX_MHI_H + +#include <linux/types.h> + +/* Modem Host Interface (MHI) */ + +/* XXX FIXME */ +#define MHI_DB_BRST_DISABLE 0 +#define MHI_ER_CTRL 0 + +enum mhi_callback { + MHI_CB_SYS_ERROR, + MHI_CB_BW_REQ, + MHI_CB_EE_MISSION_MODE, + MHI_CB_EE_RDDM, + MHI_CB_FATAL_ERROR, + MHI_CB_IDLE, + MHI_CB_LPM_ENTER, + MHI_CB_LPM_EXIT, + MHI_CB_PENDING_DATA, +}; + +struct mhi_channel_config { + const char *name; + int auto_queue, dir, doorbell, doorbell_mode_switch, ee_mask, event_ring, lpm_notify, num, num_elements, offload_channel, pollcfg; +}; + +struct mhi_event_config { + int client_managed, data_type, hardware_event, irq, irq_moderation_ms, mode, num_elements, offload_channel, priority; +}; + +struct mhi_device { +}; + +struct mhi_controller_config { + const struct mhi_channel_config *ch_cfg; + struct mhi_event_config *event_cfg; + + int buf_len, max_channels, num_channels, num_events, use_bounce_buf; + + uint32_t timeout_ms; +}; + +struct mhi_controller { + struct device *cntrl_dev; + struct mhi_device *mhi_dev; + void *regs; + int *irq; + const char *fw_image; + const u8 *fw_data; + size_t fw_sz; + + bool fbc_download; + size_t rddm_size; + size_t sbl_size; + size_t seg_len; + size_t reg_len; + int nr_irqs; + unsigned long irq_flags; + uint32_t timeout_ms; + + dma_addr_t iova_start; + dma_addr_t iova_stop; + + int (*runtime_get)(struct mhi_controller *); + void (*runtime_put)(struct mhi_controller *); + void (*status_cb)(struct mhi_controller *, enum mhi_callback); + int (*read_reg)(struct mhi_controller *, void __iomem *, uint32_t *); + void (*write_reg)(struct mhi_controller *, void __iomem *, uint32_t); +}; + +/* -------------------------------------------------------------------------- */ + +struct mhi_controller *linuxkpi_mhi_alloc_controller(void); +void linuxkpi_mhi_free_controller(struct mhi_controller *); +int linuxkpi_mhi_register_controller(struct mhi_controller *, + const struct mhi_controller_config *); +void linuxkpi_mhi_unregister_controller(struct mhi_controller *); + +/* -------------------------------------------------------------------------- */ + +static inline struct mhi_controller * +mhi_alloc_controller(void) +{ + + /* Keep allocations internal to our implementation. */ + return (linuxkpi_mhi_alloc_controller()); +} + +static inline void +mhi_free_controller(struct mhi_controller *mhi_ctrl) +{ + + linuxkpi_mhi_free_controller(mhi_ctrl); +} + +static inline int +mhi_register_controller(struct mhi_controller *mhi_ctrl, + const struct mhi_controller_config *cfg) +{ + + return (linuxkpi_mhi_register_controller(mhi_ctrl, cfg)); +} + +static inline void +mhi_unregister_controller(struct mhi_controller *mhi_ctrl) +{ + + linuxkpi_mhi_unregister_controller(mhi_ctrl); +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_device_get_sync(struct mhi_device *mhi_dev) +{ + /* XXX TODO */ + return (-1); +} + +static __inline void +mhi_device_put(struct mhi_device *mhi_dev) +{ + /* XXX TODO */ +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_prepare_for_power_up(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_sync_power_up(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_async_power_up(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline void +mhi_power_down(struct mhi_controller *mhi_ctrl, bool x) +{ + /* XXX TODO */ +} + +static __inline void +mhi_unprepare_after_power_down(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_pm_suspend(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_pm_resume(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +static __inline int +mhi_pm_resume_force(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +mhi_force_rddm_mode(struct mhi_controller *mhi_ctrl) +{ + /* XXX TODO */ + return (0); +} + +#endif /* _LINUXKPI_LINUX_MHI_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/minmax.h b/sys/compat/linuxkpi/common/include/linux/minmax.h new file mode 100644 index 000000000000..d48958f0899f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/minmax.h @@ -0,0 +1,74 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2013-2015 Mellanox Technologies, Ltd. + * Copyright (c) 2014-2015 François Tigeot + * Copyright (c) 2015 Hans Petter Selasky <hselasky@FreeBSD.org> + * Copyright (c) 2016 Matt Macy <mmacy@FreeBSD.org> + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_MINMAX_H_ +#define _LINUXKPI_LINUX_MINMAX_H_ + +#include <linux/build_bug.h> +#include <linux/compiler.h> +#include <linux/types.h> + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +#define min3(a, b, c) min(a, min(b, c)) +#define max3(a, b, c) max(a, max(b, c)) + +#define min_not_zero(x, y) ({ \ + __typeof(x) __min1 = (x); \ + __typeof(y) __min2 = (y); \ + __min1 == 0 ? __min2 : ((__min2 == 0) ? __min1 : min(__min1, __min2));\ +}) + +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1 : __min2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1 : __max2; }) + +#define clamp_t(type, _x, min, max) min_t(type, max_t(type, _x, min), max) +#define clamp(x, lo, hi) min(max(x, lo), hi) +#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi) + +/* Swap values of a and b */ +#define swap(a, b) do { \ + __typeof(a) _swap_tmp = a; \ + a = b; \ + b = _swap_tmp; \ +} while (0) + +#endif /* _LINUXKPI_LINUX_MINMAX_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/miscdevice.h b/sys/compat/linuxkpi/common/include/linux/miscdevice.h index 1aa37454ffed..c66006a6b78e 100644 --- a/sys/compat/linuxkpi/common/include/linux/miscdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/miscdevice.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MISCDEVICE_H_ #define _LINUXKPI_LINUX_MISCDEVICE_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/mm.h b/sys/compat/linuxkpi/common/include/linux/mm.h index 5a16cf0d0a58..156b00a0c0f0 100644 --- a/sys/compat/linuxkpi/common/include/linux/mm.h +++ b/sys/compat/linuxkpi/common/include/linux/mm.h @@ -27,8 +27,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MM_H_ #define _LINUXKPI_LINUX_MM_H_ @@ -37,9 +35,13 @@ #include <linux/gfp.h> #include <linux/kernel.h> #include <linux/mm_types.h> +#include <linux/mmzone.h> #include <linux/pfn.h> #include <linux/list.h> #include <linux/mmap_lock.h> +#include <linux/overflow.h> +#include <linux/shrinker.h> +#include <linux/page.h> #include <asm/pgtable.h> @@ -55,6 +57,8 @@ CTASSERT((VM_PROT_ALL & -(1 << 8)) == 0); #define VM_WRITE VM_PROT_WRITE #define VM_EXEC VM_PROT_EXECUTE +#define VM_ACCESS_FLAGS (VM_READ | VM_WRITE | VM_EXEC) + #define VM_PFNINTERNAL (1 << 8) /* FreeBSD private flag to vm_insert_pfn() */ #define VM_MIXEDMAP (1 << 9) #define VM_NORESERVE (1 << 10) @@ -143,11 +147,28 @@ struct vm_operations_struct { }; struct sysinfo { - uint64_t totalram; - uint64_t totalhigh; - uint32_t mem_unit; + uint64_t totalram; /* Total usable main memory size */ + uint64_t freeram; /* Available memory size */ + uint64_t totalhigh; /* Total high memory size */ + uint64_t freehigh; /* Available high memory size */ + uint32_t mem_unit; /* Memory unit size in bytes */ }; +static inline struct page * +virt_to_head_page(const void *p) +{ + + return (virt_to_page(p)); +} + +static inline struct folio * +virt_to_folio(const void *p) +{ + struct page *page = virt_to_page(p); + + return (page_folio(page)); +} + /* * Compute log2 of the power of two rounded up count of pages * needed for size bytes. @@ -166,6 +187,14 @@ get_order(unsigned long size) return (order); } +/* + * Resolve a page into a virtual address: + * + * NOTE: This function only works for pages allocated by the kernel. + */ +void *linux_page_address(const struct page *); +#define page_address(page) linux_page_address(page) + static inline void * lowmem_page_address(struct page *page) { @@ -217,11 +246,15 @@ apply_to_page_range(struct mm_struct *mm, unsigned long address, int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address, unsigned long size); +int lkpi_remap_pfn_range(struct vm_area_struct *vma, + unsigned long start_addr, unsigned long start_pfn, unsigned long size, + pgprot_t prot); + static inline int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot) { - return (-ENOTSUP); + return (lkpi_remap_pfn_range(vma, addr, pfn, size, prot)); } static inline unsigned long @@ -233,44 +266,114 @@ vma_pages(struct vm_area_struct *vma) #define offset_in_page(off) ((unsigned long)(off) & (PAGE_SIZE - 1)) static inline void -set_page_dirty(struct vm_page *page) +set_page_dirty(struct page *page) { vm_page_dirty(page); } static inline void -mark_page_accessed(struct vm_page *page) +mark_page_accessed(struct page *page) { vm_page_reference(page); } static inline void -get_page(struct vm_page *page) +get_page(struct page *page) { vm_page_wire(page); } +static inline void +put_page(struct page *page) +{ + /* `__free_page()` takes care of the refcounting (unwire). */ + __free_page(page); +} + +static inline void +folio_get(struct folio *folio) +{ + get_page(&folio->page); +} + +static inline void +folio_put(struct folio *folio) +{ + put_page(&folio->page); +} + +/* + * Linux uses the following "transparent" union so that `release_pages()` + * accepts both a list of `struct page` or a list of `struct folio`. This + * relies on the fact that a `struct folio` can be cast to a `struct page`. + */ +typedef union { + struct page **pages; + struct folio **folios; +} release_pages_arg __attribute__ ((__transparent_union__)); + +void linux_release_pages(release_pages_arg arg, int nr); +#define release_pages(arg, nr) linux_release_pages((arg), (nr)) + extern long -get_user_pages(unsigned long start, unsigned long nr_pages, - int gup_flags, struct page **, - struct vm_area_struct **); +lkpi_get_user_pages(unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **); +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60500 +#define get_user_pages(start, nr_pages, gup_flags, pages) \ + lkpi_get_user_pages(start, nr_pages, gup_flags, pages) +#else +#define get_user_pages(start, nr_pages, gup_flags, pages, vmas) \ + lkpi_get_user_pages(start, nr_pages, gup_flags, pages) +#endif + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60500 +static inline long +pin_user_pages(unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **pages) +{ + return (get_user_pages(start, nr_pages, gup_flags, pages)); +} +#else +static inline long +pin_user_pages(unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **pages, + struct vm_area_struct **vmas) +{ + return (get_user_pages(start, nr_pages, gup_flags, pages, vmas)); +} +#endif extern int __get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **); +static inline int +pin_user_pages_fast(unsigned long start, int nr_pages, + unsigned int gup_flags, struct page **pages) +{ + return __get_user_pages_fast( + start, nr_pages, !!(gup_flags & FOLL_WRITE), pages); +} + extern long get_user_pages_remote(struct task_struct *, struct mm_struct *, unsigned long start, unsigned long nr_pages, - int gup_flags, struct page **, + unsigned int gup_flags, struct page **, struct vm_area_struct **); -static inline void -put_page(struct vm_page *page) +static inline long +pin_user_pages_remote(struct task_struct *task, struct mm_struct *mm, + unsigned long start, unsigned long nr_pages, + unsigned int gup_flags, struct page **pages, + struct vm_area_struct **vmas) { - vm_page_unwire(page, PQ_ACTIVE); + return get_user_pages_remote( + task, mm, start, nr_pages, gup_flags, pages, vmas); } +#define unpin_user_page(page) put_page(page) +#define unpin_user_pages(pages, npages) release_pages(pages, npages) + #define copy_highpage(to, from) pmap_copy_page(from, to) static inline pgprot_t @@ -279,7 +382,19 @@ vm_get_page_prot(unsigned long vm_flags) return (vm_flags & VM_PROT_ALL); } -static inline vm_page_t +static inline void +vm_flags_set(struct vm_area_struct *vma, unsigned long flags) +{ + vma->vm_flags |= flags; +} + +static inline void +vm_flags_clear(struct vm_area_struct *vma, unsigned long flags) +{ + vma->vm_flags &= ~flags; +} + +static inline struct page * vmalloc_to_page(const void *addr) { vm_paddr_t paddr; @@ -288,13 +403,77 @@ vmalloc_to_page(const void *addr) return (PHYS_TO_VM_PAGE(paddr)); } +static inline int +trylock_page(struct page *page) +{ + return (vm_page_tryxbusy(page)); +} + +static inline void +unlock_page(struct page *page) +{ + + vm_page_xunbusy(page); +} + extern int is_vmalloc_addr(const void *addr); void si_meminfo(struct sysinfo *si); +static inline unsigned long +totalram_pages(void) +{ + return ((unsigned long)physmem); +} + #define unmap_mapping_range(...) lkpi_unmap_mapping_range(__VA_ARGS__) void lkpi_unmap_mapping_range(void *obj, loff_t const holebegin __unused, loff_t const holelen, int even_cows __unused); #define PAGE_ALIGNED(p) __is_aligned(p, PAGE_SIZE) +void vma_set_file(struct vm_area_struct *vma, struct linux_file *file); + +static inline void +might_alloc(gfp_t gfp_mask __unused) +{ +} + +#define is_cow_mapping(flags) (false) + +static inline bool +want_init_on_free(void) +{ + return (false); +} + +static inline unsigned long +folio_pfn(struct folio *folio) +{ + return (page_to_pfn(&folio->page)); +} + +static inline long +folio_nr_pages(struct folio *folio) +{ + return (1); +} + +static inline size_t +folio_size(struct folio *folio) +{ + return (PAGE_SIZE); +} + +static inline void +folio_mark_dirty(struct folio *folio) +{ + set_page_dirty(&folio->page); +} + +static inline void * +folio_address(const struct folio *folio) +{ + return (page_address(&folio->page)); +} + #endif /* _LINUXKPI_LINUX_MM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mm_types.h b/sys/compat/linuxkpi/common/include/linux/mm_types.h index 2a7b33d15054..3ea68e97004c 100644 --- a/sys/compat/linuxkpi/common/include/linux/mm_types.h +++ b/sys/compat/linuxkpi/common/include/linux/mm_types.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MM_TYPES_H_ @@ -31,6 +29,7 @@ #include <linux/types.h> #include <linux/page.h> +#include <linux/rbtree.h> #include <linux/rwsem.h> #include <asm/atomic.h> @@ -80,4 +79,15 @@ mmgrab(struct mm_struct *mm) extern struct mm_struct *linux_get_task_mm(struct task_struct *); #define get_task_mm(task) linux_get_task_mm(task) +struct folio { + /* + * The page member must be at the beginning because `page_folio(p)` + * casts from a `struct page` to a `struct folio`. + * + * `release_pages()` also relies on this to be able to accept either a + * list of `struct page` or a list of `struct folio`. + */ + struct page page; +}; + #endif /* _LINUXKPI_LINUX_MM_TYPES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/mman.h b/sys/compat/linuxkpi/common/include/linux/mman.h new file mode 100644 index 000000000000..eff80759b4cd --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mman.h @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUX_MMAN_H +#define _LINUX_MMAN_H + +/* + * In Linux, <linux/mman.h> includes <linux/percpu_counter.h>, which includes + * <linux/smp.h>. + */ +#include <linux/smp.h> + +#endif /* _LINUX_MMAN_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/mmu_context.h b/sys/compat/linuxkpi/common/include/linux/mmu_context.h index afcc9cf07249..4c1bc61b3edb 100644 --- a/sys/compat/linuxkpi/common/include/linux/mmu_context.h +++ b/sys/compat/linuxkpi/common/include/linux/mmu_context.h @@ -21,8 +21,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MMU_CONTEXT_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/mmu_notifier.h b/sys/compat/linuxkpi/common/include/linux/mmu_notifier.h index 395f41c36a65..2492a6a3bd4f 100644 --- a/sys/compat/linuxkpi/common/include/linux/mmu_notifier.h +++ b/sys/compat/linuxkpi/common/include/linux/mmu_notifier.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MMU_NOTIFIER_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/mmzone.h b/sys/compat/linuxkpi/common/include/linux/mmzone.h new file mode 100644 index 000000000000..57d3dcac9597 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mmzone.h @@ -0,0 +1,15 @@ +/* Public domain. */ + +#ifndef _LINUX_MMZONE_H +#define _LINUX_MMZONE_H + +#include <linux/mm_types.h> +#include <linux/numa.h> +#include <linux/page-flags.h> + +#define MAX_ORDER 11 + +#define MAX_PAGE_ORDER 10 +#define NR_PAGE_ORDERS (MAX_PAGE_ORDER + 1) + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h index 441faab6df81..87bd6ec24bce 100644 --- a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h +++ b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h @@ -24,23 +24,27 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ #define __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ +#include <linux/types.h> + enum dmi_field { DMI_NONE, DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_BIOS_DATE, + DMI_BIOS_RELEASE, + DMI_EC_FIRMWARE_RELEASE, DMI_SYS_VENDOR, DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_PRODUCT_SERIAL, DMI_PRODUCT_UUID, + DMI_PRODUCT_SKU, + DMI_PRODUCT_FAMILY, DMI_BOARD_VENDOR, DMI_BOARD_NAME, DMI_BOARD_VERSION, @@ -52,6 +56,7 @@ enum dmi_field { DMI_CHASSIS_SERIAL, DMI_CHASSIS_ASSET_TAG, DMI_STRING_MAX, + DMI_OEM_STRING, }; struct dmi_strmatch { @@ -70,4 +75,9 @@ struct dmi_system_id { #define DMI_MATCH(a, b) { .slot = a, .substr = b } #define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, .exact_match = 1 } +#define I2C_NAME_SIZE 20 +#define I2C_MODULE_PREFIX "i2c:" + +#define ACPI_ID_LEN 16 + #endif /* __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 ac7dfc07e468..079dacf8df6c 100644 --- a/sys/compat/linuxkpi/common/include/linux/module.h +++ b/sys/compat/linuxkpi/common/include/linux/module.h @@ -25,16 +25,15 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MODULE_H_ #define _LINUXKPI_LINUX_MODULE_H_ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/param.h> #include <sys/module.h> +#include <sys/queue.h> +#include <sys/linker.h> #include <linux/list.h> #include <linux/compiler.h> @@ -54,7 +53,26 @@ #define MODULE_SUPPORTED_DEVICE(name) #define MODULE_IMPORT_NS(_name) +/* + * THIS_MODULE is used to differentiate modules on Linux. We currently + * completely stub out any Linux struct module usage, but THIS_MODULE is still + * used to populate the "owner" fields of various drivers. Even though we + * don't actually dereference these "owner" fields they are still used by + * drivers to check if devices/dmabufs/etc come from different modules. For + * example, during DRM GEM import some drivers check if the dmabuf's owner + * matches the dev's owner. If they match because they are both NULL drivers + * may incorrectly think two resources come from the same module. + * + * To handle this we specify an undefined symbol __this_linker_file, which + * will get special treatment from the linker when resolving. This will + * populate the usages of __this_linker_file with the linker_file_t of the + * module. + */ +#ifdef KLD_MODULE +#define THIS_MODULE ((struct module *)&__this_linker_file) +#else #define THIS_MODULE ((struct module *)0) +#endif #define __MODULE_STRING(x) __stringify(x) diff --git a/sys/compat/linuxkpi/common/include/linux/moduleparam.h b/sys/compat/linuxkpi/common/include/linux/moduleparam.h index d9485de88f56..b61bbce495ea 100644 --- a/sys/compat/linuxkpi/common/include/linux/moduleparam.h +++ b/sys/compat/linuxkpi/common/include/linux/moduleparam.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MODULEPARAM_H_ #define _LINUXKPI_LINUX_MODULEPARAM_H_ @@ -90,6 +88,15 @@ LINUXKPI_PARAM_NAME(name), LINUXKPI_PARAM_PERM(perm), &(var), 0, \ LINUXKPI_PARAM_DESC(name))) +#define LINUXKPI_PARAM_bint(name, var, perm) \ + LINUXKPI_PARAM_int(name, var, perm) + +#define LINUXKPI_PARAM_hexint(name, var, perm) \ + extern const char LINUXKPI_PARAM_DESC(name)[]; \ + LINUXKPI_PARAM_PASS(SYSCTL_UINT(LINUXKPI_PARAM_PARENT, OID_AUTO, \ + LINUXKPI_PARAM_NAME(name), LINUXKPI_PARAM_PERM(perm), &(var), 0, \ + LINUXKPI_PARAM_DESC(name))) + #define LINUXKPI_PARAM_long(name, var, perm) \ extern const char LINUXKPI_PARAM_DESC(name)[]; \ LINUXKPI_PARAM_PASS(SYSCTL_LONG(LINUXKPI_PARAM_PARENT, OID_AUTO, \ diff --git a/sys/compat/linuxkpi/common/include/linux/mutex.h b/sys/compat/linuxkpi/common/include/linux/mutex.h index 7af95e9d2dc5..6fb6a7744a89 100644 --- a/sys/compat/linuxkpi/common/include/linux/mutex.h +++ b/sys/compat/linuxkpi/common/include/linux/mutex.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_MUTEX_H_ #define _LINUXKPI_LINUX_MUTEX_H_ @@ -36,6 +34,9 @@ #include <sys/lock.h> #include <sys/sx.h> +#include <linux/kernel.h> +#include <linux/cleanup.h> +#include <linux/list.h> #include <linux/spinlock.h> #include <asm/atomic.h> diff --git a/sys/compat/linuxkpi/common/include/linux/net.h b/sys/compat/linuxkpi/common/include/linux/net.h index 5438fccb8512..a5172f3f31eb 100644 --- a/sys/compat/linuxkpi/common/include/linux/net.h +++ b/sys/compat/linuxkpi/common/include/linux/net.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_NET_H_ #define _LINUXKPI_LINUX_NET_H_ @@ -47,26 +45,27 @@ sock_create_kern(int family, int type, int proto, struct socket **res) } static inline int -sock_getname(struct socket *so, struct sockaddr *addr, int *sockaddr_len, +sock_getname(struct socket *so, struct sockaddr *sa, int *sockaddr_len, int peer) { - struct sockaddr *nam; int error; - nam = NULL; + /* + * XXXGL: we can't use sopeeraddr()/sosockaddr() here since with + * INVARIANTS they would check if supplied sockaddr has enough + * length. Such notion doesn't even exist in Linux KPI. + */ if (peer) { - if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) + if ((so->so_state & SS_ISCONNECTED) == 0) return (-ENOTCONN); - error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &nam); + error = so->so_proto->pr_peeraddr(so, sa); } else - error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &nam); + error = so->so_proto->pr_sockaddr(so, sa); if (error) return (-error); - *addr = *nam; - *sockaddr_len = addr->sa_len; + *sockaddr_len = sa->sa_len; - free(nam, M_SONAME); return (0); } diff --git a/sys/compat/linuxkpi/common/include/linux/net_dim.h b/sys/compat/linuxkpi/common/include/linux/net_dim.h index 08a8bb758c32..4fe3e39210e7 100644 --- a/sys/compat/linuxkpi/common/include/linux/net_dim.h +++ b/sys/compat/linuxkpi/common/include/linux/net_dim.h @@ -31,8 +31,6 @@ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. - * - * $FreeBSD$ */ /* This file implements Dynamic Interrupt Moderation, DIM */ diff --git a/sys/compat/linuxkpi/common/include/linux/netdev_features.h b/sys/compat/linuxkpi/common/include/linux/netdev_features.h index e21d1965bec6..fae82776b071 100644 --- a/sys/compat/linuxkpi/common/include/linux/netdev_features.h +++ b/sys/compat/linuxkpi/common/include/linux/netdev_features.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2020-2025 The FreeBSD Foundation * * Portions of this software were developed by Björn Zeeb * under sponsorship from the FreeBSD Foundation. @@ -24,8 +24,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_NETDEV_FEATURES_H_ #define _LINUXKPI_LINUX_NETDEV_FEATURES_H_ @@ -35,15 +33,20 @@ typedef uint32_t netdev_features_t; -#define NETIF_F_HIGHDMA BIT(0) -#define NETIF_F_SG BIT(1) -#define NETIF_F_IP_CSUM BIT(2) -#define NETIF_F_IPV6_CSUM BIT(3) -#define NETIF_F_TSO BIT(4) -#define NETIF_F_TSO6 BIT(5) -#define NETIF_F_RXCSUM BIT(6) -#define NETIF_F_HW_CSUM BIT(7) +#define NETIF_F_HIGHDMA BIT(0) /* Can DMA to high memory. */ +#define NETIF_F_SG BIT(1) /* Can do scatter/gather I/O. */ +#define NETIF_F_IP_CSUM BIT(2) /* Can csum TCP/UDP on IPv4. */ +#define NETIF_F_IPV6_CSUM BIT(3) /* Can csum TCP/UDP on IPv6. */ +#define NETIF_F_TSO BIT(4) /* Can do TCP over IPv4 segmentation. */ +#define NETIF_F_TSO6 BIT(5) /* Can do TCP over IPv6 segmentation. */ +#define NETIF_F_RXCSUM BIT(6) /* Can do receive csum offload. */ +#define NETIF_F_HW_CSUM BIT(7) /* Can csum packets (which?). */ +#define NETIF_F_HW_TC BIT(8) /* Can offload TC. */ + +#define NETIF_F_CSUM_MASK (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) -#define NETIF_F_CSUM_MASK (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) +#define NETIF_F_BITS \ + "\20\1HIGHDMA\2SG\3IP_CSUM\4IPV6_CSUM\5TSO\6TSO6\7RXCSUM" \ + "\10HW_CSUM\11HW_TC" #endif /* _LINUXKPI_LINUX_NETDEV_FEATURES_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/netdevice.h b/sys/compat/linuxkpi/common/include/linux/netdevice.h index f8c03f92b025..cd7d23077a62 100644 --- a/sys/compat/linuxkpi/common/include/linux/netdevice.h +++ b/sys/compat/linuxkpi/common/include/linux/netdevice.h @@ -5,7 +5,7 @@ * Copyright (c) 2013-2019 Mellanox Technologies, Ltd. * All rights reserved. * Copyright (c) 2020-2021 The FreeBSD Foundation - * Copyright (c) 2020-2021 Bjoern A. Zeeb + * Copyright (c) 2020-2022 Bjoern A. Zeeb * * Portions of this software were developed by Björn Zeeb * under sponsorship from the FreeBSD Foundation. @@ -30,8 +30,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_NETDEVICE_H #define _LINUXKPI_LINUX_NETDEVICE_H @@ -53,6 +51,7 @@ #include <net/if_var.h> #include <net/if_dl.h> +#include <linux/kernel.h> #include <linux/bitops.h> #include <linux/list.h> #include <linux/device.h> @@ -76,6 +75,10 @@ struct wireless_dev; /* net/cfg80211.h */ #define NET_NAME_UNKNOWN 0 +enum net_addr_assign_type { + NET_ADDR_RANDOM, +}; + enum netdev_tx { NETDEV_TX_OK = 0, }; @@ -96,6 +99,10 @@ enum net_device_reg_state { NETREG_REGISTERED, }; +enum tc_setup_type { + TC_SETUP_MAX_DUMMY, +}; + struct net_device_ops { int (*ndo_open)(struct net_device *); int (*ndo_stop)(struct net_device *); @@ -105,9 +112,6 @@ struct net_device_ops { }; struct net_device { - /* BSD specific for compat. */ - struct ifnet bsdifp; - /* net_device fields seen publicly. */ /* XXX can we later make some aliases to ifnet? */ char name[IFNAMSIZ]; @@ -126,6 +130,7 @@ struct net_device { unsigned long tx_errors; unsigned long tx_packets; } stats; + enum net_addr_assign_type addr_assign_type; enum net_device_reg_state reg_state; const struct ethtool_ops *ethtool_ops; const struct net_device_ops *netdev_ops; @@ -134,6 +139,7 @@ struct net_device { /* Not properly typed as-of now. */ int flags, type; int name_assign_type, needed_headroom; + int threaded; void (*priv_destructor)(struct net_device *); @@ -182,6 +188,30 @@ int unregister_inetaddr_notifier(struct notifier_block *); #define NAPI_POLL_WEIGHT 64 /* budget */ +/* + * There are drivers directly testing napi state bits, so we need to publicly + * expose them. If you ask me, those accesses should be hid behind an + * inline function and the bit flags not be directly exposed. + */ +enum napi_state_bits { + /* + * Official Linux flags encountered. + */ + NAPI_STATE_SCHED = 1, + + /* + * Our internal versions (for now). + */ + /* Do not schedule new things while we are waiting to clear things. */ + LKPI_NAPI_FLAG_DISABLE_PENDING = 0, + /* To synchronise that only one poll is ever running. */ + LKPI_NAPI_FLAG_IS_SCHEDULED = 1, + /* If trying to schedule while poll is running. Need to re-schedule. */ + LKPI_NAPI_FLAG_LOST_RACE_TRY_AGAIN = 2, + /* When shutting down forcefully prevent anything from running task/poll. */ + LKPI_NAPI_FLAG_SHUTDOWN = 3, +}; + struct napi_struct { TAILQ_ENTRY(napi_struct) entry; @@ -191,11 +221,12 @@ struct napi_struct { int budget; int rx_count; + /* * These flags mostly need to be checked/changed atomically * (multiple together in some cases). */ - volatile unsigned long _flags; + volatile unsigned long state; /* FreeBSD internal. */ /* Use task for now, so we can easily switch between direct and task. */ @@ -204,11 +235,11 @@ struct napi_struct { void linuxkpi_init_dummy_netdev(struct net_device *); void linuxkpi_netif_napi_add(struct net_device *, struct napi_struct *, - int(*napi_poll)(struct napi_struct *, int), int); + int(*napi_poll)(struct napi_struct *, int)); void linuxkpi_netif_napi_del(struct napi_struct *); bool linuxkpi_napi_schedule_prep(struct napi_struct *); void linuxkpi___napi_schedule(struct napi_struct *); -void linuxkpi_napi_schedule(struct napi_struct *); +bool linuxkpi_napi_schedule(struct napi_struct *); void linuxkpi_napi_reschedule(struct napi_struct *); bool linuxkpi_napi_complete_done(struct napi_struct *, int); bool linuxkpi_napi_complete(struct napi_struct *); @@ -218,8 +249,8 @@ void linuxkpi_napi_synchronize(struct napi_struct *); #define init_dummy_netdev(_n) \ linuxkpi_init_dummy_netdev(_n) -#define netif_napi_add(_nd, _ns, _p, _b) \ - linuxkpi_netif_napi_add(_nd, _ns, _p, _b) +#define netif_napi_add(_nd, _ns, _p) \ + linuxkpi_netif_napi_add(_nd, _ns, _p) #define netif_napi_del(_n) \ linuxkpi_netif_napi_del(_n) #define napi_schedule_prep(_n) \ @@ -241,6 +272,22 @@ void linuxkpi_napi_synchronize(struct napi_struct *); #define napi_synchronize(_n) \ linuxkpi_napi_synchronize(_n) + +static inline void +netif_napi_add_tx(struct net_device *dev, struct napi_struct *napi, + int(*napi_poll)(struct napi_struct *, int)) +{ + + netif_napi_add(dev, napi, napi_poll); +} + +static inline bool +napi_is_scheduled(struct napi_struct *napi) +{ + + return (test_bit(LKPI_NAPI_FLAG_IS_SCHEDULED, &napi->state)); +} + /* -------------------------------------------------------------------------- */ static inline void @@ -283,6 +330,134 @@ synchronize_net(void) synchronize_rcu(); } +static __inline void +netif_receive_skb_list(struct list_head *head) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static __inline int +napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) +{ + + pr_debug("%s: TODO\n", __func__); + return (-1); +} + +static __inline void +ether_setup(struct net_device *ndev) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +dev_net_set(struct net_device *ndev, void *p) +{ + + pr_debug("%s: TODO\n", __func__); +} + +static __inline int +dev_set_threaded(struct net_device *ndev, bool threaded) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENODEV); +} + +/* -------------------------------------------------------------------------- */ + +static __inline bool +netif_carrier_ok(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); + return (false); +} + +static __inline void +netif_carrier_off(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +netif_carrier_on(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +/* -------------------------------------------------------------------------- */ + +static __inline bool +netif_queue_stopped(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); + return (false); +} + +static __inline void +netif_stop_queue(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +netif_wake_queue(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +/* -------------------------------------------------------------------------- */ + +static __inline int +register_netdevice(struct net_device *ndev) +{ + + /* assert rtnl_locked? */ + pr_debug("%s: TODO\n", __func__); + return (0); +} + +static __inline int +register_netdev(struct net_device *ndev) +{ + int error; + + /* lock */ + error = register_netdevice(ndev); + /* unlock */ + pr_debug("%s: TODO\n", __func__); + return (error); +} + +static __inline void +unregister_netdev(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +unregister_netdevice(struct net_device *ndev) +{ + pr_debug("%s: TODO\n", __func__); +} + +/* -------------------------------------------------------------------------- */ + +static __inline void +netif_rx(struct sk_buff *skb) +{ + pr_debug("%s: TODO\n", __func__); +} + +static __inline void +netif_rx_ni(struct sk_buff *skb) +{ + pr_debug("%s: TODO\n", __func__); +} + /* -------------------------------------------------------------------------- */ struct net_device *linuxkpi_alloc_netdev(size_t, const char *, uint32_t, @@ -291,6 +466,8 @@ void linuxkpi_free_netdev(struct net_device *); #define alloc_netdev(_l, _n, _f, _func) \ linuxkpi_alloc_netdev(_l, _n, _f, _func) +#define alloc_netdev_dummy(_l) \ + linuxkpi_alloc_netdev(_l, "dummy", NET_NAME_UNKNOWN, NULL) #define free_netdev(_n) \ linuxkpi_free_netdev(_n) @@ -306,5 +483,6 @@ netdev_priv(const struct net_device *ndev) #define rtnl_lock() do { } while(0) #define rtnl_unlock() do { } while(0) +#define rcu_dereference_rtnl(x) READ_ONCE(x) #endif /* _LINUXKPI_LINUX_NETDEVICE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/nl80211.h b/sys/compat/linuxkpi/common/include/linux/nl80211.h index f6572cc8f6b8..f3979d3a2abc 100644 --- a/sys/compat/linuxkpi/common/include/linux/nl80211.h +++ b/sys/compat/linuxkpi/common/include/linux/nl80211.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_NL80211_H @@ -51,6 +49,7 @@ enum nl80211_feature_flags { NL80211_FEATURE_TX_POWER_INSERTION = BIT(14), NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = BIT(15), NL80211_FEATURE_AP_SCAN = BIT(16), + NL80211_FEATURE_ACTIVE_MONITOR = BIT(17), }; enum nl80211_pmsr_ftm_failure_flags { @@ -79,6 +78,13 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_160MHZ = BIT(8), NL80211_RRF_NO_HE = BIT(9), NL80211_RRF_NO_OFDM = BIT(10), + NL80211_RRF_NO_320MHZ = BIT(11), + NL80211_RRF_NO_EHT = BIT(12), + NL80211_RRF_DFS_CONCURRENT = BIT(13), + NL80211_RRF_NO_6GHZ_VLP_CLIENT = BIT(14), + NL80211_RRF_NO_6GHZ_AFC_CLIENT = BIT(15), + NL80211_RRF_PSD = BIT(16), + NL80211_RRF_ALLOW_6GHZ_VLP_AP = BIT(17), }; #define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS|NL80211_RRF_NO_HT40PLUS) @@ -127,11 +133,13 @@ enum nl80211_band { /* Keep this last. */ NUM_NL80211_BANDS -}; +} __packed; -enum nl80211_chan_flags { - /* XXX TODO */ +enum nl80211_channel_type { NL80211_CHAN_NO_HT, + NL80211_CHAN_HT20, + NL80211_CHAN_HT40PLUS, + NL80211_CHAN_HT40MINUS, }; enum nl80211_chan_width { @@ -144,6 +152,7 @@ enum nl80211_chan_width { NL80211_CHAN_WIDTH_160, NL80211_CHAN_WIDTH_5, NL80211_CHAN_WIDTH_10, + NL80211_CHAN_WIDTH_320, }; enum nl80211_iftype { @@ -159,6 +168,8 @@ enum nl80211_iftype { NL80211_IFTYPE_P2P_GO, NL80211_IFTYPE_MESH_POINT, NL80211_IFTYPE_WDS, + NL80211_IFTYPE_OCB, + NL80211_IFTYPE_NAN, /* Keep this last. */ NUM_NL80211_IFTYPES @@ -179,8 +190,6 @@ enum nl80211_tdls_operation { NL80211_TDLS_ENABLE_LINK, NL80211_TDLS_DISABLE_LINK, NL80211_TDLS_DISCOVERY_REQ, - NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, - NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, }; enum nl80211_cqm_rssi_threshold_event { @@ -215,17 +224,37 @@ enum nl80211_ext_feature { NL80211_EXT_FEATURE_AQL, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT, + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, + NL80211_EXT_FEATURE_BEACON_RATE_HT, + NL80211_EXT_FEATURE_BEACON_RATE_VHT, + NL80211_EXT_FEATURE_BEACON_RATE_HE, + NL80211_EXT_FEATURE_BSS_COLOR, + NL80211_EXT_FEATURE_FILS_DISCOVERY, + NL80211_EXT_FEATURE_RADAR_BACKGROUND, + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP, + NL80211_EXT_FEATURE_BEACON_PROTECTION, + NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT, + NL80211_EXT_FEATURE_PUNCT, + NL80211_EXT_FEATURE_DFS_CONCURRENT, + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS, + NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT, + NL80211_EXT_FEATURE_SECURE_LTF, + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK, + NL80211_EXT_FEATURE_SAE_OFFLOAD_AP, /* Keep this last. */ NUM_NL80211_EXT_FEATURES }; +/* Keep in order with lkpi_nl80211_sta_info_to_str() */ enum nl80211_sta_info { /* XXX TODO */ NL80211_STA_INFO_BEACON_RX, NL80211_STA_INFO_BEACON_SIGNAL_AVG, NL80211_STA_INFO_BSS_PARAM, NL80211_STA_INFO_CHAIN_SIGNAL, + NL80211_STA_INFO_CHAIN_SIGNAL_AVG, NL80211_STA_INFO_CONNECTED_TIME, NL80211_STA_INFO_INACTIVE_TIME, NL80211_STA_INFO_SIGNAL, @@ -238,9 +267,14 @@ enum nl80211_sta_info { NL80211_STA_INFO_TX_BITRATE, NL80211_STA_INFO_TX_PACKETS, NL80211_STA_INFO_TX_BYTES, + NL80211_STA_INFO_TX_BYTES64, + NL80211_STA_INFO_RX_BYTES64, NL80211_STA_INFO_TX_FAILED, NL80211_STA_INFO_TX_RETRIES, NL80211_STA_INFO_RX_DURATION, + NL80211_STA_INFO_TX_DURATION, + NL80211_STA_INFO_ACK_SIGNAL, + NL80211_STA_INFO_ACK_SIGNAL_AVG, }; enum nl80211_ftm_stats { @@ -294,7 +328,7 @@ enum nl80211_key_type { NL80211_KEYTYPE_PAIRWISE, }; -enum nl80211_rate_info_he_ru_alloc { +enum nl80211_he_ru_alloc { NL80211_RATE_INFO_HE_RU_ALLOC_26, NL80211_RATE_INFO_HE_RU_ALLOC_52, NL80211_RATE_INFO_HE_RU_ALLOC_106, @@ -304,12 +338,43 @@ enum nl80211_rate_info_he_ru_alloc { NL80211_RATE_INFO_HE_RU_ALLOC_2x996, }; -enum nl80211_rate_info_he_gi { +enum nl80211_he_gi { NL80211_RATE_INFO_HE_GI_0_8, NL80211_RATE_INFO_HE_GI_1_6, NL80211_RATE_INFO_HE_GI_3_2, }; +enum nl80211_he_ltf { + NL80211_RATE_INFO_HE_1XLTF, + NL80211_RATE_INFO_HE_2XLTF, + NL80211_RATE_INFO_HE_4XLTF, +}; + +enum nl80211_eht_gi { + NL80211_RATE_INFO_EHT_GI_0_8, + NL80211_RATE_INFO_EHT_GI_1_6, + NL80211_RATE_INFO_EHT_GI_3_2, +}; + +enum nl80211_eht_ru_alloc { + NL80211_RATE_INFO_EHT_RU_ALLOC_26, + NL80211_RATE_INFO_EHT_RU_ALLOC_52, + NL80211_RATE_INFO_EHT_RU_ALLOC_52P26, + NL80211_RATE_INFO_EHT_RU_ALLOC_106, + NL80211_RATE_INFO_EHT_RU_ALLOC_106P26, + NL80211_RATE_INFO_EHT_RU_ALLOC_242, + NL80211_RATE_INFO_EHT_RU_ALLOC_484, + NL80211_RATE_INFO_EHT_RU_ALLOC_484P242, + NL80211_RATE_INFO_EHT_RU_ALLOC_996, + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242, + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996, + NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996, + NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484, + NL80211_RATE_INFO_EHT_RU_ALLOC_4x996, +}; + enum nl80211_dfs_regions { NL80211_DFS_UNSET, NL80211_DFS_FCC, @@ -317,11 +382,16 @@ enum nl80211_dfs_regions { NL80211_DFS_JP, }; +enum nl80211_dfs_state { + NL80211_DFS_USABLE, +}; + enum nl80211_sar_type { NL80211_SAR_TYPE_POWER, }; #define NL80211_VHT_NSS_MAX 8 +#define NL80211_HE_NSS_MAX 8 enum nl80211_tid_cfg_attr { NL80211_TID_CONFIG_ATTR_NOACK, @@ -331,6 +401,7 @@ enum nl80211_tid_cfg_attr { NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL, NL80211_TID_CONFIG_ATTR_RETRY_LONG, NL80211_TID_CONFIG_ATTR_AMPDU_CTRL, + NL80211_TID_CONFIG_ATTR_AMSDU_CTRL, }; enum nl80211_tid_config { @@ -344,6 +415,8 @@ enum nl80211_tx_rate_setting { }; enum nl80211_txrate_gi { + NL80211_TXRATE_DEFAULT_GI, + NL80211_TXRATE_FORCE_SGI, NL80211_TXRATE_FORCE_LGI, }; @@ -353,4 +426,20 @@ enum nl80211_probe_resp_offload_support { NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P, }; +enum nl80211_user_reg_hint_type { + NL80211_USER_REG_HINT_USER, +}; + +enum nl80211_hidden_ssid { + NL80211_HIDDEN_SSID_NOT_IN_USE, +}; + +#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 +#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 + +#define NL80211_KCK_LEN 16 +#define NL80211_KCK_EXT_LEN 24 +#define NL80211_KEK_LEN 16 +#define NL80211_KEK_EXT_LEN 32 +#define NL80211_REPLAY_CTR_LEN 8 #endif /* _LINUXKPI_LINUX_NL80211_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/nodemask.h b/sys/compat/linuxkpi/common/include/linux/nodemask.h new file mode 100644 index 000000000000..7a245cc6f256 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/nodemask.h @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_NODEMASK_H_ +#define _LINUXKPI_LINUX_NODEMASK_H_ + +#include <linux/kernel.h> /* pr_debug */ + +static inline int +num_online_nodes(void) +{ + return (1); +} + +static inline int +num_possible_nodes(void) +{ + pr_debug("%s: TODO\n", __func__); + return (1); +} + +#endif /* _LINUXKPI_LINUX_NODEMASK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/nospec.h b/sys/compat/linuxkpi/common/include/linux/nospec.h new file mode 100644 index 000000000000..e8458ae8b371 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/nospec.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_NOSPEC_H_ +#define _LINUXKPI_LINUX_NOSPEC_H_ + +#define array_index_nospec(a, b) (a) + +#endif /* _LINUXKPILINUX_NOSPEC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/notifier.h b/sys/compat/linuxkpi/common/include/linux/notifier.h index cafbb64f3f3e..9302a1ce4606 100644 --- a/sys/compat/linuxkpi/common/include/linux/notifier.h +++ b/sys/compat/linuxkpi/common/include/linux/notifier.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_NOTIFIER_H_ #define _LINUXKPI_LINUX_NOTIFIER_H_ @@ -34,7 +32,10 @@ #include <sys/types.h> #include <sys/eventhandler.h> -#define NOTIFY_DONE 0 +#define NOTIFY_DONE 0 +#define NOTIFY_OK 0x0001 +#define NOTIFY_STOP_MASK 0x8000 +#define NOTIFY_BAD (NOTIFY_STOP_MASK | 0x0002) enum { NETDEV_CHANGE, diff --git a/sys/compat/linuxkpi/common/include/linux/numa.h b/sys/compat/linuxkpi/common/include/linux/numa.h index b51a92951f3f..6b227e177a64 100644 --- a/sys/compat/linuxkpi/common/include/linux/numa.h +++ b/sys/compat/linuxkpi/common/include/linux/numa.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_NUMA_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/of.h b/sys/compat/linuxkpi/common/include/linux/of.h new file mode 100644 index 000000000000..fb4554a8ddbc --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/of.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_OF_H +#define _LINUXKPI_LINUX_OF_H + +#include <linux/kobject.h> + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/overflow.h b/sys/compat/linuxkpi/common/include/linux/overflow.h index d2e15d8d2383..9ba9b9500f11 100644 --- a/sys/compat/linuxkpi/common/include/linux/overflow.h +++ b/sys/compat/linuxkpi/common/include/linux/overflow.h @@ -1,53 +1,349 @@ -/*- - * Copyright (c) 2020 The FreeBSD Foundation - * - * This software was developed by Emmanuel Vadot under sponsorship - * from the FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef __LINUXKPI_LINUX_OVERFLOW_H__ -#define __LINUXKPI_LINUX_OVERFLOW_H__ - -#include <sys/stdint.h> -#include <sys/types.h> - -#define check_add_overflow(a, b, c) \ - __builtin_add_overflow(a, b, c) - -#define check_mul_overflow(a, b, c) \ - __builtin_mul_overflow(a, b, c) - -static inline size_t -array_size(size_t x, size_t y) +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +#ifndef _LINUXKPI_LINUX_OVERFLOW_H +#define _LINUXKPI_LINUX_OVERFLOW_H + +#include <linux/compiler.h> +#include <linux/limits.h> +#ifdef __linux__ +#include <linux/const.h> +#endif + +/* + * We need to compute the minimum and maximum values representable in a given + * type. These macros may also be useful elsewhere. It would seem more obvious + * to do something like: + * + * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0) + * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0) + * + * Unfortunately, the middle expressions, strictly speaking, have + * undefined behaviour, and at least some versions of gcc warn about + * the type_max expression (but not if -fsanitize=undefined is in + * effect; in that case, the warning is deferred to runtime...). + * + * The slightly excessive casting in type_min is to make sure the + * macros also produce sensible values for the exotic type _Bool. [The + * overflow checkers only almost work for _Bool, but that's + * a-feature-not-a-bug, since people shouldn't be doing arithmetic on + * _Bools. Besides, the gcc builtins don't allow _Bool* as third + * argument.] + * + * Idea stolen from + * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html - + * credit to Christian Biere. + */ +#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) +#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) +#define type_min(T) ((T)((T)-type_max(T)-(T)1)) + +/* + * 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) { - size_t retval; + return unlikely(overflow); +} + +/** + * check_add_overflow() - Calculate addition with overflow checking + * @a: first addend + * @b: second addend + * @d: pointer to store sum + * + * Returns 0 on success. + * + * *@d holds the results of the attempted addition, but is not considered + * "safe for use" on a non-zero return value, which indicates that the + * sum has overflowed or been truncated. + */ +#define check_add_overflow(a, b, d) \ + __must_check_overflow(__builtin_add_overflow(a, b, d)) + +/** + * check_sub_overflow() - Calculate subtraction with overflow checking + * @a: minuend; value to subtract from + * @b: subtrahend; value to subtract from @a + * @d: pointer to store difference + * + * Returns 0 on success. + * + * *@d holds the results of the attempted subtraction, but is not considered + * "safe for use" on a non-zero return value, which indicates that the + * difference has underflowed or been truncated. + */ +#define check_sub_overflow(a, b, d) \ + __must_check_overflow(__builtin_sub_overflow(a, b, d)) + +/** + * check_mul_overflow() - Calculate multiplication with overflow checking + * @a: first factor + * @b: second factor + * @d: pointer to store product + * + * Returns 0 on success. + * + * *@d holds the results of the attempted multiplication, but is not + * considered "safe for use" on a non-zero return value, which indicates + * that the product has overflowed or been truncated. + */ +#define check_mul_overflow(a, b, d) \ + __must_check_overflow(__builtin_mul_overflow(a, b, d)) + +/** + * check_shl_overflow() - Calculate a left-shifted value and check overflow + * @a: Value to be shifted + * @s: How many bits left to shift + * @d: Pointer to where to store the result + * + * Computes *@d = (@a << @s) + * + * Returns true if '*@d' cannot hold the result or when '@a << @s' doesn't + * make sense. Example conditions: + * + * - '@a << @s' causes bits to be lost when stored in *@d. + * - '@s' is garbage (e.g. negative) or so large that the result of + * '@a << @s' is guaranteed to be 0. + * - '@a' is negative. + * - '@a << @s' sets the sign bit, if any, in '*@d'. + * + * '*@d' will hold the results of the attempted shift, but is not + * considered "safe for use" if true is returned. + */ +#define check_shl_overflow(a, s, d) __must_check_overflow(({ \ + typeof(a) _a = a; \ + typeof(s) _s = s; \ + typeof(d) _d = d; \ + u64 _a_full = _a; \ + unsigned int _to_shift = \ + is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \ + *_d = (_a_full << _to_shift); \ + (_to_shift != _s || is_negative(*_d) || is_negative(_a) || \ + (*_d >> _to_shift) != _a); \ +})) + +#define __overflows_type_constexpr(x, T) ( \ + is_unsigned_type(typeof(x)) ? \ + (x) > type_max(typeof(T)) : \ + is_unsigned_type(typeof(T)) ? \ + (x) < 0 || (x) > type_max(typeof(T)) : \ + (x) < type_min(typeof(T)) || (x) > type_max(typeof(T))) + +#define __overflows_type(x, T) ({ \ + typeof(T) v = 0; \ + check_add_overflow((x), v, &v); \ +}) + +/** + * overflows_type - helper for checking the overflows between value, variables, + * or data type + * + * @n: source constant value or variable to be checked + * @T: destination variable or data type proposed to store @x + * + * Compares the @x expression for whether or not it can safely fit in + * the storage of the type in @T. @x and @T can have different types. + * If @x is a constant expression, this will also resolve to a constant + * expression. + * + * Returns: true if overflow can occur, false otherwise. + */ +#define overflows_type(n, T) \ + __builtin_choose_expr(__is_constexpr(n), \ + __overflows_type_constexpr(n, T), \ + __overflows_type(n, T)) - if (__builtin_mul_overflow(x, y, &retval)) - retval = SIZE_MAX; - return (retval); +/** + * castable_to_type - like __same_type(), but also allows for casted literals + * + * @n: variable or constant value + * @T: variable or data type + * + * Unlike the __same_type() macro, this allows a constant value as the + * first argument. If this value would not overflow into an assignment + * of the second argument's type, it returns true. Otherwise, this falls + * back to __same_type(). + */ +#define castable_to_type(n, T) \ + __builtin_choose_expr(__is_constexpr(n), \ + !__overflows_type_constexpr(n, T), \ + __same_type(n, T)) + +/** + * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX + * @factor1: first factor + * @factor2: second factor + * + * Returns: calculate @factor1 * @factor2, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. The + * lvalue must be size_t to avoid implicit type conversion. + */ +static inline size_t __must_check size_mul(size_t factor1, size_t factor2) +{ + size_t bytes; + + if (check_mul_overflow(factor1, factor2, &bytes)) + return SIZE_MAX; + + return bytes; +} + +/** + * size_add() - Calculate size_t addition with saturation at SIZE_MAX + * @addend1: first addend + * @addend2: second addend + * + * Returns: calculate @addend1 + @addend2, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. The + * lvalue must be size_t to avoid implicit type conversion. + */ +static inline size_t __must_check size_add(size_t addend1, size_t addend2) +{ + size_t bytes; + + if (check_add_overflow(addend1, addend2, &bytes)) + return SIZE_MAX; + + return bytes; +} + +/** + * size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX + * @minuend: value to subtract from + * @subtrahend: value to subtract from @minuend + * + * Returns: calculate @minuend - @subtrahend, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. For + * composition with the size_add() and size_mul() helpers, neither + * argument may be SIZE_MAX (or the result with be forced to SIZE_MAX). + * The lvalue must be size_t to avoid implicit type conversion. + */ +static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) +{ + size_t bytes; + + if (minuend == SIZE_MAX || subtrahend == SIZE_MAX || + check_sub_overflow(minuend, subtrahend, &bytes)) + return SIZE_MAX; + + return bytes; } -#endif /* __LINUXKPI_LINUX_OVERFLOW_H__ */ +/** + * array_size() - Calculate size of 2-dimensional array. + * @a: dimension one + * @b: dimension two + * + * Calculates size of 2-dimensional array: @a * @b. + * + * Returns: number of bytes needed to represent the array or SIZE_MAX on + * overflow. + */ +#define array_size(a, b) size_mul(a, b) + +/** + * array3_size() - Calculate size of 3-dimensional array. + * @a: dimension one + * @b: dimension two + * @c: dimension three + * + * Calculates size of 3-dimensional array: @a * @b * @c. + * + * Returns: number of bytes needed to represent the array or SIZE_MAX on + * overflow. + */ +#define array3_size(a, b, c) size_mul(size_mul(a, b), c) + +/** + * flex_array_size() - Calculate size of a flexible array member + * within an enclosing structure. + * @p: Pointer to the structure. + * @member: Name of the flexible array member. + * @count: Number of elements in the array. + * + * Calculates size of a flexible array of @count number of @member + * elements, at the end of structure @p. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define flex_array_size(p, member, count) \ + __builtin_choose_expr(__is_constexpr(count), \ + (count) * sizeof(*(p)->member) + __must_be_array((p)->member), \ + size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member))) + +/** + * struct_size() - Calculate size of structure with trailing flexible array. + * @p: Pointer to the structure. + * @member: Name of the array member. + * @count: Number of elements in the array. + * + * Calculates size of memory needed for structure of @p followed by an + * array of @count number of @member elements. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define struct_size(p, member, count) \ + __builtin_choose_expr(__is_constexpr(count), \ + sizeof(*(p)) + flex_array_size(p, member, count), \ + size_add(sizeof(*(p)), flex_array_size(p, member, count))) + +/** + * struct_size_t() - Calculate size of structure with trailing flexible array + * @type: structure type name. + * @member: Name of the array member. + * @count: Number of elements in the array. + * + * Calculates size of memory needed for structure @type followed by an + * array of @count number of @member elements. Prefer using struct_size() + * when possible instead, to keep calculations associated with a specific + * instance variable of type @type. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define struct_size_t(type, member, count) \ + struct_size((type *)NULL, member, count) + +/** + * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family. + * Enables caller macro to pass (different) initializer. + * + * @type: structure type name, including "struct" keyword. + * @name: Name for a variable to define. + * @member: Name of the array member. + * @count: Number of elements in the array; must be compile-time const. + * @initializer: initializer expression (could be empty for no init). + */ +#define _DEFINE_FLEX(type, name, member, count, initializer) \ + _Static_assert(__builtin_constant_p(count), \ + "onstack flex array members require compile-time const count"); \ + union { \ + u8 bytes[struct_size_t(type, member, count)]; \ + type obj; \ + } name##_u initializer; \ + type *name = (type *)&name##_u + +/** + * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing + * flexible array member. + * + * @type: structure type name, including "struct" keyword. + * @name: Name for a variable to define. + * @member: Name of the array member. + * @count: Number of elements in the array; must be compile-time const. + * + * Define a zeroed, on-stack, instance of @type structure with a trailing + * flexible array member. + * Use __struct_size(@name) to get compile-time size of it afterwards. + */ +#define DEFINE_FLEX(type, name, member, count) \ + _DEFINE_FLEX(type, name, member, count, = {}) + +#endif /* _LINUXKPI_LINUX_OVERFLOW_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/page-flags.h b/sys/compat/linuxkpi/common/include/linux/page-flags.h new file mode 100644 index 000000000000..a22b3a24c330 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/page-flags.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PAGEFLAGS_H_ +#define _LINUXKPI_LINUX_PAGEFLAGS_H_ + +#include <linux/mm_types.h> + +#define PageHighMem(p) (0) + +#define page_folio(p) \ + (_Generic((p), \ + const struct page *: (const struct folio *)(p), \ + struct page *: (struct folio *)(p))) + +#endif /* _LINUXKPI_LINUX_PAGEFLAGS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/page.h b/sys/compat/linuxkpi/common/include/linux/page.h index b582966b49c3..37ab593a64e9 100644 --- a/sys/compat/linuxkpi/common/include/linux/page.h +++ b/sys/compat/linuxkpi/common/include/linux/page.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PAGE_H_ #define _LINUXKPI_LINUX_PAGE_H_ @@ -74,6 +72,7 @@ pgprot2cachemode(pgprot_t prot) return (VM_MEMATTR_DEFAULT); } +#define page_to_virt(page) linux_page_address(page) #define virt_to_page(x) PHYS_TO_VM_PAGE(vtophys(x)) #define page_to_pfn(pp) (VM_PAGE_TO_PHYS(pp) >> PAGE_SHIFT) #define pfn_to_page(pfn) (PHYS_TO_VM_PAGE((pfn) << PAGE_SHIFT)) diff --git a/sys/compat/linuxkpi/common/include/linux/pagemap.h b/sys/compat/linuxkpi/common/include/linux/pagemap.h index e25fa743f9a7..cb6a1820ea8b 100644 --- a/sys/compat/linuxkpi/common/include/linux/pagemap.h +++ b/sys/compat/linuxkpi/common/include/linux/pagemap.h @@ -24,22 +24,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PAGEMAP_H_ #define _LINUXKPI_LINUX_PAGEMAP_H_ #include <linux/mm.h> +#include <linux/highmem.h> +#include <linux/vmalloc.h> + +struct folio_batch; + +#define invalidate_mapping_pages(...) \ + linux_invalidate_mapping_pages(__VA_ARGS__) + +unsigned long linux_invalidate_mapping_pages(vm_object_t obj, pgoff_t start, + pgoff_t end); static inline void -release_pages(struct page **pages, int nr) +mapping_clear_unevictable(vm_object_t mapping) { - int i; - - for (i = 0; i < nr; i++) - put_page(pages[i]); } #endif diff --git a/sys/compat/linuxkpi/common/include/linux/pagevec.h b/sys/compat/linuxkpi/common/include/linux/pagevec.h new file mode 100644 index 000000000000..0a952e965b5a --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/pagevec.h @@ -0,0 +1,137 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_PAGEVEC_H_ +#define _LINUXKPI_LINUX_PAGEVEC_H_ + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/errno.h> + +#include <linux/pagemap.h> + +#define PAGEVEC_SIZE 15 + +struct pagevec { + uint8_t nr; + struct page *pages[PAGEVEC_SIZE]; +}; + +static inline unsigned int +pagevec_space(struct pagevec *pvec) +{ + return PAGEVEC_SIZE - pvec->nr; +} + +static inline void +pagevec_init(struct pagevec *pvec) +{ + pvec->nr = 0; +} + +static inline void +pagevec_reinit(struct pagevec *pvec) +{ + pvec->nr = 0; +} + +static inline unsigned int +pagevec_count(struct pagevec *pvec) +{ + return pvec->nr; +} + +static inline unsigned int +pagevec_add(struct pagevec *pvec, struct page *page) +{ + pvec->pages[pvec->nr++] = page; + return PAGEVEC_SIZE - pvec->nr; +} + +static inline void +__pagevec_release(struct pagevec *pvec) +{ + release_pages(pvec->pages, pagevec_count(pvec)); + pagevec_reinit(pvec); +} + +static inline void +pagevec_release(struct pagevec *pvec) +{ + if (pagevec_count(pvec)) + __pagevec_release(pvec); +} + +static inline void +check_move_unevictable_pages(struct pagevec *pvec) +{ +} + +/* + * struct folio + * + * On Linux, `struct folio` replaces `struct page`. To manage a list of folios, + * there is `struct folio_batch` on top of this, which replaces `struct + * pagevec` above. + * + * Here is the original description when `struct folio` was added to the Linux + * kernel: + * "A struct folio is a new abstraction to replace the venerable struct page. + * A function which takes a struct folio argument declares that it will + * operate on the entire (possibly compound) page, not just PAGE_SIZE bytes. + * In return, the caller guarantees that the pointer it is passing does not + * point to a tail page. No change to generated code." + */ + +struct folio; + +struct folio_batch { + uint8_t nr; + struct folio *folios[PAGEVEC_SIZE]; +}; + +static inline void +folio_batch_init(struct folio_batch *fbatch) +{ + fbatch->nr = 0; +} + +static inline void +folio_batch_reinit(struct folio_batch *fbatch) +{ + fbatch->nr = 0; +} + +static inline unsigned int +folio_batch_count(struct folio_batch *fbatch) +{ + return (fbatch->nr); +} + +static inline unsigned int +folio_batch_space(struct folio_batch *fbatch) +{ + return (PAGEVEC_SIZE - fbatch->nr); +} + +static inline unsigned int +folio_batch_add(struct folio_batch *fbatch, struct folio *folio) +{ + KASSERT( + fbatch->nr < PAGEVEC_SIZE, + ("struct folio_batch %p is full", fbatch)); + + fbatch->folios[fbatch->nr++] = folio; + + return (folio_batch_space(fbatch)); +} + +void __folio_batch_release(struct folio_batch *fbatch); + +static inline void +folio_batch_release(struct folio_batch *fbatch) +{ + if (folio_batch_count(fbatch)) + __folio_batch_release(fbatch); +} + +#endif /* _LINUXKPI_LINUX_PAGEVEC_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index 695965673050..af19829f1cbb 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -4,7 +4,7 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. * All rights reserved. - * Copyright (c) 2020-2021 The FreeBSD Foundation + * Copyright (c) 2020-2022 The FreeBSD Foundation * * Portions of this software were developed by Björn Zeeb * under sponsorship from the FreeBSD Foundation. @@ -29,8 +29,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PCI_H_ #define _LINUXKPI_LINUX_PCI_H_ @@ -38,13 +36,13 @@ #define CONFIG_PCI_MSI #include <linux/types.h> +#include <linux/device/driver.h> #include <sys/param.h> #include <sys/bus.h> #include <sys/module.h> #include <sys/nv.h> #include <sys/pciio.h> -#include <sys/rman.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> #include <dev/pci/pci_private.h> @@ -57,10 +55,13 @@ #include <linux/compiler.h> #include <linux/errno.h> #include <asm/atomic.h> +#include <asm/memtype.h> #include <linux/device.h> #include <linux/pci_ids.h> #include <linux/pm.h> +#include <linux/kernel.h> /* pr_debug */ + struct pci_device_id { uint32_t vendor; uint32_t device; @@ -71,6 +72,10 @@ struct pci_device_id { uintptr_t driver_data; }; +#define MODULE_DEVICE_TABLE_BUS_pci(_bus, _table) \ +MODULE_PNP_INFO("U32:vendor;U32:device;V32:subvendor;V32:subdevice", \ + _bus, lkpi_ ## _table, _table, nitems(_table) - 1) + /* Linux has an empty element at the end of the ID table -> nitems() - 1. */ #define MODULE_DEVICE_TABLE(_bus, _table) \ \ @@ -84,11 +89,10 @@ static driver_t _ ## _bus ## _ ## _table ## _driver = { \ 0 \ }; \ \ -DRIVER_MODULE(lkpi_ ## _table, pci, _ ## _bus ## _ ## _table ## _driver,\ +DRIVER_MODULE(lkpi_ ## _table, _bus, _ ## _bus ## _ ## _table ## _driver,\ 0, 0); \ \ -MODULE_PNP_INFO("U32:vendor;U32:device;V32:subvendor;V32:subdevice", \ - _bus, lkpi_ ## _table, _table, nitems(_table) - 1) +MODULE_DEVICE_TABLE_BUS_ ## _bus(_bus, _table) #define PCI_ANY_ID -1U @@ -96,6 +100,7 @@ MODULE_PNP_INFO("U32:vendor;U32:device;V32:subvendor;V32:subdevice", \ #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) #define PCI_BUS_NUM(devfn) (((devfn) >> 8) & 0xff) +#define PCI_DEVID(bus, devfn) ((((uint16_t)(bus)) << 8) | (devfn)) #define PCI_VDEVICE(_vendor, _device) \ .vendor = PCI_VENDOR_ID_##_vendor, .device = (_device), \ @@ -106,9 +111,18 @@ MODULE_PNP_INFO("U32:vendor;U32:device;V32:subvendor;V32:subdevice", \ #define to_pci_dev(n) container_of(n, struct pci_dev, dev) -#define PCI_VENDOR_ID PCIR_DEVVENDOR +#define PCI_STD_NUM_BARS 6 +#define PCI_BASE_ADDRESS_0 PCIR_BARS +#define PCI_BASE_ADDRESS_MEM_TYPE_64 PCIM_BAR_MEM_64 +#define PCI_VENDOR_ID PCIR_VENDOR +#define PCI_DEVICE_ID PCIR_DEVICE #define PCI_COMMAND PCIR_COMMAND #define PCI_COMMAND_INTX_DISABLE PCIM_CMD_INTxDIS +#define PCI_COMMAND_MEMORY PCIM_CMD_MEMEN +#define PCI_PRIMARY_BUS PCIR_PRIBUS_1 +#define PCI_SECONDARY_BUS PCIR_SECBUS_1 +#define PCI_SUBORDINATE_BUS PCIR_SUBBUS_1 +#define PCI_SEC_LATENCY_TIMER PCIR_SECLAT_1 #define PCI_EXP_DEVCTL PCIER_DEVICE_CTL /* Device Control */ #define PCI_EXP_LNKCTL PCIER_LINK_CTL /* Link Control */ #define PCI_EXP_LNKCTL_ASPM_L0S PCIEM_LINK_CTL_ASPMC_L0S @@ -142,24 +156,38 @@ MODULE_PNP_INFO("U32:vendor;U32:device;V32:subvendor;V32:subdevice", \ #define PCI_EXP_TYPE_DOWNSTREAM PCIEM_TYPE_DOWNSTREAM_PORT /* Downstream Port */ #define PCI_EXP_FLAGS_SLOT PCIEM_FLAGS_SLOT /* Slot implemented */ #define PCI_EXP_TYPE_RC_EC PCIEM_TYPE_ROOT_EC /* Root Complex Event Collector */ +#define PCI_EXP_LNKSTA_CLS PCIEM_LINK_STA_SPEED +#define PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP_SLS_2_5GB 0x01 /* Supported Link Speed 2.5GT/s */ #define PCI_EXP_LNKCAP_SLS_5_0GB 0x02 /* Supported Link Speed 5.0GT/s */ -#define PCI_EXP_LNKCAP_SLS_8_0GB 0x04 /* Supported Link Speed 8.0GT/s */ -#define PCI_EXP_LNKCAP_SLS_16_0GB 0x08 /* Supported Link Speed 16.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_8_0GB 0x03 /* Supported Link Speed 8.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_16_0GB 0x04 /* Supported Link Speed 16.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_32_0GB 0x05 /* Supported Link Speed 32.0GT/s */ +#define PCI_EXP_LNKCAP_SLS_64_0GB 0x06 /* Supported Link Speed 64.0GT/s */ #define PCI_EXP_LNKCAP_MLW 0x03f0 /* Maximum Link Width */ #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */ #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP2_SLS_16_0GB 0x10 /* Supported Link Speed 16.0GT/s */ +#define PCI_EXP_LNKCAP2_SLS_32_0GB 0x20 /* Supported Link Speed 32.0GT/s */ +#define PCI_EXP_LNKCAP2_SLS_64_0GB 0x40 /* Supported Link Speed 64.0GT/s */ #define PCI_EXP_LNKCTL2_TLS 0x000f #define PCI_EXP_LNKCTL2_TLS_2_5GT 0x0001 /* Supported Speed 2.5GT/s */ #define PCI_EXP_LNKCTL2_TLS_5_0GT 0x0002 /* Supported Speed 5GT/s */ #define PCI_EXP_LNKCTL2_TLS_8_0GT 0x0003 /* Supported Speed 8GT/s */ #define PCI_EXP_LNKCTL2_TLS_16_0GT 0x0004 /* Supported Speed 16GT/s */ #define PCI_EXP_LNKCTL2_TLS_32_0GT 0x0005 /* Supported Speed 32GT/s */ +#define PCI_EXP_LNKCTL2_TLS_64_0GT 0x0006 /* Supported Speed 64GT/s */ #define PCI_EXP_LNKCTL2_ENTER_COMP 0x0010 /* Enter Compliance */ #define PCI_EXP_LNKCTL2_TX_MARGIN 0x0380 /* Transmit Margin */ +#define PCI_MSI_ADDRESS_LO PCIR_MSI_ADDR +#define PCI_MSI_ADDRESS_HI PCIR_MSI_ADDR_HIGH +#define PCI_MSI_FLAGS PCIR_MSI_CTRL +#define PCI_MSI_FLAGS_ENABLE PCIM_MSICTRL_MSI_ENABLE +#define PCI_MSIX_FLAGS PCIR_MSIX_CTRL +#define PCI_MSIX_FLAGS_ENABLE PCIM_MSIXCTRL_MSIX_ENABLE + #define PCI_EXP_LNKCAP_CLKPM 0x00040000 #define PCI_EXP_DEVSTA_TRPND 0x0020 @@ -173,6 +201,8 @@ enum pci_bus_speed { PCIE_SPEED_5_0GT, PCIE_SPEED_8_0GT, PCIE_SPEED_16_0GT, + PCIE_SPEED_32_0GT, + PCIE_SPEED_64_0GT, }; enum pcie_link_width { @@ -201,6 +231,10 @@ typedef int pci_power_t; #define PCI_POWER_ERROR PCI_POWERSTATE_UNKNOWN +extern const char *pci_power_names[6]; + +#define PCI_ERR_UNCOR_STATUS PCIR_AER_UC_STATUS +#define PCI_ERR_COR_STATUS PCIR_AER_COR_STATUS #define PCI_ERR_ROOT_COMMAND PCIR_AER_ROOTERR_CMD #define PCI_ERR_ROOT_ERR_SRC PCIR_AER_COR_SOURCE_ID @@ -210,9 +244,14 @@ typedef int pci_power_t; #define PCI_L1SS_CTL1 0x8 #define PCI_L1SS_CTL1_L1SS_MASK 0xf -#define PCI_IRQ_LEGACY 0x01 +#define PCI_IRQ_INTX 0x01 #define PCI_IRQ_MSI 0x02 #define PCI_IRQ_MSIX 0x04 +#define PCI_IRQ_ALL_TYPES (PCI_IRQ_MSIX|PCI_IRQ_MSI|PCI_IRQ_INTX) + +#if defined(LINUXKPI_VERSION) && (LINUXKPI_VERSION <= 61000) +#define PCI_IRQ_LEGACY PCI_IRQ_INTX +#endif struct pci_dev; @@ -240,6 +279,7 @@ struct pci_driver { struct pci_bus { struct pci_dev *self; + /* struct pci_bus *parent */ int domain; int number; }; @@ -250,29 +290,34 @@ extern spinlock_t pci_lock; #define __devexit_p(x) x -#define module_pci_driver(_driver) \ - \ -static inline int \ -_pci_init(void) \ -{ \ - \ - return (linux_pci_register_driver(&_driver)); \ -} \ - \ -static inline void \ -_pci_exit(void) \ -{ \ - \ - linux_pci_unregister_driver(&_driver); \ -} \ - \ -module_init(_pci_init); \ -module_exit(_pci_exit) +#define module_pci_driver(_drv) \ + module_driver(_drv, linux_pci_register_driver, linux_pci_unregister_driver) + +struct msi_msg { + uint32_t data; +}; + +struct pci_msi_desc { + struct { + bool is_64; + } msi_attrib; +}; + +struct msi_desc { + struct msi_msg msg; + struct pci_msi_desc pci; +}; + +struct msix_entry { + int entry; + int vector; +}; /* * If we find drivers accessing this from multiple KPIs we may have to * refcount objects of this structure. */ +struct resource; struct pci_mmio_region { TAILQ_ENTRY(pci_mmio_region) next; struct resource *res; @@ -286,6 +331,7 @@ struct pci_dev { struct pci_driver *pdrv; struct pci_bus *bus; struct pci_dev *root; + pci_power_t current_state; uint16_t device; uint16_t vendor; uint16_t subsystem_vendor; @@ -294,39 +340,65 @@ struct pci_dev { unsigned int devfn; uint32_t class; uint8_t revision; + uint8_t msi_cap; + uint8_t msix_cap; bool managed; /* devres "pcim_*(). */ bool want_iomap_res; bool msi_enabled; bool msix_enabled; phys_addr_t rom; size_t romlen; + struct msi_desc **msi_desc; + char *path_name; + spinlock_t pcie_cap_lock; TAILQ_HEAD(, pci_mmio_region) mmio; }; -/* We need some meta-struct to keep track of these for devres. */ -struct pci_devres { - bool enable_io; - /* PCIR_MAX_BAR_0 + 1 = 6 => BIT(0..5). */ - uint8_t region_mask; - struct resource *region_table[PCIR_MAX_BAR_0 + 1]; /* Not needed. */ -}; -struct pcim_iomap_devres { - void *mmio_table[PCIR_MAX_BAR_0 + 1]; - struct resource *res_table[PCIR_MAX_BAR_0 + 1]; -}; - int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name); int pci_alloc_irq_vectors(struct pci_dev *pdev, int minv, int maxv, unsigned int flags); +bool pci_device_is_present(struct pci_dev *pdev); + +int linuxkpi_pcim_enable_device(struct pci_dev *pdev); +void __iomem **linuxkpi_pcim_iomap_table(struct pci_dev *pdev); +void *linuxkpi_pci_iomap_range(struct pci_dev *pdev, int mmio_bar, + unsigned long mmio_off, unsigned long mmio_size); +void *linuxkpi_pci_iomap(struct pci_dev *pdev, int mmio_bar, int mmio_size); +void linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res); +int linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, + const char *name); +int linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name); +void linuxkpi_pci_release_region(struct pci_dev *pdev, int bar); +void linuxkpi_pci_release_regions(struct pci_dev *pdev); +int linuxkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, + int nreq); /* Internal helper function(s). */ struct pci_dev *lkpinew_pci_dev(device_t); -struct pci_devres *lkpi_pci_devres_get_alloc(struct pci_dev *pdev); void lkpi_pci_devres_release(struct device *, void *); -struct resource *_lkpi_pci_iomap(struct pci_dev *pdev, int bar, int mmio_size); -struct pcim_iomap_devres *lkpi_pcim_iomap_devres_find(struct pci_dev *pdev); -void lkpi_pcim_iomap_table_release(struct device *, void *); +struct pci_dev *lkpi_pci_get_device(uint16_t, uint16_t, struct pci_dev *); +struct msi_desc *lkpi_pci_msi_desc_alloc(int); +struct device *lkpi_pci_find_irq_dev(unsigned int irq); +int _lkpi_pci_enable_msi_range(struct pci_dev *pdev, int minvec, int maxvec); + +#define pci_err(pdev, fmt, ...) \ + dev_err(&(pdev)->dev, fmt, ##__VA_ARGS__) +#define pci_info(pdev, fmt, ...) \ + dev_info(&(pdev)->dev, fmt, ##__VA_ARGS__) + +static inline bool +dev_is_pci(struct device *dev) +{ + + return (device_get_devclass(dev->bsddev) == devclass_find("pci")); +} + +static inline uint16_t +pci_dev_id(struct pci_dev *pdev) +{ + return (PCI_DEVID(pdev->bus->number, pdev->devfn)); +} static inline int pci_resource_type(struct pci_dev *pdev, int bar) @@ -343,56 +415,6 @@ pci_resource_type(struct pci_dev *pdev, int bar) return (SYS_RES_MEMORY); } -struct resource_list_entry *linux_pci_reserve_bar(struct pci_dev *pdev, - struct resource_list *rl, int type, int rid); - -static inline struct resource_list_entry * -linux_pci_get_rle(struct pci_dev *pdev, int type, int rid, bool reserve_bar) -{ - struct pci_devinfo *dinfo; - struct resource_list *rl; - struct resource_list_entry *rle; - - dinfo = device_get_ivars(pdev->dev.bsddev); - rl = &dinfo->resources; - rle = resource_list_find(rl, type, rid); - /* Reserve resources for this BAR if needed. */ - if (rle == NULL && reserve_bar) - rle = linux_pci_reserve_bar(pdev, rl, type, rid); - return (rle); -} - -static inline struct resource_list_entry * -linux_pci_get_bar(struct pci_dev *pdev, int bar, bool reserve) -{ - int type; - - type = pci_resource_type(pdev, bar); - if (type < 0) - return (NULL); - bar = PCIR_BAR(bar); - return (linux_pci_get_rle(pdev, type, bar, reserve)); -} - -static inline struct device * -linux_pci_find_irq_dev(unsigned int irq) -{ - struct pci_dev *pdev; - struct device *found; - - found = NULL; - spin_lock(&pci_lock); - list_for_each_entry(pdev, &pci_devices, links) { - if (irq == pdev->dev.irq || - (irq >= pdev->dev.irq_start && irq < pdev->dev.irq_end)) { - found = &pdev->dev; - break; - } - } - spin_unlock(&pci_lock); - return (found); -} - /* * All drivers just seem to want to inspect the type not flags. */ @@ -410,8 +432,7 @@ pci_resource_flags(struct pci_dev *pdev, int bar) static inline const char * pci_name(struct pci_dev *d) { - - return device_get_desc(d->dev.bsddev); + return d->path_name; } static inline void * @@ -507,7 +528,20 @@ pci_upstream_bridge(struct pci_dev *pdev) if (pdev == pdev->bus->self) { device_t bridge; - bridge = device_get_parent(pdev->dev.bsddev); + /* + * In the case of DRM drivers, the passed device is a child of + * `vgapci`. We want to start the lookup from `vgapci`, so the + * parent of the passed `drmn`. + * + * We can use the `isdrm` flag to determine this. + */ + bridge = pdev->dev.bsddev; + if (pdev->pdrv != NULL && pdev->pdrv->isdrm) + bridge = device_get_parent(bridge); + if (bridge == NULL) + goto done; + + bridge = device_get_parent(bridge); if (bridge == NULL) goto done; bridge = device_get_parent(bridge); @@ -527,73 +561,10 @@ done: return (pdev->bus->self); } -static inline struct pci_devres * -lkpi_pci_devres_find(struct pci_dev *pdev) -{ - - if (!pdev->managed) - return (NULL); - - return (lkpi_pci_devres_get_alloc(pdev)); -} - -static inline void -pci_release_region(struct pci_dev *pdev, int bar) -{ - struct resource_list_entry *rle; - struct pci_devres *dr; - struct pci_mmio_region *mmio, *p; - - if ((rle = linux_pci_get_bar(pdev, bar, false)) == NULL) - return; - - /* - * As we implicitly track the requests we also need to clear them on - * release. Do clear before resource release. - */ - dr = lkpi_pci_devres_find(pdev); - if (dr != NULL) { - KASSERT(dr->region_table[bar] == rle->res, ("%s: pdev %p bar %d" - " region_table res %p != rel->res %p\n", __func__, pdev, - bar, dr->region_table[bar], rle->res)); - dr->region_table[bar] = NULL; - dr->region_mask &= ~(1 << bar); - } - - TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) { - if (rle->res != (void *)rman_get_bushandle(mmio->res)) - continue; - TAILQ_REMOVE(&pdev->mmio, mmio, next); - free(mmio, M_DEVBUF); - } - - bus_release_resource(pdev->dev.bsddev, rle->type, rle->rid, rle->res); -} - -static inline void -pci_release_regions(struct pci_dev *pdev) -{ - int i; - - for (i = 0; i <= PCIR_MAX_BAR_0; i++) - pci_release_region(pdev, i); -} - -static inline int -pci_request_regions(struct pci_dev *pdev, const char *res_name) -{ - int error; - int i; - - for (i = 0; i <= PCIR_MAX_BAR_0; i++) { - error = pci_request_region(pdev, i, res_name); - if (error && error != -ENODEV) { - pci_release_regions(pdev); - return (error); - } - } - return (0); -} +#define pci_release_region(pdev, bar) linuxkpi_pci_release_region(pdev, bar) +#define pci_release_regions(pdev) linuxkpi_pci_release_regions(pdev) +#define pci_request_regions(pdev, res_name) \ + linuxkpi_pci_request_regions(pdev, res_name) static inline void lkpi_pci_disable_msix(struct pci_dev *pdev) @@ -604,7 +575,7 @@ lkpi_pci_disable_msix(struct pci_dev *pdev) /* * The MSIX IRQ numbers associated with this PCI device are no * longer valid and might be re-assigned. Make sure - * linux_pci_find_irq_dev() does no longer see them by + * lkpi_pci_find_irq_dev() does no longer see them by * resetting their references to zero: */ pdev->dev.irq_start = 0; @@ -762,11 +733,6 @@ void linux_pci_unregister_drm_driver(struct pci_driver *pdrv); #define pci_register_driver(pdrv) linux_pci_register_driver(pdrv) #define pci_unregister_driver(pdrv) linux_pci_unregister_driver(pdrv) -struct msix_entry { - int entry; - int vector; -}; - /* * Enable msix, positive errors indicate actual number of available * vectors. Negative errors are failures. @@ -774,42 +740,7 @@ struct msix_entry { * NB: define added to prevent this definition of pci_enable_msix from * clashing with the native FreeBSD version. */ -#define pci_enable_msix(...) \ - linux_pci_enable_msix(__VA_ARGS__) - -static inline int -pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nreq) -{ - struct resource_list_entry *rle; - int error; - int avail; - int i; - - avail = pci_msix_count(pdev->dev.bsddev); - if (avail < nreq) { - if (avail == 0) - return -EINVAL; - return avail; - } - avail = nreq; - if ((error = -pci_alloc_msix(pdev->dev.bsddev, &avail)) != 0) - return error; - /* - * Handle case where "pci_alloc_msix()" may allocate less - * interrupts than available and return with no error: - */ - if (avail < nreq) { - pci_release_msi(pdev->dev.bsddev); - return avail; - } - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); - pdev->dev.irq_start = rle->start; - pdev->dev.irq_end = rle->start + avail; - for (i = 0; i < nreq; i++) - entries[i].vector = pdev->dev.irq_start + i; - pdev->msix_enabled = true; - return (0); -} +#define pci_enable_msix(...) linuxkpi_pci_enable_msix(__VA_ARGS__) #define pci_enable_msix_range(...) \ linux_pci_enable_msix_range(__VA_ARGS__) @@ -843,24 +774,8 @@ pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, static inline int pci_enable_msi(struct pci_dev *pdev) { - struct resource_list_entry *rle; - int error; - int avail; - avail = pci_msi_count(pdev->dev.bsddev); - if (avail < 1) - return -EINVAL; - - avail = 1; /* this function only enable one MSI IRQ */ - if ((error = -pci_alloc_msi(pdev->dev.bsddev, &avail)) != 0) - return error; - - rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false); - pdev->dev.irq_start = rle->start; - pdev->dev.irq_end = rle->start + avail; - pdev->irq = rle->start; - pdev->msi_enabled = true; - return (0); + return (_lkpi_pci_enable_msi_range(pdev, 1, 1)); } static inline int @@ -879,35 +794,11 @@ static inline void pci_disable_sriov(struct pci_dev *dev) { } -static inline void * -pci_iomap(struct pci_dev *pdev, int mmio_bar, int mmio_size) -{ - struct resource *res; - - res = _lkpi_pci_iomap(pdev, mmio_bar, mmio_size); - if (res == NULL) - return (NULL); - /* This is a FreeBSD extension so we can use bus_*(). */ - if (pdev->want_iomap_res) - return (res); - return ((void *)rman_get_bushandle(res)); -} - -static inline void -pci_iounmap(struct pci_dev *pdev, void *res) -{ - struct pci_mmio_region *mmio, *p; - - TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) { - if (res != (void *)rman_get_bushandle(mmio->res)) - continue; - bus_release_resource(pdev->dev.bsddev, - mmio->type, mmio->rid, mmio->res); - TAILQ_REMOVE(&pdev->mmio, mmio, next); - free(mmio, M_DEVBUF); - return; - } -} +#define pci_iomap_range(pdev, mmio_bar, mmio_off, mmio_size) \ + linuxkpi_pci_iomap_range(pdev, mmio_bar, mmio_off, mmio_size) +#define pci_iomap(pdev, mmio_bar, mmio_size) \ + linuxkpi_pci_iomap(pdev, mmio_bar, mmio_size) +#define pci_iounmap(pdev, res) linuxkpi_pci_iounmap(pdev, res) static inline void lkpi_pci_save_state(struct pci_dev *pdev) @@ -926,6 +817,13 @@ lkpi_pci_restore_state(struct pci_dev *pdev) #define pci_save_state(dev) lkpi_pci_save_state(dev) #define pci_restore_state(dev) lkpi_pci_restore_state(dev) +static inline int +pci_reset_function(struct pci_dev *pdev) +{ + + return (-ENOSYS); +} + #define DEFINE_PCI_DEVICE_TABLE(_table) \ const struct pci_device_id _table[] __devinitdata @@ -1110,6 +1008,7 @@ static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) static inline int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *dst) { + *dst = 0; if (pos & 3) return -EINVAL; @@ -1122,6 +1021,7 @@ pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *dst) static inline int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *dst) { + *dst = 0; if (pos & 3) return -EINVAL; @@ -1144,21 +1044,40 @@ pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) } static inline int -pcie_capability_set_word(struct pci_dev *dev, int pos, uint16_t val) +pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, + uint16_t clear, uint16_t set) { int error; uint16_t v; + if (pos == PCI_EXP_LNKCTL || pos == PCI_EXP_RTCTL) + spin_lock(&dev->pcie_cap_lock); + error = pcie_capability_read_word(dev, pos, &v); - if (error != 0) - return (error); + if (error == 0) { + v &= ~clear; + v |= set; + error = pcie_capability_write_word(dev, pos, v); + } - v |= val; + if (pos == PCI_EXP_LNKCTL || pos == PCI_EXP_RTCTL) + spin_unlock(&dev->pcie_cap_lock); - error = pcie_capability_write_word(dev, pos, v); return (error); } +static inline int +pcie_capability_set_word(struct pci_dev *dev, int pos, uint16_t val) +{ + return (pcie_capability_clear_and_set_word(dev, pos, 0, val)); +} + +static inline int +pcie_capability_clear_word(struct pci_dev *dev, int pos, uint16_t val) +{ + return (pcie_capability_clear_and_set_word(dev, pos, val, 0)); +} + static inline int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed, enum pcie_link_width *width) { @@ -1208,6 +1127,10 @@ pcie_get_speed_cap(struct pci_dev *dev) return (PCIE_SPEED_8_0GT); if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB) return (PCIE_SPEED_16_0GT); + if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_32_0GB) + return (PCIE_SPEED_32_0GT); + if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_64_0GB) + return (PCIE_SPEED_64_0GT); } else { /* pre-r3.0 */ lnkcap = pci_read_config(root, pos + PCIER_LINK_CAP, 4); if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB) @@ -1218,6 +1141,10 @@ pcie_get_speed_cap(struct pci_dev *dev) return (PCIE_SPEED_8_0GT); if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB) return (PCIE_SPEED_16_0GT); + if (lnkcap & PCI_EXP_LNKCAP_SLS_32_0GB) + return (PCIE_SPEED_32_0GT); + if (lnkcap & PCI_EXP_LNKCAP_SLS_64_0GB) + return (PCIE_SPEED_64_0GT); } return (PCI_SPEED_UNKNOWN); } @@ -1245,6 +1172,10 @@ PCIE_SPEED2MBS_ENC(enum pci_bus_speed spd) { switch(spd) { + case PCIE_SPEED_64_0GT: + return (64000 * 128 / 130); + case PCIE_SPEED_32_0GT: + return (32000 * 128 / 130); case PCIE_SPEED_16_0GT: return (16000 * 128 / 130); case PCIE_SPEED_8_0GT: @@ -1275,6 +1206,12 @@ pcie_bandwidth_available(struct pci_dev *pdev, return (nwidth * PCIE_SPEED2MBS_ENC(nspeed)); } +static inline bool +pcie_aspm_enabled(struct pci_dev *pdev) +{ + return (false); +} + static inline struct pci_dev * pcie_find_root_port(struct pci_dev *pdev) { @@ -1307,6 +1244,29 @@ pci_stop_and_remove_bus_device(struct pci_dev *pdev) { } +static inline int +pci_rescan_bus(struct pci_bus *pbus) +{ + device_t *devlist, parent; + int devcount, error; + + if (!device_is_attached(pbus->self->dev.bsddev)) + return (0); + /* pci_rescan_method() will work on the pcib (parent). */ + error = BUS_RESCAN(pbus->self->dev.bsddev); + if (error != 0) + return (0); + + parent = device_get_parent(pbus->self->dev.bsddev); + error = device_get_children(parent, &devlist, &devcount); + if (error != 0) + return (0); + if (devcount != 0) + free(devlist, M_TEMP); + + return (devcount); +} + /* * The following functions can be used to attach/detach the LinuxKPI's * PCI device runtime. The pci_driver and pci_device_id pointer is @@ -1330,6 +1290,29 @@ pci_dev_present(const struct pci_device_id *cur) return (0); } +static inline const struct pci_device_id * +pci_match_id(const struct pci_device_id *ids, struct pci_dev *pdev) +{ + if (ids == NULL) + return (NULL); + + for (; + ids->vendor != 0 || ids->subvendor != 0 || ids->class_mask != 0; + ids++) + if ((ids->vendor == PCI_ANY_ID || + ids->vendor == pdev->vendor) && + (ids->device == PCI_ANY_ID || + ids->device == pdev->device) && + (ids->subvendor == PCI_ANY_ID || + ids->subvendor == pdev->subsystem_vendor) && + (ids->subdevice == PCI_ANY_ID || + ids->subdevice == pdev->subsystem_device) && + ((ids->class ^ pdev->class) & ids->class_mask) == 0) + return (ids); + + return (NULL); +} + struct pci_dev *lkpi_pci_get_domain_bus_and_slot(int domain, unsigned int bus, unsigned int devfn); #define pci_get_domain_bus_and_slot(domain, bus, devfn) \ @@ -1398,66 +1381,23 @@ pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, int pos, struct pci_dev *lkpi_pci_get_class(unsigned int class, struct pci_dev *from); #define pci_get_class(class, from) lkpi_pci_get_class(class, from) +struct pci_dev *lkpi_pci_get_base_class(unsigned int class, + struct pci_dev *from); +#define pci_get_base_class(class, from) lkpi_pci_get_base_class(class, from) /* -------------------------------------------------------------------------- */ -static inline int -pcim_enable_device(struct pci_dev *pdev) -{ - struct pci_devres *dr; - int error; - - /* Here we cannot run through the pdev->managed check. */ - dr = lkpi_pci_devres_get_alloc(pdev); - if (dr == NULL) - return (-ENOMEM); - - /* If resources were enabled before do not do it again. */ - if (dr->enable_io) - return (0); - - error = pci_enable_device(pdev); - if (error == 0) - dr->enable_io = true; - - /* This device is not managed. */ - pdev->managed = true; - - return (error); -} - -static inline void __iomem ** -pcim_iomap_table(struct pci_dev *pdev) -{ - struct pcim_iomap_devres *dr; - - dr = lkpi_pcim_iomap_devres_find(pdev); - if (dr == NULL) - return (NULL); - - /* - * If the driver has manually set a flag to be able to request the - * resource to use bus_read/write_<n>, return the shadow table. - */ - if (pdev->want_iomap_res) - return ((void **)dr->res_table); - - /* This is the Linux default. */ - return (dr->mmio_table); -} +#define pcim_enable_device(pdev) linuxkpi_pcim_enable_device(pdev) +#define pcim_iomap_table(pdev) linuxkpi_pcim_iomap_table(pdev) +#define pcim_iomap_regions(pdev, mask, name) \ + linuxkpi_pcim_iomap_regions(pdev, mask, name) static inline int pcim_iomap_regions_request_all(struct pci_dev *pdev, uint32_t mask, char *name) { - struct pcim_iomap_devres *dr; - void *res; - uint32_t mappings, requests, req_mask; + uint32_t requests, req_mask; int bar, error; - dr = lkpi_pcim_iomap_devres_find(pdev); - if (dr == NULL) - return (-ENOMEM); - /* Request all the BARs ("regions") we do not iomap. */ req_mask = ((1 << (PCIR_MAX_BAR_0 + 1)) - 1) & ~mask; for (bar = requests = 0; requests != req_mask; bar++) { @@ -1469,44 +1409,34 @@ pcim_iomap_regions_request_all(struct pci_dev *pdev, uint32_t mask, char *name) requests |= (1 << bar); } - /* Now iomap all the requested (by "mask") ones. */ - for (bar = mappings = 0; mappings != mask; bar++) { - if ((mask & (1 << bar)) == 0) - continue; - - /* Request double is not allowed. */ - if (dr->mmio_table[bar] != NULL) { - device_printf(pdev->dev.bsddev, "%s: bar %d %p\n", - __func__, bar, dr->mmio_table[bar]); - goto err; - } - - res = _lkpi_pci_iomap(pdev, bar, 0); - if (res == NULL) - goto err; - dr->mmio_table[bar] = (void *)rman_get_bushandle(res); - dr->res_table[bar] = res; - - mappings |= (1 << bar); - } + error = pcim_iomap_regions(pdev, mask, name); + if (error != 0) + goto err; return (0); err: for (bar = PCIR_MAX_BAR_0; bar >= 0; bar--) { - if ((mappings & (1 << bar)) != 0) { - res = dr->mmio_table[bar]; - if (res == NULL) - continue; - pci_iounmap(pdev, res); - } else if ((requests & (1 << bar)) != 0) { + if ((requests & (1 << bar)) != 0) pci_release_region(pdev, bar); - } } return (-EINVAL); } +/* + * We cannot simply re-define pci_get_device() as we would normally do + * and then hide it in linux_pci.c as too many semi-native drivers still + * include linux/pci.h and run into the conflict with native PCI. Linux drivers + * using pci_get_device() need to be changed to call linuxkpi_pci_get_device(). + */ +static inline struct pci_dev * +linuxkpi_pci_get_device(uint16_t vendor, uint16_t device, struct pci_dev *odev) +{ + + return (lkpi_pci_get_device(vendor, device, odev)); +} + /* This is a FreeBSD extension so we can use bus_*(). */ static inline void linuxkpi_pcim_want_to_use_bus_functions(struct pci_dev *pdev) @@ -1514,4 +1444,94 @@ linuxkpi_pcim_want_to_use_bus_functions(struct pci_dev *pdev) pdev->want_iomap_res = true; } +static inline bool +pci_is_thunderbolt_attached(struct pci_dev *pdev) +{ + + return (false); +} + +static inline void * +pci_platform_rom(struct pci_dev *pdev, size_t *size) +{ + + return (NULL); +} + +static inline void +pci_ignore_hotplug(struct pci_dev *pdev) +{ +} + +static inline const char * +pci_power_name(pci_power_t state) +{ + int pstate = state + 1; + + if (pstate >= 0 && pstate < nitems(pci_power_names)) + return (pci_power_names[pstate]); + else + return (pci_power_names[0]); +} + +static inline int +pcie_get_readrq(struct pci_dev *dev) +{ + u16 ctl; + + if (pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl)) + return (-EINVAL); + + return (128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12)); +} + +static inline bool +pci_is_enabled(struct pci_dev *pdev) +{ + + return ((pci_read_config(pdev->dev.bsddev, PCIR_COMMAND, 2) & + PCIM_CMD_BUSMASTEREN) != 0); +} + +static inline int +pci_wait_for_pending_transaction(struct pci_dev *pdev) +{ + + return (0); +} + +static inline int +pci_assign_resource(struct pci_dev *pdev, int bar) +{ + + return (0); +} + +static inline int +pci_irq_vector(struct pci_dev *pdev, unsigned int vector) +{ + + if (!pdev->msix_enabled && !pdev->msi_enabled) { + if (vector != 0) + return (-EINVAL); + return (pdev->irq); + } + + if (pdev->msix_enabled || pdev->msi_enabled) { + if ((pdev->dev.irq_start + vector) >= pdev->dev.irq_end) + return (-EINVAL); + return (pdev->dev.irq_start + vector); + } + + return (-ENXIO); +} + +static inline int +pci_wake_from_d3(struct pci_dev *pdev, bool enable) +{ + + pr_debug("%s: TODO\n", __func__); + return (0); +} + #endif /* _LINUXKPI_LINUX_PCI_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pci_ids.h b/sys/compat/linuxkpi/common/include/linux/pci_ids.h index 519d1b6eb663..e318f6f75ce7 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci_ids.h +++ b/sys/compat/linuxkpi/common/include/linux/pci_ids.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PCI_IDS_H @@ -41,23 +39,31 @@ #define PCI_BASE_CLASS_BRIDGE 0x06 #define PCI_CLASS_BRIDGE_ISA 0x0601 +#define PCI_CLASS_ACCELERATOR_PROCESSING 0x1200 + /* XXX We should really generate these and use them throughout the tree. */ #define PCI_VENDOR_ID_APPLE 0x106b #define PCI_VENDOR_ID_ASUSTEK 0x1043 +#define PCI_VENDOR_ID_ASMEDIA 0x1b21 +#define PCI_VENDOR_ID_ATHEROS 0x168c #define PCI_VENDOR_ID_ATI 0x1002 #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_VENDOR_ID_DELL 0x1028 #define PCI_VENDOR_ID_HP 0x103c #define PCI_VENDOR_ID_IBM 0x1014 #define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_VENDOR_ID_ITTIM 0x0b48 +#define PCI_VENDOR_ID_MEDIATEK 0x14c3 #define PCI_VENDOR_ID_MELLANOX 0x15b3 +#define PCI_VENDOR_ID_QCOM 0x17cb #define PCI_VENDOR_ID_REALTEK 0x10ec #define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 #define PCI_VENDOR_ID_SERVERWORKS 0x1166 #define PCI_VENDOR_ID_SONY 0x104d #define PCI_VENDOR_ID_TOPSPIN 0x1867 +#define PCI_VENDOR_ID_UBIQUITI 0x0777 #define PCI_VENDOR_ID_VIA 0x1106 #define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4 #define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 diff --git a/sys/compat/linuxkpi/common/include/linux/perf_event.h b/sys/compat/linuxkpi/common/include/linux/perf_event.h new file mode 100644 index 000000000000..86b0d06cdc1f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/perf_event.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PERF_EVENT_H_ +#define _LINUXKPI_LINUX_PERF_EVENT_H_ + +#include <linux/cgroup.h> + +#endif /* _LINUXKPI_LINUX_PERF_EVENT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/pfn.h b/sys/compat/linuxkpi/common/include/linux/pfn.h index 675f5d21364a..26d47b9bc3b1 100644 --- a/sys/compat/linuxkpi/common/include/linux/pfn.h +++ b/sys/compat/linuxkpi/common/include/linux/pfn.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PFN_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/pfn_t.h b/sys/compat/linuxkpi/common/include/linux/pfn_t.h index 48fb4f59a3c6..f22289802cb8 100644 --- a/sys/compat/linuxkpi/common/include/linux/pfn_t.h +++ b/sys/compat/linuxkpi/common/include/linux/pfn_t.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PFN_T_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/pid.h b/sys/compat/linuxkpi/common/include/linux/pid.h index be7c9384d4cf..60cb9f725b21 100644 --- a/sys/compat/linuxkpi/common/include/linux/pid.h +++ b/sys/compat/linuxkpi/common/include/linux/pid.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PID_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/platform_device.h b/sys/compat/linuxkpi/common/include/linux/platform_device.h new file mode 100644 index 000000000000..6853e709cb70 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/platform_device.h @@ -0,0 +1,97 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020-2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PLATFORM_DEVICE_H +#define _LINUXKPI_LINUX_PLATFORM_DEVICE_H + +#include <linux/kernel.h> +#include <linux/device.h> + +struct platform_device { + const char *name; + int id; + bool id_auto; + struct device dev; +}; + +struct platform_driver { + int (*remove)(struct platform_device *); + struct device_driver driver; +}; + +#define dev_is_platform(dev) (false) +#define to_platform_device(dev) (NULL) + +static __inline int +platform_driver_register(struct platform_driver *pdrv) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENXIO); +} + +static __inline void * +dev_get_platdata(struct device *dev) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static __inline int +platform_driver_probe(struct platform_driver *pdrv, + int(*pd_probe_f)(struct platform_device *)) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENODEV); +} + +static __inline void +platform_driver_unregister(struct platform_driver *pdrv) +{ + + pr_debug("%s: TODO\n", __func__); + return; +} + +static __inline int +platform_device_register(struct platform_device *pdev) +{ + pr_debug("%s: TODO\n", __func__); + return (0); +} + +static __inline void +platform_device_unregister(struct platform_device *pdev) +{ + + pr_debug("%s: TODO\n", __func__); + return; +} + +#endif /* _LINUXKPI_LINUX_PLATFORM_DEVICE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pm.h b/sys/compat/linuxkpi/common/include/linux/pm.h index 255c9bf0ea8b..c8d943027909 100644 --- a/sys/compat/linuxkpi/common/include/linux/pm.h +++ b/sys/compat/linuxkpi/common/include/linux/pm.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2020 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,31 +26,75 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PM_H #define _LINUXKPI_LINUX_PM_H +#include <linux/kernel.h> /* pr_debug */ +#include <asm/atomic.h> + +/* Needed but breaks linux_usb.c */ +/* #include <linux/completion.h> */ +/* #include <linux/wait.h> */ + +struct device; + typedef struct pm_message { int event; } pm_message_t; +struct dev_pm_domain { +}; + +struct dev_pm_info { + atomic_t usage_count; +}; + +#define PM_EVENT_FREEZE 0x0001 +#define PM_EVENT_SUSPEND 0x0002 + +#define pm_sleep_ptr(_p) \ + IS_ENABLED(CONFIG_PM_SLEEP) ? (_p) : NULL + #ifdef CONFIG_PM_SLEEP +#define __SET_PM_OPS(_suspendfunc, _resumefunc) \ + .suspend = _suspendfunc, \ + .resume = _resumefunc, \ + .freeze = _suspendfunc, \ + .thaw = _resumefunc, \ + .poweroff = _suspendfunc, \ + .restore = _resumefunc, \ + #define SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ const struct dev_pm_ops _name = { \ - .suspend = _suspendfunc, \ - .resume = _resumefunc, \ - .freeze = _suspendfunc, \ - .thaw = _resumefunc, \ - .poweroff = _suspendfunc, \ - .restore = _resumefunc, \ + __SET_PM_OPS(_suspendfunc, _resumefunc) \ } + +#define DEFINE_SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ +const struct dev_pm_ops _name = { \ + __SET_PM_OPS(_suspendfunc, _resumefunc) \ +} + +#define SET_SYSTEM_SLEEP_PM_OPS(_suspendfunc, _resumefunc) \ + __SET_PM_OPS(_suspendfunc, _resumefunc) #else #define SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ const struct dev_pm_ops _name = { \ } +#define DEFINE_SIMPLE_DEV_PM_OPS(_name, _suspendfunc, _resumefunc) \ +const struct dev_pm_ops _name = { \ +} #endif +bool linuxkpi_device_can_wakeup(struct device *); +#define device_can_wakeup(_dev) linuxkpi_device_can_wakeup(_dev) + +static inline void +pm_wakeup_event(struct device *dev __unused, unsigned int x __unused) +{ + + pr_debug("%s: TODO\n", __func__); +} + #endif /* _LINUXKPI_LINUX_PM_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pm_qos.h b/sys/compat/linuxkpi/common/include/linux/pm_qos.h index 8a9b3bdbd1ef..47c41a819ba8 100644 --- a/sys/compat/linuxkpi/common/include/linux/pm_qos.h +++ b/sys/compat/linuxkpi/common/include/linux/pm_qos.h @@ -23,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PM_QOS_H diff --git a/sys/compat/linuxkpi/common/include/linux/pm_runtime.h b/sys/compat/linuxkpi/common/include/linux/pm_runtime.h index 42c96a92b1ad..6114b7b159d7 100644 --- a/sys/compat/linuxkpi/common/include/linux/pm_runtime.h +++ b/sys/compat/linuxkpi/common/include/linux/pm_runtime.h @@ -34,10 +34,21 @@ pm_runtime_get_if_in_use(struct device *dev) return 1; } +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION < 60900 static inline int pm_runtime_get_if_active(struct device *dev, bool x) +#else +static inline int +pm_runtime_get_if_active(struct device *dev) +#endif { return 1; } +static inline int +pm_runtime_suspended(struct device *dev) +{ + return 0; +} + #endif /* _LINUXKPI_LINUX_PM_RUNTIME_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/poll.h b/sys/compat/linuxkpi/common/include/linux/poll.h index ff83fb1959f6..3acb3c740954 100644 --- a/sys/compat/linuxkpi/common/include/linux/poll.h +++ b/sys/compat/linuxkpi/common/include/linux/poll.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_POLL_H_ #define _LINUXKPI_LINUX_POLL_H_ @@ -34,6 +32,7 @@ #include <sys/poll.h> #include <sys/fcntl.h> +#include <linux/eventpoll.h> #include <linux/wait.h> #include <linux/file.h> diff --git a/sys/compat/linuxkpi/common/include/linux/power_supply.h b/sys/compat/linuxkpi/common/include/linux/power_supply.h index cf8a937b04ad..8855cfff0539 100644 --- a/sys/compat/linuxkpi/common/include/linux/power_supply.h +++ b/sys/compat/linuxkpi/common/include/linux/power_supply.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_POWER_SUPPLY_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/preempt.h b/sys/compat/linuxkpi/common/include/linux/preempt.h index b8deb23d7089..32177d4a980c 100644 --- a/sys/compat/linuxkpi/common/include/linux/preempt.h +++ b/sys/compat/linuxkpi/common/include/linux/preempt.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PREEMPT_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/prefetch.h b/sys/compat/linuxkpi/common/include/linux/prefetch.h index aa997d50a3f3..71839f0ca191 100644 --- a/sys/compat/linuxkpi/common/include/linux/prefetch.h +++ b/sys/compat/linuxkpi/common/include/linux/prefetch.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PREFETCH_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/printk.h b/sys/compat/linuxkpi/common/include/linux/printk.h index 317c6232bbc5..da9d45122d4d 100644 --- a/sys/compat/linuxkpi/common/include/linux/printk.h +++ b/sys/compat/linuxkpi/common/include/linux/printk.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_PRINTK_H_ #define _LINUXKPI_LINUX_PRINTK_H_ @@ -46,57 +44,19 @@ enum { DUMP_PREFIX_OFFSET }; +int __lkpi_hexdump_printf(void *, const char *, ...) __printflike(2, 3); + +void lkpi_hex_dump(int(*)(void *, const char *, ...), void *arg1, + const char *, const char *, const int, const int, const int, + const void *, size_t, const bool); + static inline void print_hex_dump(const char *level, const char *prefix_str, const int prefix_type, const int rowsize, const int groupsize, const void *buf, size_t len, const bool ascii) { - typedef const struct { long long value; } __packed *print_64p_t; - typedef const struct { uint32_t value; } __packed *print_32p_t; - typedef const struct { uint16_t value; } __packed *print_16p_t; - const void *buf_old = buf; - int row; - - while (len > 0) { - if (level != NULL) - printf("%s", level); - if (prefix_str != NULL) - printf("%s ", prefix_str); - - switch (prefix_type) { - case DUMP_PREFIX_ADDRESS: - printf("[%p] ", buf); - break; - case DUMP_PREFIX_OFFSET: - printf("[%#tx] ", ((const char *)buf - - (const char *)buf_old)); - break; - default: - break; - } - for (row = 0; row != rowsize; row++) { - if (groupsize == 8 && len > 7) { - printf("%016llx ", ((print_64p_t)buf)->value); - buf = (const uint8_t *)buf + 8; - len -= 8; - } else if (groupsize == 4 && len > 3) { - printf("%08x ", ((print_32p_t)buf)->value); - buf = (const uint8_t *)buf + 4; - len -= 4; - } else if (groupsize == 2 && len > 1) { - printf("%04x ", ((print_16p_t)buf)->value); - buf = (const uint8_t *)buf + 2; - len -= 2; - } else if (len > 0) { - printf("%02x ", *(const uint8_t *)buf); - buf = (const uint8_t *)buf + 1; - len--; - } else { - break; - } - } - printf("\n"); - } + lkpi_hex_dump(__lkpi_hexdump_printf, NULL, level, prefix_str, prefix_type, + rowsize, groupsize, buf, len, ascii); } static inline void @@ -127,4 +87,11 @@ print_hex_dump_bytes(const char *prefix_str, const int prefix_type, #define pr_info_ratelimited(fmt, ...) \ printk_ratelimited(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) +#define no_printk(fmt, ...) \ +({ \ + if (0) \ + printk(pr_fmt(fmt), ##__VA_ARGS__); \ + 0; \ +}) + #endif /* _LINUXKPI_LINUX_PRINTK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h b/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h new file mode 100644 index 000000000000..aad46cc25b1b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ptp_clock_kernel.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2023 The FreeBSD Foundation + * + * This software was developed by Björn Zeeb under sponsorship from + * the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_PTP_CLOCK_KERNEL_H +#define _LINUXKPI_LINUX_PTP_CLOCK_KERNEL_H + +#include <linux/types.h> +#include <linux/device.h> +#include <linux/kernel.h> /* pr_debug */ +#include <linux/ktime.h> /* system_device_crosststamp */ + +/* This very likely belongs elsewhere. */ +struct system_device_crosststamp { + ktime_t device; + ktime_t sys_realtime; + ktime_t sys_monotonic_raw; /* name guessed based on comment */ +}; + +struct ptp_clock_info { + char name[32]; + int max_adj; + void *owner; /* THIS_MODULE */ + int (*adjfine)(struct ptp_clock_info *, long); + int (*adjtime)(struct ptp_clock_info *, s64); + int (*getcrosststamp)(struct ptp_clock_info *, struct system_device_crosststamp *); + int (*gettime64)(struct ptp_clock_info *, struct timespec *); +}; + +static inline struct ptp_clock * +ptp_clock_register(struct ptp_clock_info *ptpci, struct device *dev) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline void +ptp_clock_unregister(struct ptp_clock *ptpc) +{ + pr_debug("%s: TODO\n", __func__); +} + +static inline int +ptp_clock_index(struct ptp_clock *ptpc) +{ + pr_debug("%s: TODO\n", __func__); + return (0); +} + +#endif /* _LINUXKPI_LINUX_PTP_CLOCK_KERNEL_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/pwm.h b/sys/compat/linuxkpi/common/include/linux/pwm.h index 59a17f525c91..c0740db675e8 100644 --- a/sys/compat/linuxkpi/common/include/linux/pwm.h +++ b/sys/compat/linuxkpi/common/include/linux/pwm.h @@ -91,4 +91,10 @@ pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) return (-ENOTSUPP); } +static inline int +pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state) +{ + return (0); +} + #endif /* _LINUXKPI_LINUX_PWM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/qrtr.h b/sys/compat/linuxkpi/common/include/linux/qrtr.h new file mode 100644 index 000000000000..1d2af0efdce2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/qrtr.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_QRTR_H +#define _LINUXKPI_LINUX_QRTR_H + +/* Qualcomm IPC Router (QRTR) */ + +#include <sys/socket.h> + +struct sockaddr_qrtr { + sa_family_t sq_family; + uint32_t sq_node; + uint32_t sq_port; +}; + +#endif /* _LINUXKPI_LINUX_QRTR_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/radix-tree.h b/sys/compat/linuxkpi/common/include/linux/radix-tree.h index 86620614fb36..ea75836c26fb 100644 --- a/sys/compat/linuxkpi/common/include/linux/radix-tree.h +++ b/sys/compat/linuxkpi/common/include/linux/radix-tree.h @@ -25,12 +25,11 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_RADIX_TREE_H_ #define _LINUXKPI_LINUX_RADIX_TREE_H_ +#include <linux/rcupdate.h> #include <linux/types.h> #define RADIX_TREE_MAP_SHIFT 6 diff --git a/sys/compat/linuxkpi/common/include/linux/random.h b/sys/compat/linuxkpi/common/include/linux/random.h index fafb87cae9fe..893ee2b7b728 100644 --- a/sys/compat/linuxkpi/common/include/linux/random.h +++ b/sys/compat/linuxkpi/common/include/linux/random.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright 2023 The FreeBSD Foundation + * + * Portions of this software was developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,8 +29,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_RANDOM_H_ @@ -36,8 +38,6 @@ #include <sys/random.h> #include <sys/libkern.h> -#define get_random_u32() get_random_int() - static inline void get_random_bytes(void *buf, int nbytes) { @@ -54,6 +54,39 @@ get_random_int(void) return (val); } +static inline uint8_t +get_random_u8(void) +{ + uint8_t val; + + get_random_bytes(&val, sizeof(val)); + return (val); +} + +#define get_random_u32() get_random_int() + +/* + * See "Fast Random Integer Generation in an Interval" by Daniel Lemire + * [https://arxiv.org/pdf/1805.10941.pdf] for implementation insights. + */ +static inline uint32_t +get_random_u32_inclusive(uint32_t floor, uint32_t ceil) +{ + uint64_t x; + uint32_t t, v; + + MPASS(ceil >= floor); + + v = get_random_u32(); + t = ceil - floor + 1; + x = (uint64_t)t * v; + while (x < t) + x = (uint64_t)t * get_random_u32(); + v = x >> 32; + + return (floor + v); +} + static inline u_long get_random_long(void) { @@ -63,6 +96,21 @@ get_random_long(void) return (val); } +static inline uint64_t +get_random_u64(void) +{ + uint64_t val; + + get_random_bytes(&val, sizeof(val)); + return (val); +} + +static inline uint32_t +get_random_u32_below(uint32_t max) +{ + return (arc4random_uniform(max)); +} + static __inline uint32_t prandom_u32(void) { diff --git a/sys/compat/linuxkpi/common/include/linux/rbtree.h b/sys/compat/linuxkpi/common/include/linux/rbtree.h index de5ef0d6a3ce..e6033cfd760d 100644 --- a/sys/compat/linuxkpi/common/include/linux/rbtree.h +++ b/sys/compat/linuxkpi/common/include/linux/rbtree.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_RBTREE_H_ #define _LINUXKPI_LINUX_RBTREE_H_ @@ -41,8 +39,8 @@ struct rb_node { RB_ENTRY(rb_node) __entry; }; -#define rb_left __entry.rbe_left -#define rb_right __entry.rbe_right +#define rb_left __entry.rbe_link[_RB_L] +#define rb_right __entry.rbe_link[_RB_R] /* * We provide a false structure that has the same bit pattern as tree.h @@ -74,8 +72,11 @@ RB_PROTOTYPE(linux_root, rb_node, __entry, panic_cmp); #define RB_EMPTY_NODE(node) (RB_PARENT(node, __entry) == node) #define RB_CLEAR_NODE(node) RB_SET_PARENT(node, node, __entry) -#define rb_insert_color(node, root) \ - linux_root_RB_INSERT_COLOR((struct linux_root *)(root), (node)) +#define rb_insert_color(node, root) do { \ + if (rb_parent(node)) \ + linux_root_RB_INSERT_COLOR((struct linux_root *)(root), \ + rb_parent(node), (node)); \ +} while (0) #define rb_erase(node, root) \ linux_root_RB_REMOVE((struct linux_root *)(root), (node)) #define rb_next(node) RB_NEXT(linux_root, NULL, (node)) @@ -132,11 +133,12 @@ rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root) { - RB_SWAP_CHILD((struct linux_root *)root, victim, new, __entry); - if (victim->rb_left) - RB_SET_PARENT(victim->rb_left, new, __entry); - if (victim->rb_right) - RB_SET_PARENT(victim->rb_right, new, __entry); + RB_SWAP_CHILD((struct linux_root *)root, rb_parent(victim), + victim, new, __entry); + if (RB_LEFT(victim, __entry)) + RB_SET_PARENT(RB_LEFT(victim, __entry), new, __entry); + if (RB_RIGHT(victim, __entry)) + RB_SET_PARENT(RB_RIGHT(victim, __entry), new, __entry); *new = *victim; } @@ -144,7 +146,9 @@ static inline void rb_insert_color_cached(struct rb_node *node, struct rb_root_cached *root, bool leftmost) { - linux_root_RB_INSERT_COLOR((struct linux_root *)&root->rb_root, node); + if (rb_parent(node)) + linux_root_RB_INSERT_COLOR((struct linux_root *)&root->rb_root, + rb_parent(node), node); if (leftmost) root->rb_leftmost = node; } @@ -171,6 +175,30 @@ rb_replace_node_cached(struct rb_node *old, struct rb_node *new, root->rb_leftmost = new; } +static inline struct rb_node * +rb_add_cached(struct rb_node *node, struct rb_root_cached *tree, + bool (*less)(struct rb_node *, const struct rb_node *)) +{ + struct rb_node **link = &tree->rb_root.rb_node; + struct rb_node *parent = NULL; + bool leftmost = true; + + while (*link != NULL) { + parent = *link; + if (less(node, parent)) { + link = &RB_LEFT(parent, __entry); + } else { + link = &RB_RIGHT(parent, __entry); + leftmost = false; + } + } + + rb_link_node(node, parent, link); + rb_insert_color_cached(node, tree, leftmost); + + return (leftmost ? node : NULL); +} + #undef RB_ROOT #define RB_ROOT (struct rb_root) { NULL } #define RB_ROOT_CACHED (struct rb_root_cached) { RB_ROOT, NULL } diff --git a/sys/compat/linuxkpi/common/include/linux/rculist.h b/sys/compat/linuxkpi/common/include/linux/rculist.h index e0c3f79d9e5a..066ed92b7996 100644 --- a/sys/compat/linuxkpi/common/include/linux/rculist.h +++ b/sys/compat/linuxkpi/common/include/linux/rculist.h @@ -23,8 +23,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_RCULIST_H_ @@ -44,6 +42,11 @@ &(pos)->member != (head); \ pos = list_entry_rcu((pos)->member.next, typeof(*(pos)), member)) +#define list_for_each_entry_from_rcu(pos, head, member) \ + for (; \ + &(pos)->member != (head); \ + pos = list_entry_rcu((pos)->member.next, typeof(*(pos)), member)) + #define list_for_each_entry_lockless(pos, head, member) \ list_for_each_entry_rcu(pos, head, member) diff --git a/sys/compat/linuxkpi/common/include/linux/rcupdate.h b/sys/compat/linuxkpi/common/include/linux/rcupdate.h index 3599616430af..85d766c8dbc9 100644 --- a/sys/compat/linuxkpi/common/include/linux/rcupdate.h +++ b/sys/compat/linuxkpi/common/include/linux/rcupdate.h @@ -1,6 +1,10 @@ /*- * Copyright (c) 2016-2017 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2024 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -22,17 +26,24 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_RCUPDATE_H_ #define _LINUXKPI_LINUX_RCUPDATE_H_ +#include <sys/cdefs.h> + #include <linux/compiler.h> #include <linux/types.h> +#include <linux/kernel.h> #include <machine/atomic.h> +extern int linuxkpi_rcu_debug; +#define RCU_WARN_ONCE(c, ...) do { \ + if (unlikely(linuxkpi_rcu_debug > 0)) \ + WARN_ONCE((c), ##__VA_ARGS__); \ +} while(0) + #define LINUX_KFREE_RCU_OFFSET_MAX 4096 /* exclusive */ /* BSD specific defines */ @@ -63,6 +74,9 @@ linux_rcu_read_unlock(RCU_TYPE_REGULAR);\ } while (0) +#define rcu_read_lock_held(void) \ + linux_rcu_read_lock_held(RCU_TYPE_REGULAR) + #define synchronize_rcu(void) do { \ linux_synchronize_rcu(RCU_TYPE_REGULAR); \ } while (0) @@ -81,14 +95,34 @@ #define rcu_access_pointer(p) \ ((__typeof(*p) *)READ_ONCE(p)) -#define rcu_dereference_protected(p, c) \ +#define rcu_dereference(p) \ ((__typeof(*p) *)READ_ONCE(p)) -#define rcu_dereference(p) \ - rcu_dereference_protected(p, 0) +#define __rcu_var_name(n, f, l) \ + __CONCAT(__CONCAT(__CONCAT(rcu_, n), _), __COUNTER__) + +#define __rcu_dereference_protected(p, c, n) \ +({ \ + RCU_WARN_ONCE(!(c), "%s:%d: condition for %s failed\n", \ + __func__, __LINE__, __XSTRING(n)); \ + rcu_dereference(p); \ +}) + +#define rcu_dereference_protected(p, c) \ + __rcu_dereference_protected((p), (c), \ + __rcu_var_name(protected, __func__, __LINE__)) + +#define __rcu_dereference_check(p, c, n) \ +({ \ + __typeof(*p) *n = rcu_dereference(p); \ + RCU_WARN_ONCE(!(c), "%s:%d: condition for %s failed\n", \ + __func__, __LINE__, __XSTRING(n)); \ + n; \ +}) -#define rcu_dereference_check(p, c) \ - rcu_dereference_protected(p, c) +#define rcu_dereference_check(p, c) \ + __rcu_dereference_check((p), (c) || rcu_read_lock_held(), \ + __rcu_var_name(check, __func__, __LINE__)) #define rcu_dereference_raw(p) \ ((__typeof(*p) *)READ_ONCE(p)) @@ -115,11 +149,12 @@ /* prototypes */ -extern void linux_call_rcu(unsigned type, struct rcu_head *ptr, rcu_callback_t func); -extern void linux_rcu_barrier(unsigned type); -extern void linux_rcu_read_lock(unsigned type); -extern void linux_rcu_read_unlock(unsigned type); -extern void linux_synchronize_rcu(unsigned type); +void linux_call_rcu(unsigned type, struct rcu_head *ptr, rcu_callback_t func); +void linux_rcu_barrier(unsigned type); +void linux_rcu_read_lock(unsigned type); +void linux_rcu_read_unlock(unsigned type); +bool linux_rcu_read_lock_held(unsigned); +void linux_synchronize_rcu(unsigned type); /* Empty implementation for !DEBUG */ #define init_rcu_head(...) diff --git a/sys/compat/linuxkpi/common/include/linux/ref_tracker.h b/sys/compat/linuxkpi/common/include/linux/ref_tracker.h new file mode 100644 index 000000000000..fa510b2498e1 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/ref_tracker.h @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_REF_TRACKER_H_ +#define _LINUXKPI_LINUX_REF_TRACKER_H_ + +#include <linux/refcount.h> +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/stackdepot.h> + +struct ref_tracker; + +struct ref_tracker_dir { +}; + +/* + * The following functions currently have dummy implementations that, on Linux, + * are used when CONFIG_REF_TRACKER is not set at compile time. + * + * The ref tracker is a tool to associate a refcount increase to a refcount + * decrease. This helps developers track, document and debug refcounts. We + * don't need this feature for now in linuxkpi. + */ + +static inline void +ref_tracker_dir_init(struct ref_tracker_dir *dir, + unsigned int quarantine_count, const char *name) +{ +} + +static inline void +ref_tracker_dir_exit(struct ref_tracker_dir *dir) +{ +} + +static inline void +ref_tracker_dir_print_locked(struct ref_tracker_dir *dir, + unsigned int display_limit) +{ +} + +static inline void +ref_tracker_dir_print(struct ref_tracker_dir *dir, unsigned int display_limit) +{ +} + +static inline int +ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size) +{ + return (0); +} + +static inline int +ref_tracker_alloc(struct ref_tracker_dir *dir, struct ref_tracker **trackerp, + gfp_t gfp) +{ + return (0); +} + +static inline int +ref_tracker_free(struct ref_tracker_dir *dir, struct ref_tracker **trackerp) +{ + return (0); +} + +#endif /* !defined(_LINUXKPI_LINUX_REF_TRACKER_H_) */ diff --git a/sys/compat/linuxkpi/common/include/linux/refcount.h b/sys/compat/linuxkpi/common/include/linux/refcount.h index 7c055fb32029..02a7eda3f4a9 100644 --- a/sys/compat/linuxkpi/common/include/linux/refcount.h +++ b/sys/compat/linuxkpi/common/include/linux/refcount.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_REFCOUNT_H @@ -33,50 +31,54 @@ #include <linux/atomic.h> -struct refcount_linux { - atomic_t value; -}; -typedef struct refcount_linux refcount_t; +typedef atomic_t refcount_t; static inline void refcount_set(refcount_t *ref, unsigned int i) { - atomic_set(&ref->value, i); + atomic_set(ref, i); } static inline void refcount_inc(refcount_t *ref) { - atomic_inc(&ref->value); + atomic_inc(ref); } static inline bool refcount_inc_not_zero(refcount_t *ref) { - return (atomic_inc_not_zero(&ref->value)); + return (atomic_inc_not_zero(ref)); } static inline void refcount_dec(refcount_t *ref) { - atomic_dec(&ref->value); + atomic_dec(ref); } static inline unsigned int refcount_read(refcount_t *ref) { - return atomic_read(&ref->value); + return atomic_read(ref); } static inline bool refcount_dec_and_lock_irqsave(refcount_t *ref, spinlock_t *lock, unsigned long *flags) { - if (atomic_dec_and_test(&ref->value) == true) { + if (atomic_dec_and_test(ref) == true) { spin_lock_irqsave(lock, flags); return (true); } return (false); } +static inline bool +refcount_dec_and_test(refcount_t *r) +{ + + return (atomic_dec_and_test(r)); +} + #endif /* __LINUXKPI_LINUX_REFCOUNT_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/rhashtable.h b/sys/compat/linuxkpi/common/include/linux/rhashtable.h new file mode 100644 index 000000000000..c6958b6ee5f3 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/rhashtable.h @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_RHASHTABLE_H +#define _LINUXKPI_LINUX_RHASHTABLE_H + +#include <linux/kernel.h> /* pr_debug */ + +struct rhash_head { +}; + +struct rhashtable_params { + uint16_t head_offset; + uint16_t key_len; + uint16_t key_offset; + uint16_t nelem_hint; + bool automatic_shrinking; +}; + +struct rhashtable { +}; + +static inline int +rhashtable_init(struct rhashtable *rht, + const struct rhashtable_params *params) +{ + + pr_debug("%s: TODO\n", __func__); + return (-1); +} + +static inline void +rhashtable_destroy(struct rhashtable *rht) +{ + pr_debug("%s: TODO\n", __func__); +} + +static inline void * +rhashtable_lookup_fast(struct rhashtable *rht, const void *key, + const struct rhashtable_params params) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline void * +rhashtable_lookup_get_insert_fast(struct rhashtable *rht, + struct rhash_head *obj, const struct rhashtable_params params) +{ + + pr_debug("%s: TODO\n", __func__); + return (NULL); +} + +static inline int +rhashtable_remove_fast(struct rhashtable *rht, + struct rhash_head *obj, const struct rhashtable_params params) +{ + + pr_debug("%s: TODO\n", __func__); + return (-ENOENT); +} + +#endif /* _LINUXKPI_LINUX_RHASHTABLE_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/rwlock.h b/sys/compat/linuxkpi/common/include/linux/rwlock.h index e7557d29e77a..3030ec89ff1e 100644 --- a/sys/compat/linuxkpi/common/include/linux/rwlock.h +++ b/sys/compat/linuxkpi/common/include/linux/rwlock.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_RWLOCK_H_ #define _LINUXKPI_LINUX_RWLOCK_H_ @@ -36,14 +34,12 @@ #include <sys/rwlock.h> #include <sys/libkern.h> -typedef struct { - struct rwlock rw; -} rwlock_t; +typedef struct rwlock rwlock_t; -#define read_lock(_l) rw_rlock(&(_l)->rw) -#define write_lock(_l) rw_wlock(&(_l)->rw) -#define read_unlock(_l) rw_runlock(&(_l)->rw) -#define write_unlock(_l) rw_wunlock(&(_l)->rw) +#define read_lock(_l) rw_rlock(_l) +#define write_lock(_l) rw_wlock(_l) +#define read_unlock(_l) rw_runlock(_l) +#define write_unlock(_l) rw_wunlock(_l) #define read_lock_irq(lock) read_lock((lock)) #define read_unlock_irq(lock) read_unlock((lock)) #define write_lock_irq(lock) write_lock((lock)) @@ -56,13 +52,6 @@ typedef struct { do { read_unlock(lock); } while (0) #define write_unlock_irqrestore(lock, flags) \ do { write_unlock(lock); } while (0) - -static inline void -rwlock_init(rwlock_t *lock) -{ - - memset(&lock->rw, 0, sizeof(lock->rw)); - rw_init_flags(&lock->rw, "lnxrw", RW_NOWITNESS); -} +#define rwlock_init(_l) rw_init_flags(_l, "lnxrw", RW_NOWITNESS | RW_NEW) #endif /* _LINUXKPI_LINUX_RWLOCK_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/rwsem.h b/sys/compat/linuxkpi/common/include/linux/rwsem.h index fc3580bc186e..b7a800b12e18 100644 --- a/sys/compat/linuxkpi/common/include/linux/rwsem.h +++ b/sys/compat/linuxkpi/common/include/linux/rwsem.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_RWSEM_H_ #define _LINUXKPI_LINUX_RWSEM_H_ @@ -46,6 +44,7 @@ struct rw_semaphore { #define down_read(_rw) sx_slock(&(_rw)->sx) #define up_read(_rw) sx_sunlock(&(_rw)->sx) #define down_read_trylock(_rw) !!sx_try_slock(&(_rw)->sx) +#define down_read_killable(_rw) linux_down_read_killable(_rw) #define down_write_trylock(_rw) !!sx_try_xlock(&(_rw)->sx) #define down_write_killable(_rw) linux_down_write_killable(_rw) #define downgrade_write(_rw) sx_downgrade(&(_rw)->sx) @@ -80,6 +79,7 @@ linux_init_rwsem(struct rw_semaphore *rw, const char *name) sx_init_flags(&rw->sx, name, SX_NOWITNESS); } +extern int linux_down_read_killable(struct rw_semaphore *); extern int linux_down_write_killable(struct rw_semaphore *); #endif /* _LINUXKPI_LINUX_RWSEM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/scatterlist.h b/sys/compat/linuxkpi/common/include/linux/scatterlist.h index a3da30e1b9a7..537f5bebc5aa 100644 --- a/sys/compat/linuxkpi/common/include/linux/scatterlist.h +++ b/sys/compat/linuxkpi/common/include/linux/scatterlist.h @@ -27,15 +27,16 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SCATTERLIST_H_ #define _LINUXKPI_LINUX_SCATTERLIST_H_ #include <sys/types.h> +#include <sys/proc.h> +#include <sys/sched.h> #include <sys/sf_buf.h> +#include <linux/err.h> #include <linux/page.h> #include <linux/slab.h> #include <linux/mm.h> @@ -99,6 +100,12 @@ struct sg_dma_page_iter { #define for_each_sg(sglist, sg, sgmax, iter) \ for (iter = 0, sg = (sglist); iter < (sgmax); iter++, sg = sg_next(sg)) +#define for_each_sgtable_sg(sgt, sg, i) \ + for_each_sg((sgt)->sgl, sg, (sgt)->orig_nents, i) + +#define for_each_sgtable_page(sgt, iter, pgoffset) \ + for_each_sg_page((sgt)->sgl, iter, (sgt)->orig_nents, pgoffset) + #define for_each_sgtable_dma_sg(sgt, sg, iter) \ for_each_sg((sgt)->sgl, sg, (sgt)->nents, iter) @@ -152,7 +159,7 @@ sg_next(struct scatterlist *sg) static inline vm_paddr_t sg_phys(struct scatterlist *sg) { - return (VM_PAGE_TO_PHYS(sg_page(sg)) + sg->offset); + return (page_to_phys(sg_page(sg)) + sg->offset); } static inline void * @@ -321,18 +328,40 @@ sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) return (ret); } +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 +static inline struct scatterlist * +__sg_alloc_table_from_pages(struct sg_table *sgt, + struct page **pages, unsigned int count, + unsigned long off, unsigned long size, + unsigned int max_segment, + struct scatterlist *prv, unsigned int left_pages, + gfp_t gfp_mask) +#else static inline int __sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages, unsigned int count, unsigned long off, unsigned long size, unsigned int max_segment, gfp_t gfp_mask) +#endif { unsigned int i, segs, cur, len; int rc; - struct scatterlist *s; + struct scatterlist *s, *sg_iter; + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + if (prv != NULL) { + panic( + "Support for prv != NULL not implemented in " + "__sg_alloc_table_from_pages()"); + } +#endif if (__predict_false(!max_segment || offset_in_page(max_segment))) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (ERR_PTR(-EINVAL)); +#else return (-EINVAL); +#endif len = 0; for (segs = i = 1; i < count; ++i) { @@ -344,13 +373,25 @@ __sg_alloc_table_from_pages(struct sg_table *sgt, } } if (__predict_false((rc = sg_alloc_table(sgt, segs, gfp_mask)))) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (ERR_PTR(rc)); +#else return (rc); +#endif cur = 0; - for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { + for_each_sg(sgt->sgl, sg_iter, sgt->orig_nents, i) { unsigned long seg_size; unsigned int j; + /* + * We need to make sure that when we exit this loop "s" has the + * last sg in the chain so we can call sg_mark_end() on it. + * Only set this inside the loop since sg_iter will be iterated + * until it is NULL. + */ + s = sg_iter; + len = 0; for (j = cur + 1; j < count; ++j) { len += PAGE_SIZE; @@ -365,7 +406,16 @@ __sg_alloc_table_from_pages(struct sg_table *sgt, off = 0; cur = j; } + KASSERT(s != NULL, ("s is NULL after loop in __sg_alloc_table_from_pages()")); + +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + if (left_pages == 0) + sg_mark_end(s); + + return (s); +#else return (0); +#endif } static inline int @@ -375,8 +425,27 @@ sg_alloc_table_from_pages(struct sg_table *sgt, gfp_t gfp_mask) { +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (PTR_ERR_OR_ZERO(__sg_alloc_table_from_pages(sgt, pages, count, off, size, + SCATTERLIST_MAX_SEGMENT, NULL, 0, gfp_mask))); +#else return (__sg_alloc_table_from_pages(sgt, pages, count, off, size, SCATTERLIST_MAX_SEGMENT, gfp_mask)); +#endif +} + +static inline int +sg_alloc_table_from_pages_segment(struct sg_table *sgt, + struct page **pages, unsigned int count, unsigned int off, + unsigned long size, unsigned int max_segment, gfp_t gfp_mask) +{ +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51300 + return (PTR_ERR_OR_ZERO(__sg_alloc_table_from_pages(sgt, pages, count, off, size, + max_segment, NULL, 0, gfp_mask))); +#else + return (__sg_alloc_table_from_pages(sgt, pages, count, off, size, + max_segment, gfp_mask)); +#endif } static inline int @@ -587,7 +656,7 @@ sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, break; vaddr = (char *)sf_buf_kva(sf); } else - vaddr = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(page)); + vaddr = (char *)PHYS_TO_DMAP(page_to_phys(page)); memcpy(buf, vaddr + sg->offset + offset, len); if (!PMAP_HAS_DMAP) sf_buf_free(sf); @@ -605,4 +674,11 @@ sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, return (total); } +static inline void +sg_set_folio(struct scatterlist *sg, struct folio *folio, size_t len, + size_t offset) +{ + sg_set_page(sg, &folio->page, len, offset); +} + #endif /* _LINUXKPI_LINUX_SCATTERLIST_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/sched.h b/sys/compat/linuxkpi/common/include/linux/sched.h index cb0ffde04b2b..3ad2f8e4ce8b 100644 --- a/sys/compat/linuxkpi/common/include/linux/sched.h +++ b/sys/compat/linuxkpi/common/include/linux/sched.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SCHED_H_ #define _LINUXKPI_LINUX_SCHED_H_ @@ -44,15 +42,18 @@ #include <linux/completion.h> #include <linux/hrtimer.h> #include <linux/mm_types.h> +#include <linux/nodemask.h> #include <linux/pid.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/spinlock.h> #include <linux/time.h> +#include <linux/sched/mm.h> + #include <asm/atomic.h> -#define MAX_SCHEDULE_TIMEOUT INT_MAX +#define MAX_SCHEDULE_TIMEOUT LONG_MAX #define TASK_RUNNING 0x0000 #define TASK_INTERRUPTIBLE 0x0001 @@ -130,7 +131,8 @@ put_task_struct(struct task_struct *task) #define yield() kern_yield(PRI_UNCHANGED) #define sched_yield() sched_relinquish(curthread) -#define need_resched() (curthread->td_flags & TDF_NEEDRESCHED) +#define need_resched() (curthread->td_owepreempt || \ + td_ast_pending(curthread, TDA_SCHED)) static inline int cond_resched_lock(spinlock_t *lock) @@ -158,7 +160,7 @@ void linux_send_sig(int signo, struct task_struct *task); linux_send_sig(signo, task); \ } while (0) -int linux_schedule_timeout(int timeout); +long linux_schedule_timeout(long timeout); static inline void linux_schedule_save_interrupt_value(struct task_struct *task, int value) diff --git a/sys/compat/linuxkpi/common/include/linux/sched/mm.h b/sys/compat/linuxkpi/common/include/linux/sched/mm.h new file mode 100644 index 000000000000..c26d99378974 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/sched/mm.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_SCHED_MM_H_ +#define _LINUXKPI_LINUX_SCHED_MM_H_ + +#include <linux/gfp.h> + +#define fs_reclaim_acquire(x) do { \ + } while (0) +#define fs_reclaim_release(x) do { \ + } while (0) +#define memalloc_nofs_save(x) 0 +#define memalloc_nofs_restore(x) do { \ + } while (0) +#define memalloc_noreclaim_save(x) 0 +#define memalloc_noreclaim_restore(x) do { \ + } while (0) + +#endif /* _BSD_LKPI_LINUX_SCHED_MM_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/semaphore.h b/sys/compat/linuxkpi/common/include/linux/semaphore.h index da1fc73b1776..4b1a1502e589 100644 --- a/sys/compat/linuxkpi/common/include/linux/semaphore.h +++ b/sys/compat/linuxkpi/common/include/linux/semaphore.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SEMAPHORE_H_ #define _LINUXKPI_LINUX_SEMAPHORE_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/seq_file.h b/sys/compat/linuxkpi/common/include/linux/seq_file.h index 9ab5ecce7768..876ef9e8dfe5 100644 --- a/sys/compat/linuxkpi/common/include/linux/seq_file.h +++ b/sys/compat/linuxkpi/common/include/linux/seq_file.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org> * @@ -23,20 +23,24 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SEQ_FILE_H_ #define _LINUXKPI_LINUX_SEQ_FILE_H_ +#include <sys/types.h> +#include <sys/sbuf.h> + #include <linux/types.h> #include <linux/fs.h> -#include <sys/sbuf.h> +#include <linux/string_helpers.h> +#include <linux/printk.h> #undef file #define inode vnode +MALLOC_DECLARE(M_LSEQ); + #define DEFINE_SHOW_ATTRIBUTE(__name) \ static int __name ## _open(struct inode *inode, struct linux_file *file) \ { \ @@ -51,11 +55,9 @@ static const struct file_operations __name ## _fops = { \ .release = single_release, \ } -struct seq_operations; - struct seq_file { - struct sbuf *buf; - + struct sbuf *buf; + size_t size; const struct seq_operations *op; const struct linux_file *file; void *private; @@ -70,18 +72,36 @@ struct seq_operations { ssize_t seq_read(struct linux_file *, char *, size_t, off_t *); int seq_write(struct seq_file *seq, const void *data, size_t len); +void seq_putc(struct seq_file *m, char c); +void seq_puts(struct seq_file *m, const char *str); +bool seq_has_overflowed(struct seq_file *m); + +void *__seq_open_private(struct linux_file *, const struct seq_operations *, int); +int seq_release_private(struct inode *, struct linux_file *); int seq_open(struct linux_file *f, const struct seq_operations *op); int seq_release(struct inode *inode, struct linux_file *file); off_t seq_lseek(struct linux_file *file, off_t offset, int whence); int single_open(struct linux_file *, int (*)(struct seq_file *, void *), void *); +int single_open_size(struct linux_file *, int (*)(struct seq_file *, void *), void *, size_t); int single_release(struct inode *, struct linux_file *); -#define seq_printf(m, fmt, ...) sbuf_printf((m)->buf, (fmt), ##__VA_ARGS__) +void lkpi_seq_vprintf(struct seq_file *m, const char *fmt, va_list args); +void lkpi_seq_printf(struct seq_file *m, const char *fmt, ...); + +#define seq_vprintf(...) lkpi_seq_vprintf(__VA_ARGS__) +#define seq_printf(...) lkpi_seq_printf(__VA_ARGS__) -#define seq_puts(m, str) sbuf_printf((m)->buf, str) -#define seq_putc(m, str) sbuf_putc((m)->buf, str) +int __lkpi_hexdump_sbuf_printf(void *, const char *, ...) __printflike(2, 3); + +static inline void +seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type, + int rowsize, int groupsize, const void *buf, size_t len, bool ascii) +{ + lkpi_hex_dump(__lkpi_hexdump_sbuf_printf, m->buf, NULL, prefix_str, prefix_type, + rowsize, groupsize, buf, len, ascii); +} #define file linux_file diff --git a/sys/compat/linuxkpi/common/include/linux/seqlock.h b/sys/compat/linuxkpi/common/include/linux/seqlock.h index 6e81e7a0fa45..554fdfd6e202 100644 --- a/sys/compat/linuxkpi/common/include/linux/seqlock.h +++ b/sys/compat/linuxkpi/common/include/linux/seqlock.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> * @@ -31,8 +31,10 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/cdefs.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/rwlock.h> #include <sys/seqc.h> struct lock_class_key; @@ -48,6 +50,12 @@ struct seqlock { }; typedef struct seqlock seqlock_t; +struct seqcount_mutex { + seqc_t seqc; +}; +typedef struct seqcount_mutex seqcount_mutex_t; +typedef struct seqcount_mutex seqcount_ww_mutex_t; + static inline void __seqcount_init(struct seqcount *seqcount, const char *name __unused, struct lock_class_key *key __unused) @@ -57,16 +65,43 @@ __seqcount_init(struct seqcount *seqcount, const char *name __unused, #define seqcount_init(seqcount) __seqcount_init(seqcount, NULL, NULL) static inline void -write_seqcount_begin(struct seqcount *seqcount) +seqcount_mutex_init(struct seqcount_mutex *seqcount, void *mutex __unused) { - seqc_sleepable_write_begin(&seqcount->seqc); + seqcount->seqc = 0; } +#define seqcount_ww_mutex_init(seqcount, ww_mutex) \ + seqcount_mutex_init((seqcount), (ww_mutex)) + +#define write_seqcount_begin(s) \ + _Generic(*(s), \ + struct seqcount: seqc_sleepable_write_begin, \ + struct seqcount_mutex: seqc_write_begin \ + )(&(s)->seqc) + +#define write_seqcount_end(s) \ + _Generic(*(s), \ + struct seqcount: seqc_sleepable_write_end, \ + struct seqcount_mutex: seqc_write_end \ + )(&(s)->seqc) + static inline void -write_seqcount_end(struct seqcount *seqcount) +lkpi_write_seqcount_invalidate(seqc_t *seqcp) { - seqc_sleepable_write_end(&seqcount->seqc); + atomic_thread_fence_rel(); + *seqcp += SEQC_MOD * 2; } +#define write_seqcount_invalidate(s) lkpi_write_seqcount_invalidate(&(s)->seqc) + +#define read_seqcount_begin(s) seqc_read(&(s)->seqc) +#define raw_read_seqcount(s) seqc_read_any(&(s)->seqc) + +static inline seqc_t +lkpi_seqprop_sequence(const seqc_t *seqcp) +{ + return (atomic_load_int(seqcp)); +} +#define seqprop_sequence(s) lkpi_seqprop_sequence(&(s)->seqc) /* * XXX: Are predicts from inline functions still not honored by clang? @@ -76,18 +111,6 @@ write_seqcount_end(struct seqcount *seqcount) #define read_seqcount_retry(seqcount, gen) \ (!seqc_consistent(&(seqcount)->seqc, gen)) -static inline unsigned -read_seqcount_begin(const struct seqcount *seqcount) -{ - return (seqc_read(&seqcount->seqc)); -} - -static inline unsigned -raw_read_seqcount(const struct seqcount *seqcount) -{ - return (seqc_read_any(&seqcount->seqc)); -} - static inline void seqlock_init(struct seqlock *seqlock) { diff --git a/sys/compat/linuxkpi/common/include/linux/shmem_fs.h b/sys/compat/linuxkpi/common/include/linux/shmem_fs.h index 240d26c47685..5e91725d4a1c 100644 --- a/sys/compat/linuxkpi/common/include/linux/shmem_fs.h +++ b/sys/compat/linuxkpi/common/include/linux/shmem_fs.h @@ -25,20 +25,22 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SHMEM_FS_H_ #define _LINUXKPI_LINUX_SHMEM_FS_H_ -/* Shared memory support */ -unsigned long linux_invalidate_mapping_pages(vm_object_t, pgoff_t, pgoff_t); -struct page *linux_shmem_read_mapping_page_gfp(vm_object_t, int, gfp_t); -struct linux_file *linux_shmem_file_setup(const char *, loff_t, unsigned long); -void linux_shmem_truncate_range(vm_object_t, loff_t, loff_t); +#include <linux/file.h> +#include <linux/mempolicy.h> +#include <linux/pagemap.h> +#include <linux/swap.h> -#define invalidate_mapping_pages(...) \ - linux_invalidate_mapping_pages(__VA_ARGS__) +/* Shared memory support */ +struct page *linux_shmem_read_mapping_page_gfp(vm_object_t obj, int pindex, + gfp_t gfp); +struct linux_file *linux_shmem_file_setup(const char *name, loff_t size, + unsigned long flags); +void linux_shmem_truncate_range(vm_object_t obj, loff_t lstart, + loff_t lend); #define shmem_read_mapping_page(...) \ linux_shmem_read_mapping_page_gfp(__VA_ARGS__, 0) @@ -52,4 +54,14 @@ void linux_shmem_truncate_range(vm_object_t, loff_t, loff_t); #define shmem_truncate_range(...) \ linux_shmem_truncate_range(__VA_ARGS__) +static inline struct folio * +shmem_read_folio_gfp(vm_object_t obj, int pindex, gfp_t gfp) +{ + struct page *page; + + page = shmem_read_mapping_page_gfp(obj, pindex, gfp); + + return (page_folio(page)); +} + #endif /* _LINUXKPI_LINUX_SHMEM_FS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/shrinker.h b/sys/compat/linuxkpi/common/include/linux/shrinker.h index 05f702e62fd5..eb95dafb83ce 100644 --- a/sys/compat/linuxkpi/common/include/linux/shrinker.h +++ b/sys/compat/linuxkpi/common/include/linux/shrinker.h @@ -21,8 +21,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SHRINKER_H_ @@ -30,7 +28,11 @@ #include <sys/queue.h> +#include <linux/bitops.h> +#include <linux/gfp.h> + struct shrink_control { + gfp_t gfp_mask; unsigned long nr_to_scan; unsigned long nr_scanned; }; @@ -39,6 +41,8 @@ struct shrinker { unsigned long (*count_objects)(struct shrinker *, struct shrink_control *); unsigned long (*scan_objects)(struct shrinker *, struct shrink_control *); int seeks; + unsigned int flags; + void * private_data; long batch; TAILQ_ENTRY(shrinker) next; }; @@ -47,10 +51,29 @@ struct shrinker { #define DEFAULT_SEEKS 2 +#define SHRINKER_REGISTERED BIT(0) +#define SHRINKER_ALLOCATED BIT(1) + +struct shrinker *linuxkpi_shrinker_alloc( + unsigned int flags, const char *fmt, ...); int linuxkpi_register_shrinker(struct shrinker *s); void linuxkpi_unregister_shrinker(struct shrinker *s); +void linuxkpi_shrinker_free(struct shrinker *shrinker); +void linuxkpi_synchronize_shrinkers(void); + +#define shrinker_alloc(flags, fmt, ...) \ + linuxkpi_shrinker_alloc(flags, fmt __VA_OPT__(,) __VA_ARGS__) +#define shrinker_register(shrinker) \ + linuxkpi_register_shrinker(shrinker) +#define shrinker_free(shrinker) \ + linuxkpi_shrinker_free(shrinker) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60000 +#define register_shrinker(s, ...) linuxkpi_register_shrinker(s) +#else #define register_shrinker(s) linuxkpi_register_shrinker(s) +#endif #define unregister_shrinker(s) linuxkpi_unregister_shrinker(s) +#define synchronize_shrinkers() linuxkpi_synchronize_shrinkers() #endif /* _LINUXKPI_LINUX_SHRINKER_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/sizes.h b/sys/compat/linuxkpi/common/include/linux/sizes.h index b132eedff933..d8a6e75192f6 100644 --- a/sys/compat/linuxkpi/common/include/linux/sizes.h +++ b/sys/compat/linuxkpi/common/include/linux/sizes.h @@ -24,14 +24,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SIZES_H_ #define _LINUXKPI_LINUX_SIZES_H_ #define SZ_1K (1024 * 1) +#define SZ_2K (1024 * 2) #define SZ_4K (1024 * 4) #define SZ_8K (1024 * 8) #define SZ_16K (1024 * 16) @@ -43,9 +42,22 @@ #define SZ_1M (1024 * 1024 * 1) #define SZ_2M (1024 * 1024 * 2) +#define SZ_4M (1024 * 1024 * 4) #define SZ_8M (1024 * 1024 * 8) #define SZ_16M (1024 * 1024 * 16) #define SZ_32M (1024 * 1024 * 32) #define SZ_64M (1024 * 1024 * 64) +#define SZ_128M (1024 * 1024 * 128) +#define SZ_256M (1024 * 1024 * 256) +#define SZ_512M (1024 * 1024 * 512) + +#define SZ_1G (1024 * 1024 * 1024 * 1) +#define SZ_2G (1024 * 1024 * 1024 * 2) +#define SZ_4G (1024 * 1024 * 1024 * 4) +#define SZ_8G (1024 * 1024 * 1024 * 8) +#define SZ_16G (1024 * 1024 * 1024 * 16) +#define SZ_32G (1024 * 1024 * 1024 * 32) + +#define SZ_64T (1024 * 1024 * 1024 * 1024 * 64) #endif diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h index 3caf7059dd15..c8ad90281e34 100644 --- a/sys/compat/linuxkpi/common/include/linux/skbuff.h +++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h @@ -1,6 +1,6 @@ /*- - * Copyright (c) 2020-2022 The FreeBSD Foundation - * Copyright (c) 2021-2022 Bjoern A. Zeeb + * Copyright (c) 2020-2025 The FreeBSD Foundation + * Copyright (c) 2021-2023 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -25,8 +25,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ /* @@ -46,8 +44,18 @@ #include <linux/gfp.h> #include <linux/compiler.h> #include <linux/spinlock.h> +#include <linux/ktime.h> +#include <linux/compiler.h> + +#include "opt_wlan.h" + +/* Currently this is only used for wlan so we can depend on that. */ +#if defined(IEEE80211_DEBUG) && !defined(SKB_DEBUG) +#define SKB_DEBUG +#endif /* #define SKB_DEBUG */ + #ifdef SKB_DEBUG #define DSKB_TODO 0x01 #define DSKB_IMPROVE 0x02 @@ -85,12 +93,25 @@ enum sk_buff_pkt_type { PACKET_OTHERHOST, }; +struct skb_shared_hwtstamps { + ktime_t hwtstamp; +}; + #define NET_SKB_PAD max(CACHE_LINE_SIZE, 32) +#define SKB_DATA_ALIGN(_x) roundup2(_x, CACHE_LINE_SIZE) struct sk_buff_head { /* XXX TODO */ - struct sk_buff *next; - struct sk_buff *prev; + union { + struct { + struct sk_buff *next; + struct sk_buff *prev; + }; + struct sk_buff_head_l { + struct sk_buff *next; + struct sk_buff *prev; + } list; + }; size_t qlen; spinlock_t lock; }; @@ -124,39 +145,54 @@ struct skb_shared_info { }; struct sk_buff { - /* XXX TODO */ - /* struct sk_buff_head */ - struct sk_buff *next; - struct sk_buff *prev; - int list; /* XXX TYPE */ - uint32_t _alloc_len; /* Length of alloc data-buf. XXX-BZ give up for truesize? */ + /* XXX TODO */ + union { + /* struct sk_buff_head */ + struct { + struct sk_buff *next; + struct sk_buff *prev; + }; + struct list_head list; + }; + + uint8_t *head; /* Head of buffer. */ + uint8_t *data; /* Head of data. */ + uint8_t *tail; /* End of data. */ + uint8_t *end; /* End of buffer. */ + uint32_t len; /* ? */ uint32_t data_len; /* ? If we have frags? */ - uint32_t truesize; /* The total size of all buffers, incl. frags. */ - uint16_t mac_len; /* Link-layer header length. */ - __sum16 csum; - uint16_t l3hdroff; /* network header offset from *head */ - uint16_t l4hdroff; /* transport header offset from *head */ - uint32_t priority; - uint16_t qmap; /* queue mapping */ - uint16_t _spareu16_0; - enum sk_buff_pkt_type pkt_type; + union { + __wsum csum; + struct { + uint16_t csum_offset; + uint16_t csum_start; + }; + }; + uint16_t protocol; + uint8_t ip_summed; + /* uint8_t */ /* "Scratch" area for layers to store metadata. */ /* ??? I see sizeof() operations so probably an array. */ uint8_t cb[64] __aligned(CACHE_LINE_SIZE); - struct net_device *dev; - void *sk; /* XXX net/sock.h? */ - - int csum_offset, csum_start, ip_summed, protocol; + struct skb_shared_info *shinfo __aligned(CACHE_LINE_SIZE); - uint8_t *head; /* Head of buffer. */ - uint8_t *data; /* Head of data. */ - uint8_t *tail; /* End of data. */ - uint8_t *end; /* End of buffer. */ + uint32_t truesize; /* The total size of all buffers, incl. frags. */ + uint32_t priority; + uint16_t qmap; /* queue mapping */ + uint16_t _flags; /* Internal flags. */ +#define _SKB_FLAGS_SKBEXTFRAG 0x0001 + uint16_t l3hdroff; /* network header offset from *head */ + uint16_t l4hdroff; /* transport header offset from *head */ + uint16_t mac_header; /* offset of mac_header */ + uint16_t mac_len; /* Link-layer header length. */ + enum sk_buff_pkt_type pkt_type; + refcount_t refcnt; - struct skb_shared_info *shinfo; + struct net_device *dev; + void *sk; /* XXX net/sock.h? */ /* FreeBSD specific bandaid (see linuxkpi_kfree_skb). */ void *m; @@ -170,9 +206,10 @@ struct sk_buff { struct sk_buff *linuxkpi_alloc_skb(size_t, gfp_t); struct sk_buff *linuxkpi_dev_alloc_skb(size_t, gfp_t); +struct sk_buff *linuxkpi_build_skb(void *, size_t); void linuxkpi_kfree_skb(struct sk_buff *); -struct sk_buff *linuxkpi_skb_copy(struct sk_buff *, gfp_t); +struct sk_buff *linuxkpi_skb_copy(const struct sk_buff *, gfp_t); /* -------------------------------------------------------------------------- */ @@ -216,6 +253,13 @@ kfree_skb(struct sk_buff *skb) } static inline void +consume_skb(struct sk_buff *skb) +{ + SKB_TRACE(skb); + kfree_skb(skb); +} + +static inline void dev_kfree_skb(struct sk_buff *skb) { SKB_TRACE(skb); @@ -237,11 +281,24 @@ dev_kfree_skb_irq(struct sk_buff *skb) dev_kfree_skb(skb); } +static inline struct sk_buff * +build_skb(void *data, unsigned int fragsz) +{ + struct sk_buff *skb; + + skb = linuxkpi_build_skb(data, fragsz); + SKB_TRACE(skb); + return (skb); +} + /* -------------------------------------------------------------------------- */ -/* XXX BZ review this one for terminal condition as Linux "queues" are special. */ -#define skb_list_walk_safe(_q, skb, tmp) \ - for ((skb) = (_q)->next; (skb) != NULL && ((tmp) = (skb)->next); (skb) = (tmp)) +static inline bool +skb_is_nonlinear(struct sk_buff *skb) +{ + SKB_TRACE(skb); + return ((skb->data_len > 0) ? true : false); +} /* Add headroom; cannot do once there is data in there. */ static inline void @@ -266,7 +323,7 @@ skb_reserve(struct sk_buff *skb, size_t len) * front to copy data in (manually). */ static inline void * -skb_push(struct sk_buff *skb, size_t len) +__skb_push(struct sk_buff *skb, size_t len) { SKB_TRACE(skb); KASSERT(((skb->data - len) >= skb->head), ("%s: skb %p (data %p - " @@ -276,6 +333,14 @@ skb_push(struct sk_buff *skb, size_t len) return (skb->data); } +static inline void * +skb_push(struct sk_buff *skb, size_t len) +{ + + SKB_TRACE(skb); + return (__skb_push(skb, len)); +} + /* * Length of the data on the skb (without any frags)??? */ @@ -305,12 +370,14 @@ skb_tailroom(struct sk_buff *skb) SKB_TRACE(skb); KASSERT((skb->end - skb->tail) >= 0, ("%s: skb %p tailroom < 0, " "end %p tail %p\n", __func__, skb, skb->end, skb->tail)); + if (unlikely(skb_is_nonlinear(skb))) + return (0); return (skb->end - skb->tail); } -/* Return numer of bytes available at the beginning of buffer. */ +/* Return number of bytes available at the beginning of buffer. */ static inline unsigned int -skb_headroom(struct sk_buff *skb) +skb_headroom(const struct sk_buff *skb) { SKB_TRACE(skb); KASSERT((skb->data - skb->head) >= 0, ("%s: skb %p headroom < 0, " @@ -324,7 +391,7 @@ skb_headroom(struct sk_buff *skb) * the end to copy data in (manually). See also skb_put_data() below. */ static inline void * -skb_put(struct sk_buff *skb, size_t len) +__skb_put(struct sk_buff *skb, size_t len) { void *s; @@ -347,6 +414,14 @@ skb_put(struct sk_buff *skb, size_t len) return (s); } +static inline void * +skb_put(struct sk_buff *skb, size_t len) +{ + + SKB_TRACE(skb); + return (__skb_put(skb, len)); +} + /* skb_put() + copying data in. */ static inline void * skb_put_data(struct sk_buff *skb, const void *buf, size_t len) @@ -447,14 +522,12 @@ skb_add_rx_frag(struct sk_buff *skb, int fragno, struct page *page, shinfo->frags[fragno].size = size; shinfo->nr_frags = fragno + 1; skb->len += size; + skb->data_len += size; skb->truesize += truesize; - - /* XXX TODO EXTEND truesize? */ } /* -------------------------------------------------------------------------- */ -/* XXX BZ review this one for terminal condition as Linux "queues" are special. */ #define skb_queue_walk(_q, skb) \ for ((skb) = (_q)->next; (skb) != (struct sk_buff *)(_q); \ (skb) = (skb)->next) @@ -463,12 +536,23 @@ skb_add_rx_frag(struct sk_buff *skb, int fragno, struct page *page, for ((skb) = (_q)->next, (tmp) = (skb)->next; \ (skb) != (struct sk_buff *)(_q); (skb) = (tmp), (tmp) = (skb)->next) +#define skb_list_walk_safe(_q, skb, tmp) \ + for ((skb) = (_q), (tmp) = ((skb) != NULL) ? (skb)->next ? NULL; \ + ((skb) != NULL); \ + (skb) = (tmp), (tmp) = ((skb) != NULL) ? (skb)->next ? NULL) + static inline bool -skb_queue_empty(struct sk_buff_head *q) +skb_queue_empty(const struct sk_buff_head *q) { + SKB_TRACE(q); + return (q->next == (const struct sk_buff *)q); +} +static inline bool +skb_queue_empty_lockless(const struct sk_buff_head *q) +{ SKB_TRACE(q); - return (q->qlen == 0); + return (READ_ONCE(q->next) == (const struct sk_buff *)q); } static inline void @@ -483,7 +567,8 @@ static inline void skb_queue_head_init(struct sk_buff_head *q) { SKB_TRACE(q); - return (__skb_queue_head_init(q)); + __skb_queue_head_init(q); + spin_lock_init(&q->lock); } static inline void @@ -492,11 +577,11 @@ __skb_insert(struct sk_buff *new, struct sk_buff *prev, struct sk_buff *next, { SKB_TRACE_FMT(new, "prev %p next %p q %p", prev, next, q); - new->prev = prev; - new->next = next; - next->prev = new; - prev->next = new; - q->qlen++; + WRITE_ONCE(new->prev, prev); + WRITE_ONCE(new->next, next); + WRITE_ONCE(((struct sk_buff_head_l *)next)->prev, new); + WRITE_ONCE(((struct sk_buff_head_l *)prev)->next, new); + WRITE_ONCE(q->qlen, q->qlen + 1); } static inline void @@ -505,7 +590,7 @@ __skb_queue_after(struct sk_buff_head *q, struct sk_buff *skb, { SKB_TRACE_FMT(q, "skb %p new %p", skb, new); - __skb_insert(new, skb, skb->next, q); + __skb_insert(new, skb, ((struct sk_buff_head_l *)skb)->next, q); } static inline void @@ -518,57 +603,72 @@ __skb_queue_before(struct sk_buff_head *q, struct sk_buff *skb, } static inline void -__skb_queue_tail(struct sk_buff_head *q, struct sk_buff *skb) +__skb_queue_tail(struct sk_buff_head *q, struct sk_buff *new) { - struct sk_buff *s; - SKB_TRACE2(q, skb); - q->qlen++; - s = (struct sk_buff *)q; - s->prev->next = skb; - skb->prev = s->prev; - skb->next = s; - s->prev = skb; + SKB_TRACE2(q, new); + __skb_queue_before(q, (struct sk_buff *)q, new); } static inline void -skb_queue_tail(struct sk_buff_head *q, struct sk_buff *skb) +skb_queue_tail(struct sk_buff_head *q, struct sk_buff *new) { + unsigned long flags; + + SKB_TRACE2(q, new); + spin_lock_irqsave(&q->lock, flags); + __skb_queue_tail(q, new); + spin_unlock_irqrestore(&q->lock, flags); +} + +static inline struct sk_buff * +skb_peek(const struct sk_buff_head *q) +{ + struct sk_buff *skb; + + skb = q->next; SKB_TRACE2(q, skb); - return (__skb_queue_tail(q, skb)); + if (skb == (const struct sk_buff *)q) + return (NULL); + return (skb); } static inline struct sk_buff * -skb_peek_tail(struct sk_buff_head *q) +skb_peek_tail(const struct sk_buff_head *q) { struct sk_buff *skb; - skb = q->prev; + skb = READ_ONCE(q->prev); SKB_TRACE2(q, skb); - if (skb == (struct sk_buff *)q) + if (skb == (const struct sk_buff *)q) return (NULL); return (skb); } static inline void -__skb_unlink(struct sk_buff *skb, struct sk_buff_head *head) +__skb_unlink(struct sk_buff *skb, struct sk_buff_head *q) { - SKB_TRACE2(skb, head); - struct sk_buff *p, *n;; + struct sk_buff *p, *n; - head->qlen--; + SKB_TRACE2(skb, q); + + WRITE_ONCE(q->qlen, q->qlen - 1); p = skb->prev; n = skb->next; - p->next = n; - n->prev = p; + WRITE_ONCE(n->prev, p); + WRITE_ONCE(p->next, n); skb->prev = skb->next = NULL; } static inline void -skb_unlink(struct sk_buff *skb, struct sk_buff_head *head) +skb_unlink(struct sk_buff *skb, struct sk_buff_head *q) { - SKB_TRACE2(skb, head); - return (__skb_unlink(skb, head)); + unsigned long flags; + + SKB_TRACE2(skb, q); + spin_lock_irqsave(&q->lock, flags); + __skb_unlink(skb, q); + spin_unlock_irqrestore(&q->lock, flags); } static inline struct sk_buff * @@ -576,32 +676,47 @@ __skb_dequeue(struct sk_buff_head *q) { struct sk_buff *skb; - SKB_TRACE(q); - skb = q->next; - if (skb == (struct sk_buff *)q) - return (NULL); + skb = skb_peek(q); if (skb != NULL) __skb_unlink(skb, q); - SKB_TRACE(skb); + SKB_TRACE2(q, skb); return (skb); } static inline struct sk_buff * skb_dequeue(struct sk_buff_head *q) { - SKB_TRACE(q); - return (__skb_dequeue(q)); + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb = __skb_dequeue(q); + spin_unlock_irqrestore(&q->lock, flags); + SKB_TRACE2(q, skb); + return (skb); } static inline struct sk_buff * -skb_dequeue_tail(struct sk_buff_head *q) +__skb_dequeue_tail(struct sk_buff_head *q) { struct sk_buff *skb; skb = skb_peek_tail(q); if (skb != NULL) __skb_unlink(skb, q); + SKB_TRACE2(q, skb); + return (skb); +} +static inline struct sk_buff * +skb_dequeue_tail(struct sk_buff_head *q) +{ + unsigned long flags; + struct sk_buff *skb; + + spin_lock_irqsave(&q->lock, flags); + skb = __skb_dequeue_tail(q); + spin_unlock_irqrestore(&q->lock, flags); SKB_TRACE2(q, skb); return (skb); } @@ -617,27 +732,74 @@ __skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb) static inline void skb_queue_head(struct sk_buff_head *q, struct sk_buff *skb) { + unsigned long flags; SKB_TRACE2(q, skb); - __skb_queue_after(q, (struct sk_buff *)q, skb); + spin_lock_irqsave(&q->lock, flags); + __skb_queue_head(q, skb); + spin_unlock_irqrestore(&q->lock, flags); } static inline uint32_t -skb_queue_len(struct sk_buff_head *head) +skb_queue_len(const struct sk_buff_head *q) { - SKB_TRACE(head); - return (head->qlen); + SKB_TRACE(q); + return (q->qlen); } static inline uint32_t -skb_queue_len_lockless(const struct sk_buff_head *head) +skb_queue_len_lockless(const struct sk_buff_head *q) +{ + + SKB_TRACE(q); + return (READ_ONCE(q->qlen)); +} + +static inline void +___skb_queue_splice(const struct sk_buff_head *from, + struct sk_buff *p, struct sk_buff *n) +{ + struct sk_buff *b, *e; + + b = from->next; + e = from->prev; + + WRITE_ONCE(b->prev, p); + WRITE_ONCE(((struct sk_buff_head_l *)p)->next, b); + WRITE_ONCE(e->next, n); + WRITE_ONCE(((struct sk_buff_head_l *)n)->prev, e); +} + +static inline void +skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to) +{ + + SKB_TRACE2(from, to); + + if (skb_queue_empty(from)) + return; + + ___skb_queue_splice(from, (struct sk_buff *)to, to->next); + to->qlen += from->qlen; + __skb_queue_head_init(from); +} + +static inline void +skb_queue_splice_tail_init(struct sk_buff_head *from, struct sk_buff_head *to) { - SKB_TRACE(head); - return (READ_ONCE(head->qlen)); + SKB_TRACE2(from, to); + + if (skb_queue_empty(from)) + return; + + ___skb_queue_splice(from, to->prev, (struct sk_buff *)to); + to->qlen += from->qlen; + __skb_queue_head_init(from); } + static inline void __skb_queue_purge(struct sk_buff_head *q) { @@ -646,13 +808,26 @@ __skb_queue_purge(struct sk_buff_head *q) SKB_TRACE(q); while ((skb = __skb_dequeue(q)) != NULL) kfree_skb(skb); + WARN_ONCE(skb_queue_len(q) != 0, "%s: queue %p not empty: %u", + __func__, q, skb_queue_len(q)); } static inline void skb_queue_purge(struct sk_buff_head *q) { + struct sk_buff_head _q; + unsigned long flags; + SKB_TRACE(q); - return (__skb_queue_purge(q)); + + if (skb_queue_empty_lockless(q)) + return; + + __skb_queue_head_init(&_q); + spin_lock_irqsave(&q->lock, flags); + skb_queue_splice_init(q, &_q); + spin_unlock_irqrestore(&q->lock, flags); + __skb_queue_purge(&_q); } static inline struct sk_buff * @@ -667,7 +842,7 @@ skb_queue_prev(struct sk_buff_head *q, struct sk_buff *skb) /* -------------------------------------------------------------------------- */ static inline struct sk_buff * -skb_copy(struct sk_buff *skb, gfp_t gfp) +skb_copy(const struct sk_buff *skb, gfp_t gfp) { struct sk_buff *new; @@ -676,13 +851,6 @@ skb_copy(struct sk_buff *skb, gfp_t gfp) return (new); } -static inline void -consume_skb(struct sk_buff *skb) -{ - SKB_TRACE(skb); - SKB_TODO(); -} - static inline uint16_t skb_checksum(struct sk_buff *skb, int offs, size_t len, int x) { @@ -712,15 +880,7 @@ static inline size_t skb_frag_size(const skb_frag_t *frag) { SKB_TRACE(frag); - SKB_TODO(); - return (-1); -} - -static inline bool -skb_is_nonlinear(struct sk_buff *skb) -{ - SKB_TRACE(skb); - return ((skb->data_len > 0) ? true : false); + return (frag->size); } #define skb_walk_frags(_skb, _frag) \ @@ -745,8 +905,14 @@ static inline void * skb_frag_address(const skb_frag_t *frag) { SKB_TRACE(frag); - SKB_TODO(); - return (NULL); + return (page_address(frag->page + frag->offset)); +} + +static inline void +skb_free_frag(void *frag) +{ + + page_frag_free(frag); } static inline struct sk_buff * @@ -769,31 +935,7 @@ static inline void skb_mark_not_on_list(struct sk_buff *skb) { SKB_TRACE(skb); - SKB_TODO(); -} - -static inline void -skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to) -{ - struct sk_buff *b, *e, *n; - - SKB_TRACE2(from, to); - - if (skb_queue_empty(from)) - return; - - /* XXX do we need a barrier around this? */ - b = from->next; - e = from->prev; - n = to->next; - - b->prev = (struct sk_buff *)to; - to->next = b; - e->next = n; - n->prev = e; - - to->qlen += from->qlen; - __skb_queue_head_init(from); + skb->next = NULL; } static inline void @@ -825,7 +967,13 @@ __skb_linearize(struct sk_buff *skb) { SKB_TRACE(skb); SKB_TODO(); - return (ENXIO); + return (-ENXIO); +} + +static inline int +skb_linearize(struct sk_buff *skb) +{ + return (skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0); } static inline int @@ -853,48 +1001,61 @@ skb_get_queue_mapping(struct sk_buff *skb) return (skb->qmap); } +static inline void +skb_copy_header(struct sk_buff *to, const struct sk_buff *from) +{ + SKB_TRACE2(to, from); + SKB_TODO(); +} + static inline bool skb_header_cloned(struct sk_buff *skb) { SKB_TRACE(skb); SKB_TODO(); - return (false); + return (true); } static inline uint8_t * -skb_mac_header(struct sk_buff *skb) +skb_mac_header(const struct sk_buff *skb) { SKB_TRACE(skb); - SKB_TODO(); - return (NULL); + return (skb->head + skb->mac_header); } static inline void -skb_orphan(struct sk_buff *skb) +skb_reset_mac_header(struct sk_buff *skb) { SKB_TRACE(skb); - SKB_TODO(); + skb->mac_header = skb->data - skb->head; } static inline void -skb_reset_mac_header(struct sk_buff *skb) +skb_set_mac_header(struct sk_buff *skb, const size_t len) { SKB_TRACE(skb); - SKB_TODO(); + skb_reset_mac_header(skb); + skb->mac_header += len; } -static inline struct sk_buff * -skb_peek(struct sk_buff_head *q) +static inline struct skb_shared_hwtstamps * +skb_hwtstamps(struct sk_buff *skb) { - SKB_TRACE(q); + SKB_TRACE(skb); SKB_TODO(); return (NULL); } -static inline __sum16 -csum_unfold(__sum16 sum) +static inline void +skb_orphan(struct sk_buff *skb) { + SKB_TRACE(skb); SKB_TODO(); +} + +static inline __wsum +csum_unfold(__sum16 sum) +{ return (sum); } @@ -909,7 +1070,10 @@ skb_reset_tail_pointer(struct sk_buff *skb) { SKB_TRACE(skb); +#ifdef SKB_DOING_OFFSETS_US_NOT skb->tail = (uint8_t *)(uintptr_t)(skb->data - skb->head); +#endif + skb->tail = skb->data; SKB_TRACE(skb); } @@ -917,7 +1081,8 @@ static inline struct sk_buff * skb_get(struct sk_buff *skb) { - SKB_TODO(); /* XXX refcnt? as in get/put_device? */ + SKB_TRACE(skb); + refcount_inc(&skb->refcnt); return (skb); } @@ -938,4 +1103,65 @@ skb_copy_from_linear_data(const struct sk_buff *skb, void *dst, size_t len) memcpy(dst, skb->data, len); } +static inline int +skb_pad(struct sk_buff *skb, int pad) +{ + + SKB_TRACE(skb); + SKB_TODO(); + return (-1); +} + +static inline void +skb_list_del_init(struct sk_buff *skb) +{ + + SKB_TRACE(skb); + __list_del_entry(&skb->list); + skb_mark_not_on_list(skb); +} + +static inline void +napi_consume_skb(struct sk_buff *skb, int budget) +{ + + SKB_TRACE(skb); + SKB_TODO(); +} + +static inline struct sk_buff * +napi_build_skb(void *data, size_t len) +{ + + SKB_TODO(); + return (NULL); +} + +static inline uint32_t +skb_get_hash(struct sk_buff *skb) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (0); +} + +static inline void +skb_mark_for_recycle(struct sk_buff *skb) +{ + SKB_TRACE(skb); + /* page_pool */ + SKB_TODO(); +} + +static inline int +skb_cow_head(struct sk_buff *skb, unsigned int headroom) +{ + SKB_TRACE(skb); + SKB_TODO(); + return (-1); +} + +#define SKB_WITH_OVERHEAD(_s) \ + (_s) - ALIGN(sizeof(struct skb_shared_info), CACHE_LINE_SIZE) + #endif /* _LINUXKPI_LINUX_SKBUFF_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h index 1228c4d07aa6..efa5c8cb67b3 100644 --- a/sys/compat/linuxkpi/common/include/linux/slab.h +++ b/sys/compat/linuxkpi/common/include/linux/slab.h @@ -4,6 +4,10 @@ * Copyright (c) 2010 Panasas, Inc. * Copyright (c) 2013-2021 Mellanox Technologies, Ltd. * All rights reserved. + * Copyright (c) 2024-2025 The FreeBSD Foundation + * + * Portions of this software were developed by Björn Zeeb + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,8 +29,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SLAB_H_ #define _LINUXKPI_LINUX_SLAB_H_ @@ -43,19 +45,18 @@ MALLOC_DECLARE(M_KMALLOC); -#define kvmalloc(size, flags) kmalloc(size, flags) -#define kvzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO) +#define kvzalloc(size, flags) kvmalloc(size, (flags) | __GFP_ZERO) #define kvcalloc(n, size, flags) kvmalloc_array(n, size, (flags) | __GFP_ZERO) #define kzalloc(size, flags) kmalloc(size, (flags) | __GFP_ZERO) #define kzalloc_node(size, flags, node) kmalloc_node(size, (flags) | __GFP_ZERO, node) #define kfree_const(ptr) kfree(ptr) +#define kfree_async(ptr) kfree(ptr) /* drm-kmod 5.4 compat */ #define vzalloc(size) __vmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, 0) #define vfree(arg) kfree(arg) #define kvfree(arg) kfree(arg) #define vmalloc_node(size, node) __vmalloc_node(size, GFP_KERNEL, node) #define vmalloc_user(size) __vmalloc(size, GFP_KERNEL | __GFP_ZERO, 0) #define vmalloc(size) __vmalloc(size, GFP_KERNEL, 0) -#define __kmalloc(...) kmalloc(__VA_ARGS__) /* * Prefix some functions with linux_ to avoid namespace conflict @@ -67,6 +68,7 @@ MALLOC_DECLARE(M_KMALLOC); #define kmem_cache_zalloc(...) lkpi_kmem_cache_zalloc(__VA_ARGS__) #define kmem_cache_free(...) lkpi_kmem_cache_free(__VA_ARGS__) #define kmem_cache_destroy(...) linux_kmem_cache_destroy(__VA_ARGS__) +#define kmem_cache_shrink(x) (0) #define KMEM_CACHE(__struct, flags) \ linux_kmem_cache_create(#__struct, sizeof(struct __struct), \ @@ -86,8 +88,21 @@ struct linux_kmem_cache; #define ARCH_KMALLOC_MINALIGN \ __alignof(unsigned long long) -/* drm-kmod 5.4 compat */ -#define kfree_async(ptr) kfree(ptr); +#define ZERO_SIZE_PTR ((void *)16) +#define ZERO_OR_NULL_PTR(x) ((x) == NULL || (x) == ZERO_SIZE_PTR) + +struct linux_kmem_cache *linux_kmem_cache_create(const char *name, + size_t size, size_t align, unsigned flags, linux_kmem_ctor_t *ctor); +void *lkpi_kmem_cache_alloc(struct linux_kmem_cache *, gfp_t); +void *lkpi_kmem_cache_zalloc(struct linux_kmem_cache *, gfp_t); +void lkpi_kmem_cache_free(struct linux_kmem_cache *, void *); +void linux_kmem_cache_destroy(struct linux_kmem_cache *); + +void *lkpi_kmalloc(size_t, gfp_t); +void *lkpi___kmalloc(size_t, gfp_t); +void *lkpi___kmalloc_node(size_t, gfp_t, int); +void *lkpi_krealloc(void *, size_t, gfp_t); +void lkpi_kfree(const void *); static inline gfp_t linux_check_m_flags(gfp_t flags) @@ -104,35 +119,89 @@ linux_check_m_flags(gfp_t flags) return (flags & GFP_NATIVE_MASK); } +/* + * Base functions with a native implementation. + */ static inline void * kmalloc(size_t size, gfp_t flags) { - return (malloc(MAX(size, sizeof(struct llist_node)), M_KMALLOC, - linux_check_m_flags(flags))); + return (lkpi_kmalloc(size, flags)); +} + +static inline void * +__kmalloc(size_t size, gfp_t flags) +{ + return (lkpi___kmalloc(size, flags)); } static inline void * kmalloc_node(size_t size, gfp_t flags, int node) { - return (malloc_domainset(size, M_KMALLOC, - linux_get_vm_domain_set(node), linux_check_m_flags(flags))); + return (lkpi___kmalloc_node(size, flags, node)); +} + +static inline void * +krealloc(void *ptr, size_t size, gfp_t flags) +{ + return (lkpi_krealloc(ptr, size, flags)); +} + +static inline void +kfree(const void *ptr) +{ + lkpi_kfree(ptr); +} + +/* + * Other k*alloc() funtions using the above as underlying allocator. + */ +/* kmalloc */ +static inline void * +kmalloc_array(size_t n, size_t size, gfp_t flags) +{ + if (WOULD_OVERFLOW(n, size)) + panic("%s: %zu * %zu overflowed", __func__, n, size); + + return (kmalloc(size * n, flags)); } static inline void * kcalloc(size_t n, size_t size, gfp_t flags) { flags |= __GFP_ZERO; - return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); + return (kmalloc_array(n, size, flags)); +} + +/* kmalloc_node */ +static inline void * +kmalloc_array_node(size_t n, size_t size, gfp_t flags, int node) +{ + if (WOULD_OVERFLOW(n, size)) + panic("%s: %zu * %zu overflowed", __func__, n, size); + + return (kmalloc_node(size * n, flags, node)); } static inline void * kcalloc_node(size_t n, size_t size, gfp_t flags, int node) { flags |= __GFP_ZERO; - return (mallocarray_domainset(n, size, M_KMALLOC, - linux_get_vm_domain_set(node), linux_check_m_flags(flags))); + return (kmalloc_array_node(n, size, flags, node)); } +/* krealloc */ +static inline void * +krealloc_array(void *ptr, size_t n, size_t size, gfp_t flags) +{ + if (WOULD_OVERFLOW(n, size)) + return NULL; + + return (krealloc(ptr, n * size, flags)); +} + +/* + * vmalloc/kvalloc functions. + */ static inline void * __vmalloc(size_t size, gfp_t flags, int other) { @@ -152,45 +221,49 @@ vmalloc_32(size_t size) return (contigmalloc(size, M_KMALLOC, M_WAITOK, 0, UINT_MAX, 1, 1)); } +/* May return non-contiguous memory. */ static inline void * -kmalloc_array(size_t n, size_t size, gfp_t flags) -{ - return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); -} - -static inline void * -kmalloc_array_node(size_t n, size_t size, gfp_t flags, int node) +kvmalloc(size_t size, gfp_t flags) { - return (mallocarray_domainset(n, size, M_KMALLOC, - linux_get_vm_domain_set(node), linux_check_m_flags(flags))); + return (malloc(size, M_KMALLOC, linux_check_m_flags(flags))); } static inline void * kvmalloc_array(size_t n, size_t size, gfp_t flags) { - return (mallocarray(n, size, M_KMALLOC, linux_check_m_flags(flags))); + if (WOULD_OVERFLOW(n, size)) + panic("%s: %zu * %zu overflowed", __func__, n, size); + + return (kvmalloc(size * n, flags)); } static inline void * -krealloc(void *ptr, size_t size, gfp_t flags) +kvrealloc(const void *ptr, size_t oldsize, size_t newsize, gfp_t flags) { - return (realloc(ptr, size, M_KMALLOC, linux_check_m_flags(flags))); -} + void *newptr; -extern void linux_kfree_async(void *); + if (newsize <= oldsize) + return (__DECONST(void *, ptr)); -static inline void -kfree(const void *ptr) -{ - if (curthread->td_critnest != 0) - linux_kfree_async(__DECONST(void *, ptr)); - else - free(__DECONST(void *, ptr), M_KMALLOC); + newptr = kvmalloc(newsize, flags); + if (newptr != NULL) { + memcpy(newptr, ptr, oldsize); + kvfree(ptr); + } + + return (newptr); } +/* + * Misc. + */ + static __inline void kfree_sensitive(const void *ptr) { + if (ZERO_OR_NULL_PTR(ptr)) + return; + zfree(__DECONST(void *, ptr), M_KMALLOC); } @@ -200,11 +273,12 @@ ksize(const void *ptr) return (malloc_usable_size(ptr)); } -extern struct linux_kmem_cache *linux_kmem_cache_create(const char *name, - size_t size, size_t align, unsigned flags, linux_kmem_ctor_t *ctor); -extern void *lkpi_kmem_cache_alloc(struct linux_kmem_cache *, gfp_t); -extern void *lkpi_kmem_cache_zalloc(struct linux_kmem_cache *, gfp_t); -extern void lkpi_kmem_cache_free(struct linux_kmem_cache *, void *); -extern void linux_kmem_cache_destroy(struct linux_kmem_cache *); +static inline size_t +kmalloc_size_roundup(size_t size) +{ + if (unlikely(size == 0 || size == SIZE_MAX)) + return (size); + return (malloc_size(size)); +} #endif /* _LINUXKPI_LINUX_SLAB_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/smp.h b/sys/compat/linuxkpi/common/include/linux/smp.h index c6d011fceb5f..b057953e6282 100644 --- a/sys/compat/linuxkpi/common/include/linux/smp.h +++ b/sys/compat/linuxkpi/common/include/linux/smp.h @@ -22,13 +22,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SMP_H_ #define _LINUXKPI_LINUX_SMP_H_ +#include <asm/smp.h> + /* * Important note about the use of the function provided below: * diff --git a/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h b/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h new file mode 100644 index 000000000000..903053e7f6e8 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h @@ -0,0 +1,62 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H +#define _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H + +struct mtk_wed_device { +}; + +#define WED_WO_STA_REC 0x6 + +#define mtk_wed_device_start(_dev, _mask) do { } while(0) +#define mtk_wed_device_detach(_dev) do { } while(0) +#define mtk_wed_device_irq_get(_dev, _mask) 0 +#define mtk_wed_device_irq_set_mask(_dev, _mask) do { } while(0) +#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) (-ENODEV) +#define mtk_wed_device_dma_reset(_dev) do {} while (0) +#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _entry) \ + do {} while (0) +#define mtk_wed_device_stop(_dev) do { } while(0) +#define mtk_wed_device_start_hw_rro(_dev, _mask, _b) do { } while(0) +#define mtk_wed_device_setup_tc(_dev, _ndev, _type, _tdata) (-EOPNOTSUPP) + +static inline bool +mtk_wed_device_active(struct mtk_wed_device *dev __unused) +{ + + return (false); +} + +static inline bool +mtk_wed_get_rx_capa(struct mtk_wed_device *dev __unused) +{ + + return (false); +} + +#endif /* _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/soc/qcom/qmi.h b/sys/compat/linuxkpi/common/include/linux/soc/qcom/qmi.h new file mode 100644 index 000000000000..647eaf271d87 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/soc/qcom/qmi.h @@ -0,0 +1,173 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022-2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_SOC_QCOM_QMI_H +#define _LINUXKPI_LINUX_SOC_QCOM_QMI_H + +/* QMI (Qualcomm MSM Interface) */ + +#include <linux/qrtr.h> + +enum soc_qcom_qmi_data_type { + QMI_EOTI, + QMI_DATA_LEN, + QMI_OPT_FLAG, + QMI_UNSIGNED_1_BYTE, + QMI_UNSIGNED_2_BYTE, + QMI_UNSIGNED_4_BYTE, + QMI_UNSIGNED_8_BYTE, + QMI_SIGNED_4_BYTE_ENUM, + QMI_STRUCT, + QMI_STRING, +}; + +#define QMI_RESULT_SUCCESS_V01 __LINE__ +#define QMI_INDICATION __LINE__ + +struct qmi_handle; + +enum soc_qcom_qmi_array_type { + NO_ARRAY, + STATIC_ARRAY, + VAR_LEN_ARRAY, +}; + +/* Should this become an enum? */ +#define QMI_COMMON_TLV_TYPE 0 + +struct qmi_elem_info { + enum soc_qcom_qmi_data_type data_type; + uint32_t elem_len; + uint32_t elem_size; + enum soc_qcom_qmi_array_type array_type; + uint8_t tlv_type; + uint32_t offset; + const struct qmi_elem_info *ei_array; +}; + +struct qmi_response_type_v01 { + uint16_t result; + uint16_t error; +}; + +struct qmi_txn { +}; + +struct qmi_service { + uint32_t node; + uint32_t port; +}; + +struct qmi_msg_handler { + uint32_t type; + uint32_t msg_id; + const struct qmi_elem_info *ei; + size_t decoded_size; + void (*fn)(struct qmi_handle *, struct sockaddr_qrtr *, struct qmi_txn *, const void *); +}; + +struct qmi_ops { + int (*new_server)(struct qmi_handle *, struct qmi_service *); + void (*del_server)(struct qmi_handle *, struct qmi_service *); +}; + +struct qmi_handle { + int sock; + + const struct qmi_msg_handler *handler; + struct qmi_ops ops; +}; + + +/* XXX-TODO need implementation somewhere... it is not in ath1xk* */ +extern struct qmi_elem_info qmi_response_type_v01_ei[]; + +static inline int +qmi_handle_init(struct qmi_handle *handle, size_t resp_len_max, + const struct qmi_ops *ops, const struct qmi_msg_handler *handler) +{ + + handle->handler = handler; + if (ops != NULL) + handle->ops = *ops; + + /* We will find out what else to do here. */ + /* XXX TODO */ + + return (0); +} + +static __inline int +qmi_add_lookup(struct qmi_handle *handle, uint32_t service, uint32_t version, + uint32_t service_ins_id) +{ + + /* XXX TODO */ + return (0); +} + +static __inline void +qmi_handle_release(struct qmi_handle *handle) +{ + + /* XXX TODO */ +} + +static __inline int +qmi_send_request(struct qmi_handle *handle, void *x, struct qmi_txn *txn, + uint32_t msd_id, size_t len, const struct qmi_elem_info *ei, void *req) +{ + + /* XXX TODO */ + return (-ENXIO); +} + +static __inline void +qmi_txn_cancel(struct qmi_txn *txn) +{ + + /* XXX TODO */ +} + +static __inline int +qmi_txn_init(struct qmi_handle *handle, struct qmi_txn *txn, + const struct qmi_elem_info *ei, void *resp) +{ + + /* XXX TODO */ + return (-ENXIO); +} + +static __inline int +qmi_txn_wait(struct qmi_txn *txn, uint64_t jiffies) +{ + + /* XXX TODO */ + return (-ENXIO); +} + +#endif /* _LINUXKPI_LINUX_SOC_QCOM_QMI_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/socket.h b/sys/compat/linuxkpi/common/include/linux/socket.h index 3afb9bdfe3ba..638ee058c2f5 100644 --- a/sys/compat/linuxkpi/common/include/linux/socket.h +++ b/sys/compat/linuxkpi/common/include/linux/socket.h @@ -25,14 +25,23 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SOCKET_H_ #define _LINUXKPI_LINUX_SOCKET_H_ #include <sys/socket.h> +#define AF_QIPCRTR 42 + +static inline int +kernel_connect(int sd, struct sockaddr *sa, size_t salen, int flags) +{ + + /* kern_connectat()? It is used for sockaddr_qrtr by ath1xk/qmi. */ + pr_debug("%s: TODO\n", __func__); + return (-EINVAL); +} + #ifdef notyet static inline int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len) diff --git a/sys/compat/linuxkpi/common/include/linux/sort.h b/sys/compat/linuxkpi/common/include/linux/sort.h index 91ccd7ff83c4..e6196d1f41c7 100644 --- a/sys/compat/linuxkpi/common/include/linux/sort.h +++ b/sys/compat/linuxkpi/common/include/linux/sort.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> * diff --git a/sys/compat/linuxkpi/common/include/linux/spinlock.h b/sys/compat/linuxkpi/common/include/linux/spinlock.h index a87cb7180b28..dc10b0457153 100644 --- a/sys/compat/linuxkpi/common/include/linux/spinlock.h +++ b/sys/compat/linuxkpi/common/include/linux/spinlock.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SPINLOCK_H_ #define _LINUXKPI_LINUX_SPINLOCK_H_ @@ -43,9 +41,7 @@ #include <linux/bottom_half.h> #include <linux/lockdep.h> -typedef struct { - struct mtx m; -} spinlock_t; +typedef struct mtx spinlock_t; /* * By defining CONFIG_SPIN_SKIP LinuxKPI spinlocks and asserts will be @@ -61,7 +57,7 @@ typedef struct { #define spin_lock(_l) do { \ if (SPIN_SKIP()) \ break; \ - mtx_lock(&(_l)->m); \ + mtx_lock(_l); \ local_bh_disable(); \ } while (0) @@ -78,7 +74,7 @@ typedef struct { if (SPIN_SKIP()) \ break; \ local_bh_enable(); \ - mtx_unlock(&(_l)->m); \ + mtx_unlock(_l); \ } while (0) #define spin_unlock_bh(_l) do { \ @@ -95,7 +91,7 @@ typedef struct { if (SPIN_SKIP()) { \ __ret = 1; \ } else { \ - __ret = mtx_trylock(&(_l)->m); \ + __ret = mtx_trylock(_l); \ if (likely(__ret != 0)) \ local_bh_disable(); \ } \ @@ -113,7 +109,7 @@ typedef struct { #define spin_lock_nested(_l, _n) do { \ if (SPIN_SKIP()) \ break; \ - mtx_lock_flags(&(_l)->m, MTX_DUPOK); \ + mtx_lock_flags(_l, MTX_DUPOK); \ local_bh_disable(); \ } while (0) @@ -128,6 +124,7 @@ typedef struct { } while (0) #define spin_unlock_irqrestore(_l, flags) do { \ + (void)(flags); \ spin_unlock(_l); \ } while (0) @@ -142,31 +139,27 @@ typedef struct { #define _spin_lock_name(...) __spin_lock_name(__VA_ARGS__) #define spin_lock_name(name) _spin_lock_name(name, __FILE__, __LINE__) -#define spin_lock_init(lock) linux_spin_lock_init(lock, spin_lock_name("lnxspin")) - -static inline void -linux_spin_lock_init(spinlock_t *lock, const char *name) -{ +#define spin_lock_init(lock) mtx_init(lock, spin_lock_name("lnxspin"), \ + NULL, MTX_DEF | MTX_NOWITNESS | MTX_NEW) - memset(lock, 0, sizeof(*lock)); - mtx_init(&lock->m, name, NULL, MTX_DEF | MTX_NOWITNESS); -} - -static inline void -spin_lock_destroy(spinlock_t *lock) -{ - - mtx_destroy(&lock->m); -} +#define spin_lock_destroy(_l) mtx_destroy(_l) #define DEFINE_SPINLOCK(lock) \ spinlock_t lock; \ - MTX_SYSINIT(lock, &(lock).m, spin_lock_name("lnxspin"), MTX_DEF) + MTX_SYSINIT(lock, &lock, spin_lock_name("lnxspin"), MTX_DEF) #define assert_spin_locked(_l) do { \ if (SPIN_SKIP()) \ break; \ - mtx_assert(&(_l)->m, MA_OWNED); \ + mtx_assert(_l, MA_OWNED); \ +} while (0) + +#define local_irq_save(flags) do { \ + (flags) = 0; \ +} while (0) + +#define local_irq_restore(flags) do { \ + (void)(flags); \ } while (0) #define atomic_dec_and_lock_irqsave(cnt, lock, flags) \ diff --git a/sys/compat/linuxkpi/common/include/linux/srcu.h b/sys/compat/linuxkpi/common/include/linux/srcu.h index 0742d25d11ac..b42c28a1311b 100644 --- a/sys/compat/linuxkpi/common/include/linux/srcu.h +++ b/sys/compat/linuxkpi/common/include/linux/srcu.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SRCU_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/stackdepot.h b/sys/compat/linuxkpi/common/include/linux/stackdepot.h new file mode 100644 index 000000000000..df223d46be6e --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/stackdepot.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _LINUXKPI_LINUX_STACKDEPOT_H_ +#define _LINUXKPI_LINUX_STACKDEPOT_H_ + +typedef bool depot_stack_handle_t; + +#endif /* _LINUXKPI_LINUX_STACKDEPOT_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/stdarg.h b/sys/compat/linuxkpi/common/include/linux/stdarg.h new file mode 100644 index 000000000000..698ac45e9198 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/stdarg.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_STDARG_H_ +#define _LINUXKPI_STDARG_H_ + +#include <sys/stdarg.h> + +#endif /* _LINUXKPI_STDARG_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/stddef.h b/sys/compat/linuxkpi/common/include/linux/stddef.h new file mode 100644 index 000000000000..d04a5a4bf516 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/stddef.h @@ -0,0 +1,31 @@ +/* Public domain */ + +#ifndef _LINUXKPI_LINUX_STDDEF_H_ +#define _LINUXKPI_LINUX_STDDEF_H_ + +#include <sys/stddef.h> + +/* + * FreeBSD has multiple (vendor) drivers containing copies of this + * and including LinuxKPI headers. Put the #defines behind guards. + */ + +#ifndef __struct_group +#define __struct_group(_tag, _name, _attrs, _members...) \ + union { \ + struct { _members } _attrs; \ + struct _tag { _members } _attrs _name; \ + } _attrs +#endif + +#ifndef struct_group +#define struct_group(_name, _members...) \ + __struct_group(/* no tag */, _name, /* no attrs */, _members) +#endif + +#ifndef struct_group_tagged +#define struct_group_tagged(_tag, _name, _members...) \ + __struct_group(_tag, _name, /* no attrs */, _members) +#endif + +#endif /* _LINUXKPI_LINUX_STDDEF_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/string.h b/sys/compat/linuxkpi/common/include/linux/string.h index 73a38dc42c6c..f7b64560d254 100644 --- a/sys/compat/linuxkpi/common/include/linux/string.h +++ b/sys/compat/linuxkpi/common/include/linux/string.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_STRING_H_ #define _LINUXKPI_LINUX_STRING_H_ @@ -38,6 +36,9 @@ #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/err.h> +#include <linux/bitops.h> /* for BITS_PER_LONG */ +#include <linux/overflow.h> +#include <linux/stdarg.h> #include <sys/libkern.h> @@ -97,6 +98,27 @@ kmemdup(const void *src, size_t len, gfp_t gfp) return (dst); } +/* See slab.h for kvmalloc/kvfree(). */ +static inline void * +kvmemdup(const void *src, size_t len, gfp_t gfp) +{ + void *dst; + + dst = kvmalloc(len, gfp); + if (dst != NULL) + memcpy(dst, src, len); + return (dst); +} + +static inline char * +strndup_user(const char __user *ustr, long n) +{ + if (n < 1) + return (ERR_PTR(-EINVAL)); + + return (memdup_user_nul(ustr, n - 1)); +} + static inline char * kstrdup(const char *string, gfp_t gfp) { @@ -139,6 +161,24 @@ skip_spaces(const char *str) return (__DECONST(char *, str)); } +/* + * This function trims whitespaces at the end of a string and returns a pointer + * to the first non-whitespace character. + */ +static inline char * +strim(char *str) +{ + char *end; + + end = str + strlen(str); + while (end >= str && (*end == '\0' || isspace(*end))) { + *end = '\0'; + end--; + } + + return (skip_spaces(str)); +} + static inline void * memchr_inv(const void *start, int c, size_t length) { @@ -196,4 +236,94 @@ strscpy(char* dst, const char* src, size_t len) return (-E2BIG); } -#endif /* _LINUXKPI_LINUX_STRING_H_ */ +static inline ssize_t +strscpy_pad(char* dst, const char* src, size_t len) +{ + + bzero(dst, len); + + return (strscpy(dst, src, len)); +} + +static inline char * +strnchr(const char *cp, size_t n, int ch) +{ + char *p; + + for (p = __DECONST(char *, cp); n--; ++p) { + if (*p == ch) + return (p); + if (*p == '\0') + break; + } + + return (NULL); +} + +static inline void * +memset32(uint32_t *b, uint32_t c, size_t len) +{ + uint32_t *dst = b; + + while (len--) + *dst++ = c; + return (b); +} + +static inline void * +memset64(uint64_t *b, uint64_t c, size_t len) +{ + uint64_t *dst = b; + + while (len--) + *dst++ = c; + return (b); +} + +static inline void * +memset_p(void **p, void *v, size_t n) +{ + + if (BITS_PER_LONG == 32) + return (memset32((uint32_t *)p, (uintptr_t)v, n)); + else + return (memset64((uint64_t *)p, (uintptr_t)v, n)); +} + +static inline void +memcpy_and_pad(void *dst, size_t dstlen, const void *src, size_t len, int ch) +{ + + if (len >= dstlen) { + memcpy(dst, src, dstlen); + } else { + memcpy(dst, src, len); + /* Pad with given padding character. */ + memset((char *)dst + len, ch, dstlen - len); + } +} + +#define memset_startat(ptr, bytepat, smember) \ +({ \ + uint8_t *_ptr = (uint8_t *)(ptr); \ + int _c = (int)(bytepat); \ + size_t _o = offsetof(typeof(*(ptr)), smember); \ + memset(_ptr + _o, _c, sizeof(*(ptr)) - _o); \ +}) + +#define memset_after(ptr, bytepat, smember) \ +({ \ + uint8_t *_ptr = (uint8_t *)(ptr); \ + int _c = (int)(bytepat); \ + size_t _o = offsetofend(typeof(*(ptr)), smember); \ + memset(_ptr + _o, _c, sizeof(*(ptr)) - _o); \ +}) + +static inline void +memzero_explicit(void *p, size_t s) +{ + memset(p, 0, s); + __asm__ __volatile__("": :"r"(p) :"memory"); +} + +#endif /* _LINUXKPI_LINUX_STRING_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/string_helpers.h b/sys/compat/linuxkpi/common/include/linux/string_helpers.h new file mode 100644 index 000000000000..1bdff2730361 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/string_helpers.h @@ -0,0 +1,69 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_STRING_HELPERS_H_ +#define _LINUXKPI_LINUX_STRING_HELPERS_H_ + +#include <sys/types.h> + +static inline const char * +str_yes_no(bool value) +{ + if (value) + return "yes"; + else + return "no"; +} + +static inline const char * +str_on_off(bool value) +{ + if (value) + return "on"; + else + return "off"; +} + +static inline const char * +str_enabled_disabled(bool value) +{ + if (value) + return "enabled"; + else + return "disabled"; +} + +static inline const char * +str_enable_disable(bool value) +{ + if (value) + return "enable"; + else + return "disable"; +} + +#endif diff --git a/sys/compat/linuxkpi/common/include/linux/stringify.h b/sys/compat/linuxkpi/common/include/linux/stringify.h index bfdf99a30f2f..9345bdc441aa 100644 --- a/sys/compat/linuxkpi/common/include/linux/stringify.h +++ b/sys/compat/linuxkpi/common/include/linux/stringify.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_STRINGIFY_H_ diff --git a/sys/compat/linuxkpi/common/include/linux/suspend.h b/sys/compat/linuxkpi/common/include/linux/suspend.h new file mode 100644 index 000000000000..dacecbebdc08 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/suspend.h @@ -0,0 +1,23 @@ +/* Public domain. */ + +#ifndef _LINUXKPI_LINUX_SUSPEND_H_ +#define _LINUXKPI_LINUX_SUSPEND_H_ + +typedef int suspend_state_t; + +extern suspend_state_t pm_suspend_target_state; + +#define PM_SUSPEND_ON 0 +#define PM_SUSPEND_TO_IDLE 1 +#define PM_SUSPEND_STANDBY 2 +#define PM_SUSPEND_MEM 3 +#define PM_SUSPEND_MIN PM_SUSPEND_TO_IDLE +#define PM_SUSPEND_MAX 4 + +static inline int +pm_suspend_via_firmware(void) +{ + return 0; +} + +#endif /* _LINUXKPI_LINUX_SUSPEND_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/swap.h b/sys/compat/linuxkpi/common/include/linux/swap.h index a080895bed98..5828db7ae392 100644 --- a/sys/compat/linuxkpi/common/include/linux/swap.h +++ b/sys/compat/linuxkpi/common/include/linux/swap.h @@ -22,16 +22,24 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SWAP_H_ #define _LINUXKPI_LINUX_SWAP_H_ +#include <sys/param.h> +#include <sys/domainset.h> +#include <sys/queue.h> +#include <sys/proc.h> +#include <sys/pcpu.h> + +#include <vm/vm.h> #include <vm/swap_pager.h> #include <vm/vm_pageout.h> +#include <linux/pagemap.h> +#include <linux/page-flags.h> + static inline long get_nr_swap_pages(void) { @@ -49,4 +57,15 @@ current_is_kswapd(void) return (curproc == pageproc); } +static inline void +folio_mark_accessed(struct folio *folio) +{ + mark_page_accessed(&folio->page); +} + +static inline void +check_move_unevictable_folios(struct folio_batch *fbatch) +{ +} + #endif diff --git a/sys/compat/linuxkpi/common/include/linux/sysfs.h b/sys/compat/linuxkpi/common/include/linux/sysfs.h index 0b6b479d9362..65e023031bb2 100644 --- a/sys/compat/linuxkpi/common/include/linux/sysfs.h +++ b/sys/compat/linuxkpi/common/include/linux/sysfs.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_SYSFS_H_ #define _LINUXKPI_LINUX_SYSFS_H_ @@ -37,6 +35,7 @@ #include <linux/kobject.h> #include <linux/stringify.h> +#include <linux/mm.h> struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *, char *); @@ -51,11 +50,23 @@ struct attribute_group { struct attribute **attrs; }; +struct bin_attribute { + struct attribute attr; + size_t size; + ssize_t (*read)(struct linux_file *, struct kobject *, + struct bin_attribute *, char *, loff_t, size_t); + ssize_t (*write)(struct linux_file *, struct kobject *, + struct bin_attribute *, char *, loff_t, size_t); +}; + #define __ATTR(_name, _mode, _show, _store) { \ .attr = { .name = __stringify(_name), .mode = _mode }, \ .show = _show, .store = _store, \ } -#define __ATTR_RO(_name) __ATTR(_name, 0444, _name##_show, NULL) +#define __ATTR_RO(_name) { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = _name##_show, \ +} #define __ATTR_WO(_name) __ATTR(_name, 0200, NULL, _name##_store) #define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store) #define __ATTR_NULL { .attr = { .name = NULL } } @@ -70,6 +81,39 @@ struct attribute_group { NULL, \ } +#define __BIN_ATTR(_name, _mode, _read, _write, _size) { \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ + .read = _read, .write = _write, .size = _size, \ +} +#define __BIN_ATTR_RO(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .read = _name##_read, .size = _size, \ +} +#define __BIN_ATTR_WO(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = 0200 }, \ + .write = _name##_write, .size = _size, \ +} +#define __BIN_ATTR_WR(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = 0644 }, \ + .read = _name##_read, .write = _name##_write, .size = _size, \ +} + +#define BIN_ATTR(_name, _mode, _read, _write, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR(_name, _mode, _read, _write, _size); + +#define BIN_ATTR_RO(_name, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR_RO(_name, _size); + +#define BIN_ATTR_WO(_name, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR_WO(_name, _size); + +#define BIN_ATTR_WR(_name, _size) \ +struct bin_attribute bin_attr_##_name = \ + __BIN_ATTR_WR(_name, _size); + /* * Handle our generic '\0' terminated 'C' string. * Two cases: @@ -154,6 +198,95 @@ sysfs_remove_file(struct kobject *kobj, const struct attribute *attr) } static inline int +sysctl_handle_bin_attr(SYSCTL_HANDLER_ARGS) +{ + struct kobject *kobj; + struct bin_attribute *attr; + char *buf; + int error; + ssize_t len; + + kobj = arg1; + attr = (struct bin_attribute *)(intptr_t)arg2; + if (kobj->ktype == NULL || kobj->ktype->sysfs_ops == NULL) + return (ENODEV); + buf = (char *)get_zeroed_page(GFP_KERNEL); + if (buf == NULL) + return (ENOMEM); + + if (attr->read) { + len = attr->read( + NULL, /* <-- struct file, unimplemented */ + kobj, attr, buf, req->oldidx, PAGE_SIZE); + if (len < 0) { + error = -len; + if (error != EIO) + goto out; + } + } + + error = sysctl_handle_opaque(oidp, buf, PAGE_SIZE, req); + if (error != 0 || req->newptr == NULL || attr->write == NULL) + goto out; + + len = attr->write( + NULL, /* <-- struct file, unimplemented */ + kobj, attr, buf, req->newidx, req->newlen); + if (len < 0) + error = -len; +out: + free_page((unsigned long)buf); + + return (error); +} + +static inline int +sysfs_create_bin_file(struct kobject *kobj, const struct bin_attribute *attr) +{ + struct sysctl_oid *oid; + int ctlflags; + + ctlflags = CTLTYPE_OPAQUE | CTLFLAG_MPSAFE; + if (attr->attr.mode & (S_IRUSR | S_IWUSR)) + ctlflags |= CTLFLAG_RW; + else if (attr->attr.mode & S_IRUSR) + ctlflags |= CTLFLAG_RD; + else if (attr->attr.mode & S_IWUSR) + ctlflags |= CTLFLAG_WR; + + oid = SYSCTL_ADD_OID(NULL, SYSCTL_CHILDREN(kobj->oidp), OID_AUTO, + attr->attr.name, ctlflags, kobj, + (uintptr_t)attr, sysctl_handle_bin_attr, "", ""); + if (oid == NULL) + return (-ENOMEM); + + return (0); +} + +static inline void +sysfs_remove_bin_file(struct kobject *kobj, const struct bin_attribute *attr) +{ + + if (kobj->oidp) + sysctl_remove_name(kobj->oidp, attr->attr.name, 1, 1); +} + +static inline int +sysfs_create_link(struct kobject *kobj __unused, + struct kobject *target __unused, const char *name __unused) +{ + /* TODO */ + + return (0); +} + +static inline void +sysfs_remove_link(struct kobject *kobj, const char *name) +{ + /* TODO (along with sysfs_create_link) */ +} + +static inline int sysfs_create_files(struct kobject *kobj, const struct attribute * const *attrs) { int error = 0; @@ -246,7 +379,7 @@ sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp) struct attribute **attr; struct sysctl_oid *oidp; - SLIST_FOREACH(oidp, SYSCTL_CHILDREN(kobj->oidp), oid_link) { + SYSCTL_FOREACH(oidp, SYSCTL_CHILDREN(kobj->oidp)) { if (strcmp(oidp->oid_name, grp->name) != 0) continue; for (attr = grp->attrs; *attr != NULL; attr++) { @@ -295,6 +428,60 @@ sysfs_streq(const char *s1, const char *s2) return (l1 == l2 && strncmp(s1, s2, l1) == 0); } +static inline int +sysfs_emit(char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + if (!buf || offset_in_page(buf)) { + pr_warn("invalid sysfs_emit: buf:%p\n", buf); + return (0); + } + + va_start(args, fmt); + i = vscnprintf(buf, PAGE_SIZE, fmt, args); + va_end(args); + + return (i); +} + +static inline int +sysfs_emit_at(char *buf, int at, const char *fmt, ...) +{ + va_list args; + int i; + + if (!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE) { + pr_warn("invalid sysfs_emit: buf:%p at:%d\n", buf, at); + return (0); + } + + va_start(args, fmt); + i = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args); + va_end(args); + + return (i); +} + +static inline int +_sysfs_match_string(const char * const *a, size_t l, const char *s) +{ + const char *p; + int i; + + for (i = 0; i < l; i++) { + p = a[i]; + if (p == NULL) + break; + if (sysfs_streq(p, s)) + return (i); + } + + return (-ENOENT); +} +#define sysfs_match_string(a, s) _sysfs_match_string(a, ARRAY_SIZE(a), s) + #define sysfs_attr_init(attr) do {} while(0) #endif /* _LINUXKPI_LINUX_SYSFS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/tcp.h b/sys/compat/linuxkpi/common/include/linux/tcp.h index cfc64b8c7e53..3e461d8e7075 100644 --- a/sys/compat/linuxkpi/common/include/linux/tcp.h +++ b/sys/compat/linuxkpi/common/include/linux/tcp.h @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_TCP_H diff --git a/sys/compat/linuxkpi/common/include/linux/time.h b/sys/compat/linuxkpi/common/include/linux/time.h index c7a41a83f4aa..ca77a20516ff 100644 --- a/sys/compat/linuxkpi/common/include/linux/time.h +++ b/sys/compat/linuxkpi/common/include/linux/time.h @@ -22,12 +22,12 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_TIME_H_ #define _LINUXKPI_LINUX_TIME_H_ +#define MSEC_PER_SEC 1000L + #define NSEC_PER_USEC 1000L #define NSEC_PER_MSEC 1000000L #define NSEC_PER_SEC 1000000000L @@ -40,6 +40,10 @@ #include <sys/time.h> #include <sys/stdint.h> +#include <linux/math64.h> + +typedef int64_t time64_t; + static inline struct timeval ns_to_timeval(const int64_t nsec) { @@ -117,6 +121,8 @@ ns_to_timespec(const int64_t nsec) return (ts); } +#define ns_to_timespec64(_x) ns_to_timespec(_x) + static inline int timespec_valid(const struct timespec *ts) { diff --git a/sys/compat/linuxkpi/common/include/linux/timer.h b/sys/compat/linuxkpi/common/include/linux/timer.h index 3432bfc46c4f..a635f0faea59 100644 --- a/sys/compat/linuxkpi/common/include/linux/timer.h +++ b/sys/compat/linuxkpi/common/include/linux/timer.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_TIMER_H_ #define _LINUXKPI_LINUX_TIMER_H_ @@ -44,7 +42,7 @@ struct timer_list { void (*function_415) (struct timer_list *); }; unsigned long data; - int expires; + unsigned long expires; }; extern unsigned long linux_timer_hz_mask; @@ -78,15 +76,17 @@ extern unsigned long linux_timer_hz_mask; callout_init(&(timer)->callout, 1); \ } while (0) -extern int mod_timer(struct timer_list *, int); +extern int mod_timer(struct timer_list *, unsigned long); extern void add_timer(struct timer_list *); extern void add_timer_on(struct timer_list *, int cpu); extern int del_timer(struct timer_list *); extern int del_timer_sync(struct timer_list *); +extern int timer_delete_sync(struct timer_list *); +extern int timer_shutdown_sync(struct timer_list *); #define timer_pending(timer) callout_pending(&(timer)->callout) #define round_jiffies(j) \ - ((int)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask)) + ((unsigned long)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask)) #define round_jiffies_relative(j) round_jiffies(j) #define round_jiffies_up(j) round_jiffies(j) #define round_jiffies_up_relative(j) round_jiffies_up(j) diff --git a/sys/compat/linuxkpi/common/include/linux/tracepoint.h b/sys/compat/linuxkpi/common/include/linux/tracepoint.h index 0171427439f9..8ce7992306b9 100644 --- a/sys/compat/linuxkpi/common/include/linux/tracepoint.h +++ b/sys/compat/linuxkpi/common/include/linux/tracepoint.h @@ -23,8 +23,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_TRACEPOINT_H @@ -37,7 +35,13 @@ #define TP_printk(...) #define TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ -static void trace_ ## _name(_proto) \ +static inline void trace_ ## _name(_proto) \ +{ \ +} + +#define DECLARE_EVENT_CLASS(...) +#define DEFINE_EVENT(_x, _name, _proto, _args) \ +static inline void trace_ ## _name(_proto) \ { \ } diff --git a/sys/compat/linuxkpi/common/include/linux/types.h b/sys/compat/linuxkpi/common/include/linux/types.h index dab5e6ddce42..fcc455e5f731 100644 --- a/sys/compat/linuxkpi/common/include/linux/types.h +++ b/sys/compat/linuxkpi/common/include/linux/types.h @@ -25,13 +25,10 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_TYPES_H_ #define _LINUXKPI_LINUX_TYPES_H_ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> @@ -66,6 +63,7 @@ typedef unsigned gfp_t; typedef off_t loff_t; typedef vm_paddr_t resource_size_t; typedef uint16_t __bitwise__ __sum16; +typedef uint32_t __bitwise__ __wsum; typedef unsigned long pgoff_t; typedef unsigned __poll_t; @@ -79,6 +77,14 @@ typedef unsigned long kernel_ulong_t; typedef unsigned long irq_hw_number_t; +#ifndef LIST_HEAD_DEF +#define LIST_HEAD_DEF +struct list_head { + struct list_head *next; + struct list_head *prev; +}; +#endif + struct rcu_head { void *raw[2]; } __aligned(sizeof(void *)); diff --git a/sys/compat/linuxkpi/common/include/linux/uaccess.h b/sys/compat/linuxkpi/common/include/linux/uaccess.h index c62a94e8e044..660e84e6af3b 100644 --- a/sys/compat/linuxkpi/common/include/linux/uaccess.h +++ b/sys/compat/linuxkpi/common/include/linux/uaccess.h @@ -26,8 +26,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_UACCESS_H_ @@ -89,4 +87,29 @@ pagefault_disabled(void) return ((curthread->td_pflags & TDP_NOFAULTING) != 0); } +static inline int +__copy_to_user_inatomic(void __user *to, const void *from, unsigned n) +{ + + return (copyout_nofault(from, to, n) != 0 ? n : 0); +} +#define __copy_to_user_inatomic_nocache(to, from, n) \ + __copy_to_user_inatomic((to), (from), (n)) + +static inline unsigned long +__copy_from_user_inatomic(void *to, const void __user *from, + unsigned long n) +{ + /* + * XXXKIB. Equivalent Linux function is implemented using + * MOVNTI for aligned moves. For unaligned head and tail, + * normal move is performed. As such, it is not incorrect, if + * only somewhat slower, to use normal copyin. All uses + * except shmem_pwrite_fast() have the destination mapped WC. + */ + return ((copyin_nofault(__DECONST(void *, from), to, n) != 0 ? n : 0)); +} +#define __copy_from_user_inatomic_nocache(to, from, n) \ + __copy_from_user_inatomic((to), (from), (n)) + #endif /* _LINUXKPI_LINUX_UACCESS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/udp.h b/sys/compat/linuxkpi/common/include/linux/udp.h index 44c0763a1eeb..f3cd40cf8bb7 100644 --- a/sys/compat/linuxkpi/common/include/linux/udp.h +++ b/sys/compat/linuxkpi/common/include/linux/udp.h @@ -26,8 +26,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_UDP_H diff --git a/sys/compat/linuxkpi/common/include/linux/units.h b/sys/compat/linuxkpi/common/include/linux/units.h new file mode 100644 index 000000000000..304b5c27d87f --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/units.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025 Jean-Sébastien Pédron + * + * This software was developed by Jean-Sébastien Pédron under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_UNITS_H_ +#define _LINUXKPI_LINUX_UNITS_H_ + +#define NANOHZ_PER_HZ 1000000000UL +#define MICROHZ_PER_HZ 1000000UL +#define MILLIHZ_PER_HZ 1000UL +#define HZ_PER_KHZ 1000UL +#define KHZ_PER_MHZ 1000UL +#define HZ_PER_MHZ 1000000UL + +#endif /* _LINUXKPI_LINUX_UNITS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/usb.h b/sys/compat/linuxkpi/common/include/linux/usb.h index 3b7c8a2cde78..d9649dcb5471 100644 --- a/sys/compat/linuxkpi/common/include/linux/usb.h +++ b/sys/compat/linuxkpi/common/include/linux/usb.h @@ -1,4 +1,3 @@ -/* $FreeBSD$ */ /*- * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved. * Copyright (c) 2007 Hans Petter Selasky. All rights reserved. diff --git a/sys/compat/linuxkpi/common/include/linux/utsname.h b/sys/compat/linuxkpi/common/include/linux/utsname.h new file mode 100644 index 000000000000..3239801ca17b --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/utsname.h @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUXKPI_LINUX_UTSNAME_H +#define _LINUXKPI_LINUX_UTSNAME_H + +#include <sys/types.h> +#include <sys/jail.h> + +struct _utsname { + char release[OSRELEASELEN]; +}; + +struct uts_namespace { + struct _utsname name; +}; + +extern struct uts_namespace init_uts_ns; + +static inline struct _utsname * +init_utsname(void) +{ + + return &init_uts_ns.name; +} + +#endif /* _LINUXKPI_LINUX_UTSNAME_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/uuid.h b/sys/compat/linuxkpi/common/include/linux/uuid.h index 31a018497f78..4f6f4a8b34f0 100644 --- a/sys/compat/linuxkpi/common/include/linux/uuid.h +++ b/sys/compat/linuxkpi/common/include/linux/uuid.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2021 The FreeBSD Foundation + * Copyright (c) 2021,2023 The FreeBSD Foundation * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -26,13 +26,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_UUID_H #define _LINUXKPI_LINUX_UUID_H +#include <linux/random.h> + #define UUID_STRING_LEN 36 #define GUID_INIT(x0_3, x4_5, x6_7, x8, x9, x10, x11, x12, x13, x14, x15) \ @@ -59,4 +59,19 @@ typedef struct { char x[16]; } guid_t; +static inline void +guid_gen(guid_t *g) +{ + + get_random_bytes(g, 16); + g->x[7] = (g->x[7] & 0x0f) | 0x40; + g->x[8] = (g->x[8] & 0x3f) | 0x80; +} + +static inline void +guid_copy(guid_t *dst, const guid_t *src) +{ + memcpy(dst, src, sizeof(*dst)); +} + #endif /* _LINUXKPI_LINUX_UUID_H */ diff --git a/sys/compat/linuxkpi/common/include/linux/vgaarb.h b/sys/compat/linuxkpi/common/include/linux/vgaarb.h new file mode 100644 index 000000000000..d43a88136864 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/vgaarb.h @@ -0,0 +1,281 @@ +/* + * The VGA aribiter manages VGA space routing and VGA resource decode to + * allow multiple VGA devices to be used in a system in a safe way. + * + * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> + * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com> + * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _LINUXKPI_LINUX_VGA_H_ +#define _LINUXKPI_LINUX_VGA_H_ + +#include <video/vga.h> + +/* Legacy VGA regions */ +#define VGA_RSRC_NONE 0x00 +#define VGA_RSRC_LEGACY_IO 0x01 +#define VGA_RSRC_LEGACY_MEM 0x02 +#define VGA_RSRC_LEGACY_MASK (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM) +/* Non-legacy access */ +#define VGA_RSRC_NORMAL_IO 0x04 +#define VGA_RSRC_NORMAL_MEM 0x08 + +/* Passing that instead of a pci_dev to use the system "default" + * device, that is the one used by vgacon. Archs will probably + * have to provide their own vga_default_device(); + */ +#define VGA_DEFAULT_DEVICE (NULL) + +struct pci_dev; + +/* For use by clients */ + +/** + * vga_set_legacy_decoding + * + * @pdev: pci device of the VGA card + * @decodes: bit mask of what legacy regions the card decodes + * + * Indicates to the arbiter if the card decodes legacy VGA IOs, + * legacy VGA Memory, both, or none. All cards default to both, + * the card driver (fbdev for example) should tell the arbiter + * if it has disabled legacy decoding, so the card can be left + * out of the arbitration process (and can be safe to take + * interrupts at any time. + */ +#if defined(CONFIG_VGA_ARB) +extern void vga_set_legacy_decoding(struct pci_dev *pdev, + unsigned int decodes); +#else +static inline void vga_set_legacy_decoding(struct pci_dev *pdev, + unsigned int decodes) { }; +#endif + +/** + * vga_get - acquire & locks VGA resources + * + * @pdev: pci device of the VGA card or NULL for the system default + * @rsrc: bit mask of resources to acquire and lock + * @interruptible: blocking should be interruptible by signals ? + * + * This function acquires VGA resources for the given + * card and mark those resources locked. If the resource requested + * are "normal" (and not legacy) resources, the arbiter will first check + * whether the card is doing legacy decoding for that type of resource. If + * yes, the lock is "converted" into a legacy resource lock. + * The arbiter will first look for all VGA cards that might conflict + * and disable their IOs and/or Memory access, including VGA forwarding + * on P2P bridges if necessary, so that the requested resources can + * be used. Then, the card is marked as locking these resources and + * the IO and/or Memory accesse are enabled on the card (including + * VGA forwarding on parent P2P bridges if any). + * This function will block if some conflicting card is already locking + * one of the required resources (or any resource on a different bus + * segment, since P2P bridges don't differenciate VGA memory and IO + * afaik). You can indicate whether this blocking should be interruptible + * by a signal (for userland interface) or not. + * Must not be called at interrupt time or in atomic context. + * If the card already owns the resources, the function succeeds. + * Nested calls are supported (a per-resource counter is maintained) + */ + +#if defined(CONFIG_VGA_ARB) +extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible); +#else +static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) { return 0; } +#endif + +/** + * vga_get_interruptible + * + * Shortcut to vga_get + */ + +static inline int vga_get_interruptible(struct pci_dev *pdev, + unsigned int rsrc) +{ + return vga_get(pdev, rsrc, 1); +} + +/** + * vga_get_uninterruptible + * + * Shortcut to vga_get + */ + +static inline int vga_get_uninterruptible(struct pci_dev *pdev, + unsigned int rsrc) +{ + return vga_get(pdev, rsrc, 0); +} + +/** + * vga_tryget - try to acquire & lock legacy VGA resources + * + * @pdev: pci devivce of VGA card or NULL for system default + * @rsrc: bit mask of resources to acquire and lock + * + * This function performs the same operation as vga_get(), but + * will return an error (-EBUSY) instead of blocking if the resources + * are already locked by another card. It can be called in any context + */ + +#if defined(CONFIG_VGA_ARB) +extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc); +#else +static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; } +#endif + +/** + * vga_put - release lock on legacy VGA resources + * + * @pdev: pci device of VGA card or NULL for system default + * @rsrc: but mask of resource to release + * + * This function releases resources previously locked by vga_get() + * or vga_tryget(). The resources aren't disabled right away, so + * that a subsequence vga_get() on the same card will succeed + * immediately. Resources have a counter, so locks are only + * released if the counter reaches 0. + */ + +#if defined(CONFIG_VGA_ARB) +extern void vga_put(struct pci_dev *pdev, unsigned int rsrc); +#else +#define vga_put(pdev, rsrc) +#endif + + +/** + * vga_default_device + * + * This can be defined by the platform. The default implementation + * is rather dumb and will probably only work properly on single + * vga card setups and/or x86 platforms. + * + * If your VGA default device is not PCI, you'll have to return + * NULL here. In this case, I assume it will not conflict with + * any PCI card. If this is not true, I'll have to define two archs + * hooks for enabling/disabling the VGA default device if that is + * possible. This may be a problem with real _ISA_ VGA cards, in + * addition to a PCI one. I don't know at this point how to deal + * with that card. Can theirs IOs be disabled at all ? If not, then + * I suppose it's a matter of having the proper arch hook telling + * us about it, so we basically never allow anybody to succeed a + * vga_get()... + */ + +#ifdef CONFIG_VGA_ARB +extern struct pci_dev *vga_default_device(void); +extern void vga_set_default_device(struct pci_dev *pdev); +#else +static inline struct pci_dev *vga_default_device(void) { return NULL; }; +static inline void vga_set_default_device(struct pci_dev *pdev) { }; +#endif + +/** + * vga_conflicts + * + * Architectures should define this if they have several + * independent PCI domains that can afford concurrent VGA + * decoding + */ + +#ifndef __ARCH_HAS_VGA_CONFLICT +static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2) +{ + return 1; +} +#endif + +/** + * vga_client_register + * + * @pdev: pci device of the VGA client + * @cookie: client cookie to be used in callbacks + * @irq_set_state: irq state change callback + * @set_vga_decode: vga decode change callback + * + * return value: 0 on success, -1 on failure + * Register a client with the VGA arbitration logic + * + * Clients have two callback mechanisms they can use. + * irq enable/disable callback - + * If a client can't disable its GPUs VGA resources, then we + * need to be able to ask it to turn off its irqs when we + * turn off its mem and io decoding. + * set_vga_decode + * If a client can disable its GPU VGA resource, it will + * get a callback from this to set the encode/decode state + * + * Rationale: we cannot disable VGA decode resources unconditionally + * some single GPU laptops seem to require ACPI or BIOS access to the + * VGA registers to control things like backlights etc. + * Hopefully newer multi-GPU laptops do something saner, and desktops + * won't have any special ACPI for this. + * They driver will get a callback when VGA arbitration is first used + * by userspace since we some older X servers have issues. + */ +#if defined(CONFIG_VGA_ARB) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51501 +int vga_client_register(struct pci_dev *pdev, + unsigned int (*set_vga_decode)(struct pci_dev *pdev, bool state)); +#elif defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51500 +int vga_client_register(struct pci_dev *pdev, void *cookie, + unsigned int (*set_vga_decode)(void *cookie, bool state)); +#else +int vga_client_register(struct pci_dev *pdev, void *cookie, + void (*irq_set_state)(void *cookie, bool state), + unsigned int (*set_vga_decode)(void *cookie, bool state)); +#endif +#else +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51501 +static inline int vga_client_register(struct pci_dev *pdev, + unsigned int (*set_vga_decode)(struct pci_dev *pdev, bool state)) +#elif defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51500 +static inline int vga_client_register(struct pci_dev *pdev, void *cookie, + unsigned int (*set_vga_decode)(void *cookie, bool state)) +#else +static inline int vga_client_register(struct pci_dev *pdev, void *cookie, + void (*irq_set_state)(void *cookie, bool state), + unsigned int (*set_vga_decode)(void *cookie, bool state)) +#endif +{ + return 0; +} + +static inline int vga_client_unregister(struct pci_dev *pdev) +{ +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51501 + return (vga_client_register(NULL, NULL)); +#elif defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51500 + return (vga_client_register(NULL, NULL, NULL)); +#else + return (vga_client_register(NULL, NULL, NULL, NULL)); +#endif +} +#endif + +#endif /* _LINUXKPI_LINUX_VGA_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/vmalloc.h b/sys/compat/linuxkpi/common/include/linux/vmalloc.h index 450db0f761f2..00650a2df9b6 100644 --- a/sys/compat/linuxkpi/common/include/linux/vmalloc.h +++ b/sys/compat/linuxkpi/common/include/linux/vmalloc.h @@ -25,12 +25,11 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_VMALLOC_H_ #define _LINUXKPI_LINUX_VMALLOC_H_ +#include <linux/overflow.h> #include <linux/page.h> #define VM_MAP 0x0000 diff --git a/sys/compat/linuxkpi/common/include/linux/wait.h b/sys/compat/linuxkpi/common/include/linux/wait.h index 09cb5918b84b..03ddce2c06f5 100644 --- a/sys/compat/linuxkpi/common/include/linux/wait.h +++ b/sys/compat/linuxkpi/common/include/linux/wait.h @@ -26,8 +26,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_WAIT_H_ @@ -63,12 +61,14 @@ typedef struct wait_queue_head wait_queue_head_t; typedef int wait_queue_func_t(wait_queue_t *, unsigned int, int, void *); +#define WQ_FLAG_WOKEN 0x02 + /* * Many API consumers directly reference these fields and those of * wait_queue_head. */ struct wait_queue { - unsigned int flags; /* always 0 */ + unsigned int flags; void *private; wait_queue_func_t *func; union { @@ -89,8 +89,14 @@ struct wait_queue_head { * This function is referenced by at least one DRM driver, so it may not be * renamed and furthermore must be the default wait queue callback. */ -extern wait_queue_func_t autoremove_wake_function; -extern wait_queue_func_t default_wake_function; +wait_queue_func_t autoremove_wake_function; +wait_queue_func_t default_wake_function; +wait_queue_func_t woken_wake_function; + +long linux_wait_woken(wait_queue_t *wq, unsigned state, long timeout); + +#define wait_woken(wq, state, timeout) \ + linux_wait_woken((wq), (state), (timeout)) #define DEFINE_WAIT_FUNC(name, function) \ wait_queue_t name = { \ @@ -112,10 +118,10 @@ extern wait_queue_func_t default_wake_function; wait_queue_head_t name = { \ .task_list = LINUX_LIST_HEAD_INIT(name.task_list), \ }; \ - MTX_SYSINIT(name, &(name).lock.m, spin_lock_name("wqhead"), MTX_DEF) + MTX_SYSINIT(name, &(name).lock, spin_lock_name("wqhead"), MTX_DEF) #define init_waitqueue_head(wqh) do { \ - mtx_init(&(wqh)->lock.m, spin_lock_name("wqhead"), \ + mtx_init(&(wqh)->lock, spin_lock_name("wqhead"), \ NULL, MTX_DEF | MTX_NEW | MTX_NOWITNESS); \ INIT_LIST_HEAD(&(wqh)->task_list); \ } while (0) @@ -140,7 +146,7 @@ void linux_wake_up(wait_queue_head_t *, unsigned int, int, bool); #define wake_up_interruptible_all(wqh) \ linux_wake_up(wqh, TASK_INTERRUPTIBLE, 0, false) -int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, int, +int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, long, unsigned int, spinlock_t *); /* @@ -150,9 +156,9 @@ int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, int, */ #define __wait_event_common(wqh, cond, timeout, state, lock) ({ \ DEFINE_WAIT(__wq); \ - const int __timeout = ((int)(timeout)) < 1 ? 1 : (timeout); \ - int __start = ticks; \ - int __ret = 0; \ + const long __timeout = ((long)(timeout)) < 1 ? 1 : (timeout); \ + long __start = jiffies; \ + long __ret = 0; \ \ for (;;) { \ linux_prepare_to_wait(&(wqh), &__wq, state); \ @@ -168,7 +174,7 @@ int linux_wait_event_common(wait_queue_head_t *, wait_queue_t *, int, if (__ret == -EWOULDBLOCK) \ __ret = !!(cond); \ else if (__ret != -ERESTARTSYS) { \ - __ret = __timeout + __start - ticks; \ + __ret = __timeout + __start - jiffies; \ /* range check return value */ \ if (__ret < 1) \ __ret = 1; \ @@ -286,7 +292,7 @@ void linux_finish_wait(wait_queue_head_t *, wait_queue_t *); #define finish_wait(wqh, wq) linux_finish_wait(wqh, wq) void linux_wake_up_bit(void *, int); -int linux_wait_on_bit_timeout(unsigned long *, int, unsigned int, int); +int linux_wait_on_bit_timeout(unsigned long *, int, unsigned int, long); void linux_wake_up_atomic_t(atomic_t *); int linux_wait_on_atomic_t(atomic_t *, unsigned int); diff --git a/sys/compat/linuxkpi/common/include/linux/wait_bit.h b/sys/compat/linuxkpi/common/include/linux/wait_bit.h index 66c1149da432..573798590b73 100644 --- a/sys/compat/linuxkpi/common/include/linux/wait_bit.h +++ b/sys/compat/linuxkpi/common/include/linux/wait_bit.h @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef __LINUXKPI_LINUX_WAITBIT_H__ diff --git a/sys/compat/linuxkpi/common/include/linux/workqueue.h b/sys/compat/linuxkpi/common/include/linux/workqueue.h index 7ced4270e1db..66d3981d4229 100644 --- a/sys/compat/linuxkpi/common/include/linux/workqueue.h +++ b/sys/compat/linuxkpi/common/include/linux/workqueue.h @@ -25,8 +25,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_WORKQUEUE_H_ #define _LINUXKPI_LINUX_WORKQUEUE_H_ @@ -92,7 +90,7 @@ struct delayed_work { struct { struct callout callout; struct mtx mtx; - int expires; + unsigned long expires; } timer; }; @@ -190,6 +188,9 @@ do { \ #define delayed_work_pending(dwork) \ linux_work_pending(&(dwork)->work) +#define cancel_work(work) \ + linux_cancel_work(work) + #define cancel_delayed_work(dwork) \ linux_cancel_delayed_work(dwork) @@ -244,7 +245,8 @@ extern struct workqueue_struct *linux_create_workqueue_common(const char *, int) extern void linux_destroy_workqueue(struct workqueue_struct *); extern bool linux_queue_work_on(int cpu, struct workqueue_struct *, struct work_struct *); extern bool linux_queue_delayed_work_on(int cpu, struct workqueue_struct *, - struct delayed_work *, unsigned delay); + struct delayed_work *, unsigned long delay); +extern bool linux_cancel_work(struct work_struct *); extern bool linux_cancel_delayed_work(struct delayed_work *); extern bool linux_cancel_work_sync(struct work_struct *); extern bool linux_cancel_delayed_work_sync(struct delayed_work *); @@ -256,4 +258,10 @@ extern struct work_struct *linux_current_work(void); extern bool linux_queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork); extern bool linux_flush_rcu_work(struct rcu_work *rwork); +static inline bool +queue_work_node(int node __unused, struct workqueue_struct *wq, struct work_struct *work) +{ + return (queue_work(wq, work)); +} + #endif /* _LINUXKPI_LINUX_WORKQUEUE_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/ww_mutex.h b/sys/compat/linuxkpi/common/include/linux/ww_mutex.h index 82ba7a55a7e8..9219755bb78e 100644 --- a/sys/compat/linuxkpi/common/include/linux/ww_mutex.h +++ b/sys/compat/linuxkpi/common/include/linux/ww_mutex.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_WW_MUTEX_H_ #define _LINUXKPI_LINUX_WW_MUTEX_H_ @@ -61,6 +59,8 @@ struct ww_mutex { } \ SYSINIT(name, SI_SUB_LOCK, SI_ORDER_SECOND, name##_init, NULL) +#define DEFINE_WD_CLASS(name) DEFINE_WW_CLASS(name) + #define ww_mutex_is_locked(_m) \ sx_xlocked(&(_m)->base.sx) @@ -70,8 +70,13 @@ struct ww_mutex { #define ww_mutex_lock_slow_interruptible(_m, _x) \ ww_mutex_lock_interruptible(_m, _x) +#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 51600 +static inline int __must_check +ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx __unused) +#else static inline int __must_check ww_mutex_trylock(struct ww_mutex *lock) +#endif { return (mutex_trylock(&lock->base)); } diff --git a/sys/compat/linuxkpi/common/include/linux/xarray.h b/sys/compat/linuxkpi/common/include/linux/xarray.h index 408906867479..fba36eea0ab5 100644 --- a/sys/compat/linuxkpi/common/include/linux/xarray.h +++ b/sys/compat/linuxkpi/common/include/linux/xarray.h @@ -22,8 +22,6 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _LINUXKPI_LINUX_XARRAY_H_ #define _LINUXKPI_LINUX_XARRAY_H_ @@ -31,6 +29,7 @@ #include <linux/gfp.h> #include <linux/radix-tree.h> #include <linux/err.h> +#include <linux/kconfig.h> #include <sys/lock.h> #include <sys/mutex.h> @@ -45,16 +44,19 @@ #define XA_ERROR(x) \ ERR_PTR(x) +#define xa_is_err(x) \ + IS_ERR(x) + #define xa_limit_32b XA_LIMIT(0, 0xFFFFFFFF) -#define XA_ASSERT_LOCKED(xa) mtx_assert(&(xa)->mtx, MA_OWNED) -#define xa_lock(xa) mtx_lock(&(xa)->mtx) -#define xa_unlock(xa) mtx_unlock(&(xa)->mtx) +#define XA_ASSERT_LOCKED(xa) mtx_assert(&(xa)->xa_lock, MA_OWNED) +#define xa_lock(xa) mtx_lock(&(xa)->xa_lock) +#define xa_unlock(xa) mtx_unlock(&(xa)->xa_lock) struct xarray { - struct radix_tree_root root; - struct mtx mtx; /* internal mutex */ - uint32_t flags; /* see XA_FLAGS_XXX */ + struct radix_tree_root xa_head; + struct mtx xa_lock; /* internal mutex */ + uint32_t xa_flags; /* see XA_FLAGS_XXX */ }; /* @@ -65,6 +67,7 @@ void *xa_erase(struct xarray *, uint32_t); void *xa_load(struct xarray *, uint32_t); int xa_alloc(struct xarray *, uint32_t *, void *, uint32_t, gfp_t); int xa_alloc_cyclic(struct xarray *, uint32_t *, void *, uint32_t, uint32_t *, gfp_t); +int xa_alloc_cyclic_irq(struct xarray *, uint32_t *, void *, uint32_t, uint32_t *, gfp_t); int xa_insert(struct xarray *, uint32_t, void *, gfp_t); void *xa_store(struct xarray *, uint32_t, void *, gfp_t); void xa_init_flags(struct xarray *, uint32_t); @@ -87,6 +90,27 @@ void *__xa_store(struct xarray *, uint32_t, void *, gfp_t); bool __xa_empty(struct xarray *); void *__xa_next(struct xarray *, unsigned long *, bool); +#define xa_store_irq(xa, index, ptr, gfp) \ + xa_store((xa), (index), (ptr), (gfp)) + +#define xa_erase_irq(xa, index) \ + xa_erase((xa), (index)) + +#define xa_lock_irq(xa) xa_lock(xa) +#define xa_unlock_irq(xa) xa_unlock(xa) + +#define xa_lock_irqsave(xa, flags) \ + do { \ + xa_lock((xa)); \ + flags = 0; \ + } while (0) + +#define xa_unlock_irqrestore(xa, flags) \ + do { \ + xa_unlock((xa)); \ + flags == 0; \ + } while (0) + static inline int xa_err(void *ptr) { |