aboutsummaryrefslogtreecommitdiff
path: root/sys/compat/linuxkpi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linuxkpi')
-rw-r--r--sys/compat/linuxkpi/common/include/acpi/acpi.h2
-rw-r--r--sys/compat/linuxkpi/common/include/kunit/static_stub.h15
-rw-r--r--sys/compat/linuxkpi/common/include/linux/bitops.h9
-rw-r--r--sys/compat/linuxkpi/common/include/linux/cleanup.h49
-rw-r--r--sys/compat/linuxkpi/common/include/linux/compiler.h14
-rw-r--r--sys/compat/linuxkpi/common/include/linux/device.h6
-rw-r--r--sys/compat/linuxkpi/common/include/linux/etherdevice.h23
-rw-r--r--sys/compat/linuxkpi/common/include/linux/fips.h12
-rw-r--r--sys/compat/linuxkpi/common/include/linux/ieee80211.h2
-rw-r--r--sys/compat/linuxkpi/common/include/linux/math.h2
-rw-r--r--sys/compat/linuxkpi/common/include/linux/math64.h6
-rw-r--r--sys/compat/linuxkpi/common/include/linux/netdevice.h15
-rw-r--r--sys/compat/linuxkpi/common/include/linux/nl80211.h10
-rw-r--r--sys/compat/linuxkpi/common/include/linux/overflow.h180
-rw-r--r--sys/compat/linuxkpi/common/include/linux/pci.h36
-rw-r--r--sys/compat/linuxkpi/common/include/linux/platform_device.h2
-rw-r--r--sys/compat/linuxkpi/common/include/linux/pm.h14
-rw-r--r--sys/compat/linuxkpi/common/include/linux/rcupdate.h5
-rw-r--r--sys/compat/linuxkpi/common/include/linux/skbuff.h3
-rw-r--r--sys/compat/linuxkpi/common/include/linux/slab.h4
-rw-r--r--sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h47
-rw-r--r--sys/compat/linuxkpi/common/include/linux/string_choices.h71
-rw-r--r--sys/compat/linuxkpi/common/include/linux/string_helpers.h67
-rw-r--r--sys/compat/linuxkpi/common/include/linux/timer.h21
-rw-r--r--sys/compat/linuxkpi/common/include/net/cfg80211.h322
-rw-r--r--sys/compat/linuxkpi/common/include/net/mac80211.h53
-rw-r--r--sys/compat/linuxkpi/common/include/net/netmem.h21
-rw-r--r--sys/compat/linuxkpi/common/include/net/page_pool.h119
-rw-r--r--sys/compat/linuxkpi/common/include/net/page_pool/helpers.h79
-rw-r--r--sys/compat/linuxkpi/common/include/net/page_pool/types.h36
-rw-r--r--sys/compat/linuxkpi/common/src/linux_80211.c85
-rw-r--r--sys/compat/linuxkpi/common/src/linux_80211_macops.c14
-rw-r--r--sys/compat/linuxkpi/common/src/linux_acpi.c33
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c13
-rw-r--r--sys/compat/linuxkpi/common/src/linux_devres.c26
-rw-r--r--sys/compat/linuxkpi/common/src/linux_page.c4
-rw-r--r--sys/compat/linuxkpi/common/src/linux_pci.c190
-rw-r--r--sys/compat/linuxkpi/dummy/include/kunit/skbuff.h0
-rw-r--r--sys/compat/linuxkpi/dummy/include/kunit/test-bug.h0
-rw-r--r--sys/compat/linuxkpi/dummy/include/kunit/test.h0
40 files changed, 1139 insertions, 471 deletions
diff --git a/sys/compat/linuxkpi/common/include/acpi/acpi.h b/sys/compat/linuxkpi/common/include/acpi/acpi.h
index 016c7ede0f6e..9bb435591daa 100644
--- a/sys/compat/linuxkpi/common/include/acpi/acpi.h
+++ b/sys/compat/linuxkpi/common/include/acpi/acpi.h
@@ -131,7 +131,7 @@ acpi_format_exception(ACPI_STATUS Exception)
}
static inline ACPI_STATUS
-acpi_get_handle(ACPI_HANDLE Parent, ACPI_STRING Pathname,
+acpi_get_handle(ACPI_HANDLE Parent, const char *Pathname,
ACPI_HANDLE *RetHandle)
{
return (AcpiGetHandle(Parent, Pathname, RetHandle));
diff --git a/sys/compat/linuxkpi/common/include/kunit/static_stub.h b/sys/compat/linuxkpi/common/include/kunit/static_stub.h
new file mode 100644
index 000000000000..9d425d46dbb0
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/kunit/static_stub.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * This software was developed by Björn Zeeb under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _LINUXKPI_KUNIT_STATIC_STUB_H
+#define _LINUXKPI_KUNIT_STATIC_STUB_H
+
+#define KUNIT_STATIC_STUB_REDIRECT(_fn, ...) do { } while(0)
+
+#endif /* _LINUXKPI_KUNIT_STATIC_STUB_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/bitops.h b/sys/compat/linuxkpi/common/include/linux/bitops.h
index 00dd1f9a1ec0..a5a7abd55287 100644
--- a/sys/compat/linuxkpi/common/include/linux/bitops.h
+++ b/sys/compat/linuxkpi/common/include/linux/bitops.h
@@ -37,13 +37,8 @@
#define BIT(nr) (1UL << (nr))
#define BIT_ULL(nr) (1ULL << (nr))
-#ifdef __LP64__
-#define BITS_PER_LONG 64
-#else
-#define BITS_PER_LONG 32
-#endif
-
-#define BITS_PER_LONG_LONG 64
+#define BITS_PER_LONG (__SIZEOF_LONG__ * __CHAR_BIT__)
+#define BITS_PER_LONG_LONG (__SIZEOF_LONG_LONG__ * __CHAR_BIT__)
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
#define BITMAP_LAST_WORD_MASK(n) (~0UL >> (BITS_PER_LONG - (n)))
diff --git a/sys/compat/linuxkpi/common/include/linux/cleanup.h b/sys/compat/linuxkpi/common/include/linux/cleanup.h
index 01f234f0cbe7..5bb146f082ed 100644
--- a/sys/compat/linuxkpi/common/include/linux/cleanup.h
+++ b/sys/compat/linuxkpi/common/include/linux/cleanup.h
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2024 The FreeBSD Foundation
+ * Copyright (c) 2024-2025 The FreeBSD Foundation
*
* This software was developed by Björn Zeeb under sponsorship from
* the FreeBSD Foundation.
@@ -43,4 +43,51 @@
guard_ ## _n ## _t guard_ ## _n ## _ ## __COUNTER__ \
__cleanup(guard_ ## _n ## _destroy) = guard_ ## _n ## _create
+#define DEFINE_FREE(_n, _t, _f) \
+ static inline void \
+ __free_ ## _n(void *p) \
+ { \
+ _t _T; \
+ \
+ _T = *(_t *)p; \
+ _f; \
+ }
+
+#define __free(_n) __cleanup(__free_##_n)
+
+/*
+ * Given this is a _0 version it should likely be broken up into parts.
+ * But we have no idead what a _1, _2, ... version would do different
+ * until we see a call.
+ * This is used for a not-real-type (rcu). We use a bool to "simulate"
+ * the lock held. Also _T still special, may not always be used, so tag
+ * with __unused (or better the LinuxKPI __maybe_unused).
+ */
+#define DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...) \
+ \
+ typedef struct { \
+ bool lock; \
+ __VA_ARGS__; \
+ } guard_ ## _n ## _t; \
+ \
+ static inline void \
+ guard_ ## _n ## _destroy(guard_ ## _n ## _t *_T) \
+ { \
+ if (_T->lock) { \
+ _unlock; \
+ } \
+ } \
+ \
+ static inline guard_ ## _n ## _t \
+ guard_ ## _n ## _create(void) \
+ { \
+ guard_ ## _n ## _t _tmp; \
+ guard_ ## _n ## _t *_T __maybe_unused; \
+ \
+ _tmp.lock = true; \
+ _T = &_tmp; \
+ _lock; \
+ return (_tmp); \
+ }
+
#endif /* _LINUXKPI_LINUX_CLEANUP_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/compiler.h b/sys/compat/linuxkpi/common/include/linux/compiler.h
index fb5ad3bf4fe4..4146c829b936 100644
--- a/sys/compat/linuxkpi/common/include/linux/compiler.h
+++ b/sys/compat/linuxkpi/common/include/linux/compiler.h
@@ -31,6 +31,7 @@
#define _LINUXKPI_LINUX_COMPILER_H_
#include <sys/cdefs.h>
+#include <sys/endian.h>
#define __user
#define __kernel
@@ -79,6 +80,13 @@
#else
#define __counted_by(_x)
#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define __counted_by_le(_x) __counted_by(_x)
+#define __counted_by_be(_x)
+#else
+#define __counted_by_le(_x)
+#define __counted_by_be(_x) __counted_by(_x)
+#endif
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
@@ -130,4 +138,10 @@
#define is_signed_type(t) ((t)-1 < (t)1)
#define is_unsigned_type(t) ((t)-1 > (t)1)
+#if __has_builtin(__builtin_dynamic_object_size)
+#define __struct_size(_s) __builtin_dynamic_object_size(_s, 0)
+#else
+#define __struct_size(_s) __builtin_object_size(_s, 0)
+#endif
+
#endif /* _LINUXKPI_LINUX_COMPILER_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h
index 2556b0c45e49..c291133e2e0b 100644
--- a/sys/compat/linuxkpi/common/include/linux/device.h
+++ b/sys/compat/linuxkpi/common/include/linux/device.h
@@ -4,7 +4,7 @@
* Copyright (c) 2010 Panasas, Inc.
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
* All rights reserved.
- * Copyright (c) 2021-2022 The FreeBSD Foundation
+ * Copyright (c) 2021-2025 The FreeBSD Foundation
*
* Portions of this software were developed by Björn Zeeb
* under sponsorship from the FreeBSD Foundation.
@@ -92,6 +92,7 @@ struct device_driver {
const struct dev_pm_ops *pm;
void (*shutdown) (struct device *);
+ void (*coredump) (struct device *);
};
struct device_type {
@@ -284,7 +285,8 @@ 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)
+void lkpi_devm_kfree(struct device *, const void *);
+#define devm_kfree(_d, _p) lkpi_devm_kfree(_d, _p)
static inline const char *
dev_driver_string(const struct device *dev)
diff --git a/sys/compat/linuxkpi/common/include/linux/etherdevice.h b/sys/compat/linuxkpi/common/include/linux/etherdevice.h
index 1f2d6cf22d7e..b9a4951de8ac 100644
--- a/sys/compat/linuxkpi/common/include/linux/etherdevice.h
+++ b/sys/compat/linuxkpi/common/include/linux/etherdevice.h
@@ -27,6 +27,8 @@
#include <linux/types.h>
#include <linux/device.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
#include <sys/random.h>
#include <sys/libkern.h>
@@ -137,4 +139,25 @@ device_get_mac_address(struct device *dev, char *dst)
return (-ENOENT);
}
+/* Returns network byte order. */
+static inline uint16_t
+eth_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+ pr_debug("%s: TODO\n", __func__);
+ return (htons(ETHERTYPE_8023));
+}
+
+static inline void
+eth_hw_addr_set(struct net_device *dev, const u8 *addr)
+{
+ pr_debug("%s: TODO (if we want to)\n", __func__);
+}
+
+static inline int
+eth_platform_get_mac_address(struct device *dev __unused, u8 *addr __unused)
+{
+ pr_debug("%s: TODO\n", __func__);
+ return (-ENODEV);
+}
+
#endif /* _LINUXKPI_LINUX_ETHERDEVICE_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/fips.h b/sys/compat/linuxkpi/common/include/linux/fips.h
new file mode 100644
index 000000000000..25c0c1fc1fa0
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/fips.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _LINUXKPI_LINUX_FIPS_H
+#define _LINUXKPI_LINUX_FIPS_H
+
+#define fips_enabled 0
+
+#endif /* _LINUXKPI_LINUX_FIPS_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h
index 17041bb03ce8..ea8c0fc8ef5e 100644
--- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h
+++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h
@@ -312,6 +312,7 @@ enum ieee80211_ac_numbers {
#define IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS 0xf
#define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP 0x0060
#define IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP_SAME 1
+#define IEEE80211_MLD_CAP_OP_LINK_RECONF_SUPPORT 0x2000
struct ieee80211_mcs_info {
uint8_t rx_mask[IEEE80211_HT_MCS_MASK_LEN];
@@ -365,6 +366,7 @@ enum ieee80211_chanctx_change_flags {
IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(4),
IEEE80211_CHANCTX_CHANGE_PUNCTURING = BIT(5),
IEEE80211_CHANCTX_CHANGE_MIN_DEF = BIT(6),
+ IEEE80211_CHANCTX_CHANGE_AP = BIT(7),
};
enum ieee80211_frame_release_type {
diff --git a/sys/compat/linuxkpi/common/include/linux/math.h b/sys/compat/linuxkpi/common/include/linux/math.h
index 5a348a57747b..1d50e011f66d 100644
--- a/sys/compat/linuxkpi/common/include/linux/math.h
+++ b/sys/compat/linuxkpi/common/include/linux/math.h
@@ -56,7 +56,7 @@
__ret; \
})
-#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60600
+#if !defined(LINUXKPI_VERSION) || (LINUXKPI_VERSION >= 60600)
#define abs_diff(x, y) ({ \
__typeof(x) _x = (x); \
__typeof(y) _y = (y); \
diff --git a/sys/compat/linuxkpi/common/include/linux/math64.h b/sys/compat/linuxkpi/common/include/linux/math64.h
index a216d350570f..25ca9da1b622 100644
--- a/sys/compat/linuxkpi/common/include/linux/math64.h
+++ b/sys/compat/linuxkpi/common/include/linux/math64.h
@@ -98,6 +98,12 @@ div64_u64_round_up(uint64_t dividend, uint64_t divisor)
return ((dividend + divisor - 1) / divisor);
}
+static inline uint64_t
+roundup_u64(uint64_t x1, uint32_t x2)
+{
+ return (div_u64(x1 + x2 - 1, x2) * x2);
+}
+
#define DIV64_U64_ROUND_UP(...) \
div64_u64_round_up(__VA_ARGS__)
diff --git a/sys/compat/linuxkpi/common/include/linux/netdevice.h b/sys/compat/linuxkpi/common/include/linux/netdevice.h
index 3b808a4a1749..cf27753bcb80 100644
--- a/sys/compat/linuxkpi/common/include/linux/netdevice.h
+++ b/sys/compat/linuxkpi/common/include/linux/netdevice.h
@@ -486,6 +486,21 @@ netdev_priv(const struct net_device *ndev)
}
/* -------------------------------------------------------------------------- */
+
+static __inline void
+netif_device_attach(struct net_device *ndev)
+{
+ pr_debug("%s: TODO\n", __func__);
+}
+
+static __inline void
+netif_device_detach(struct net_device *ndev)
+{
+ pr_debug("%s: TODO\n", __func__);
+}
+
+
+/* -------------------------------------------------------------------------- */
/* This is really rtnetlink and probably belongs elsewhere. */
#define rtnl_lock() do { } while(0)
diff --git a/sys/compat/linuxkpi/common/include/linux/nl80211.h b/sys/compat/linuxkpi/common/include/linux/nl80211.h
index f3979d3a2abc..845ffec4bcba 100644
--- a/sys/compat/linuxkpi/common/include/linux/nl80211.h
+++ b/sys/compat/linuxkpi/common/include/linux/nl80211.h
@@ -50,6 +50,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = BIT(15),
NL80211_FEATURE_AP_SCAN = BIT(16),
NL80211_FEATURE_ACTIVE_MONITOR = BIT(17),
+ NL80211_FEATURE_SAE = BIT(18),
};
enum nl80211_pmsr_ftm_failure_flags {
@@ -85,6 +86,7 @@ enum nl80211_reg_rule_flags {
NL80211_RRF_NO_6GHZ_AFC_CLIENT = BIT(15),
NL80211_RRF_PSD = BIT(16),
NL80211_RRF_ALLOW_6GHZ_VLP_AP = BIT(17),
+ NL80211_RRF_ALLOW_20MHZ_ACTIVITY = BIT(18),
};
#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS|NL80211_RRF_NO_HT40PLUS)
@@ -434,6 +436,14 @@ enum nl80211_hidden_ssid {
NL80211_HIDDEN_SSID_NOT_IN_USE,
};
+enum nl80211_external_auth_action {
+ NL80211_EXTERNAL_AUTH_START,
+};
+
+enum nl80211_rxmgmt_flags {
+ NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = BIT(1),
+};
+
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
diff --git a/sys/compat/linuxkpi/common/include/linux/overflow.h b/sys/compat/linuxkpi/common/include/linux/overflow.h
index 9ba9b9500f11..e811037b8ecc 100644
--- a/sys/compat/linuxkpi/common/include/linux/overflow.h
+++ b/sys/compat/linuxkpi/common/include/linux/overflow.h
@@ -33,8 +33,10 @@
* 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))
+#define __type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
+#define type_max(t) __type_max(typeof(t))
+#define __type_min(T) ((T)((T)-type_max(T)-(T)1))
+#define type_min(t) __type_min(typeof(t))
/*
* Avoids triggering -Wtype-limits compilation warning,
@@ -59,46 +61,123 @@ static inline bool __must_check __must_check_overflow(bool overflow)
* @b: second addend
* @d: pointer to store sum
*
- * Returns 0 on success.
+ * Returns true on wrap-around, false otherwise.
*
- * *@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.
+ * *@d holds the results of the attempted addition, regardless of whether
+ * wrap-around occurred.
*/
#define check_add_overflow(a, b, d) \
__must_check_overflow(__builtin_add_overflow(a, b, d))
/**
+ * wrapping_add() - Intentionally perform a wrapping addition
+ * @type: type for result of calculation
+ * @a: first addend
+ * @b: second addend
+ *
+ * Return the potentially wrapped-around addition without
+ * tripping any wrap-around sanitizers that may be enabled.
+ */
+#define wrapping_add(type, a, b) \
+ ({ \
+ type __val; \
+ __builtin_add_overflow(a, b, &__val); \
+ __val; \
+ })
+
+/**
+ * wrapping_assign_add() - Intentionally perform a wrapping increment assignment
+ * @var: variable to be incremented
+ * @offset: amount to add
+ *
+ * Increments @var by @offset with wrap-around. Returns the resulting
+ * value of @var. Will not trip any wrap-around sanitizers.
+ *
+ * Returns the new value of @var.
+ */
+#define wrapping_assign_add(var, offset) \
+ ({ \
+ typeof(var) *__ptr = &(var); \
+ *__ptr = wrapping_add(typeof(var), *__ptr, offset); \
+ })
+
+/**
* check_sub_overflow() - Calculate subtraction with overflow checking
* @a: minuend; value to subtract from
* @b: subtrahend; value to subtract from @a
* @d: pointer to store difference
*
- * Returns 0 on success.
+ * Returns true on wrap-around, false otherwise.
*
- * *@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.
+ * *@d holds the results of the attempted subtraction, regardless of whether
+ * wrap-around occurred.
*/
#define check_sub_overflow(a, b, d) \
__must_check_overflow(__builtin_sub_overflow(a, b, d))
/**
+ * wrapping_sub() - Intentionally perform a wrapping subtraction
+ * @type: type for result of calculation
+ * @a: minuend; value to subtract from
+ * @b: subtrahend; value to subtract from @a
+ *
+ * Return the potentially wrapped-around subtraction without
+ * tripping any wrap-around sanitizers that may be enabled.
+ */
+#define wrapping_sub(type, a, b) \
+ ({ \
+ type __val; \
+ __builtin_sub_overflow(a, b, &__val); \
+ __val; \
+ })
+
+/**
+ * wrapping_assign_sub() - Intentionally perform a wrapping decrement assign
+ * @var: variable to be decremented
+ * @offset: amount to subtract
+ *
+ * Decrements @var by @offset with wrap-around. Returns the resulting
+ * value of @var. Will not trip any wrap-around sanitizers.
+ *
+ * Returns the new value of @var.
+ */
+#define wrapping_assign_sub(var, offset) \
+ ({ \
+ typeof(var) *__ptr = &(var); \
+ *__ptr = wrapping_sub(typeof(var), *__ptr, offset); \
+ })
+
+/**
* check_mul_overflow() - Calculate multiplication with overflow checking
* @a: first factor
* @b: second factor
* @d: pointer to store product
*
- * Returns 0 on success.
+ * Returns true on wrap-around, false otherwise.
*
- * *@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.
+ * *@d holds the results of the attempted multiplication, regardless of whether
+ * wrap-around occurred.
*/
#define check_mul_overflow(a, b, d) \
__must_check_overflow(__builtin_mul_overflow(a, b, d))
/**
+ * wrapping_mul() - Intentionally perform a wrapping multiplication
+ * @type: type for result of calculation
+ * @a: first factor
+ * @b: second factor
+ *
+ * Return the potentially wrapped-around multiplication without
+ * tripping any wrap-around sanitizers that may be enabled.
+ */
+#define wrapping_mul(type, a, b) \
+ ({ \
+ type __val; \
+ __builtin_mul_overflow(a, b, &__val); \
+ __val; \
+ })
+
+/**
* check_shl_overflow() - Calculate a left-shifted value and check overflow
* @a: Value to be shifted
* @s: How many bits left to shift
@@ -122,7 +201,7 @@ static inline bool __must_check __must_check_overflow(bool overflow)
typeof(a) _a = a; \
typeof(s) _s = s; \
typeof(d) _d = d; \
- u64 _a_full = _a; \
+ unsigned long long _a_full = _a; \
unsigned int _to_shift = \
is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \
*_d = (_a_full << _to_shift); \
@@ -132,10 +211,10 @@ static inline bool __must_check __must_check_overflow(bool overflow)
#define __overflows_type_constexpr(x, T) ( \
is_unsigned_type(typeof(x)) ? \
- (x) > type_max(typeof(T)) : \
+ (x) > type_max(T) : \
is_unsigned_type(typeof(T)) ? \
- (x) < 0 || (x) > type_max(typeof(T)) : \
- (x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))
+ (x) < 0 || (x) > type_max(T) : \
+ (x) < type_min(T) || (x) > type_max(T))
#define __overflows_type(x, T) ({ \
typeof(T) v = 0; \
@@ -312,27 +391,40 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
struct_size((type *)NULL, member, count)
/**
- * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
- * Enables caller macro to pass (different) initializer.
+ * __DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
+ * Enables caller macro to pass arbitrary trailing expressions
*
* @type: structure type name, including "struct" keyword.
* @name: Name for a variable to define.
* @member: Name of the array member.
* @count: Number of elements in the array; must be compile-time const.
- * @initializer: initializer expression (could be empty for no init).
+ * @trailer: Trailing expressions for attributes and/or initializers.
*/
-#define _DEFINE_FLEX(type, name, member, count, initializer) \
+#define __DEFINE_FLEX(type, name, member, count, trailer...) \
_Static_assert(__builtin_constant_p(count), \
"onstack flex array members require compile-time const count"); \
union { \
u8 bytes[struct_size_t(type, member, count)]; \
type obj; \
- } name##_u initializer; \
+ } name##_u trailer; \
type *name = (type *)&name##_u
/**
- * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
- * flexible array member.
+ * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
+ * Enables caller macro to pass (different) initializer.
+ *
+ * @type: structure type name, including "struct" keyword.
+ * @name: Name for a variable to define.
+ * @member: Name of the array member.
+ * @count: Number of elements in the array; must be compile-time const.
+ * @initializer: Initializer expression (e.g., pass `= { }` at minimum).
+ */
+#define _DEFINE_FLEX(type, name, member, count, initializer...) \
+ __DEFINE_FLEX(type, name, member, count, = { .obj initializer })
+
+/**
+ * DEFINE_RAW_FLEX() - Define an on-stack instance of structure with a trailing
+ * flexible array member, when it does not have a __counted_by annotation.
*
* @type: structure type name, including "struct" keyword.
* @name: Name for a variable to define.
@@ -342,8 +434,42 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
* Define a zeroed, on-stack, instance of @type structure with a trailing
* flexible array member.
* Use __struct_size(@name) to get compile-time size of it afterwards.
+ * Use __member_size(@name->member) to get compile-time size of @name members.
+ * Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of
+ * elements in array @member.
+ */
+#define DEFINE_RAW_FLEX(type, name, member, count) \
+ __DEFINE_FLEX(type, name, member, count, = { })
+
+/**
+ * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
+ * flexible array member.
+ *
+ * @TYPE: structure type name, including "struct" keyword.
+ * @NAME: Name for a variable to define.
+ * @MEMBER: Name of the array member.
+ * @COUNTER: Name of the __counted_by member.
+ * @COUNT: Number of elements in the array; must be compile-time const.
+ *
+ * Define a zeroed, on-stack, instance of @TYPE structure with a trailing
+ * flexible array member.
+ * Use __struct_size(@NAME) to get compile-time size of it afterwards.
+ * Use __member_size(@NAME->member) to get compile-time size of @NAME members.
+ * Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of
+ * elements in array @member.
+ */
+#define DEFINE_FLEX(TYPE, NAME, MEMBER, COUNTER, COUNT) \
+ _DEFINE_FLEX(TYPE, NAME, MEMBER, COUNT, = { .COUNTER = COUNT, })
+
+/**
+ * STACK_FLEX_ARRAY_SIZE() - helper macro for DEFINE_FLEX() family.
+ * Returns the number of elements in @array.
+ *
+ * @name: Name for a variable defined in DEFINE_RAW_FLEX()/DEFINE_FLEX().
+ * @array: Name of the array member.
*/
-#define DEFINE_FLEX(type, name, member, count) \
- _DEFINE_FLEX(type, name, member, count, = {})
+#define STACK_FLEX_ARRAY_SIZE(name, array) \
+ (__member_size((name)->array) / sizeof(*(name)->array) + \
+ __must_be_array((name)->array))
#endif /* _LINUXKPI_LINUX_OVERFLOW_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h
index 3fd4191b9917..06336bf963d6 100644
--- a/sys/compat/linuxkpi/common/include/linux/pci.h
+++ b/sys/compat/linuxkpi/common/include/linux/pci.h
@@ -355,7 +355,6 @@ struct pci_dev {
TAILQ_HEAD(, pci_mmio_region) mmio;
};
-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);
@@ -365,10 +364,13 @@ void __iomem **linuxkpi_pcim_iomap_table(struct pci_dev *pdev);
void *linuxkpi_pci_iomap_range(struct pci_dev *, int,
unsigned long, unsigned long);
void *linuxkpi_pci_iomap(struct pci_dev *, int, unsigned long);
+void *linuxkpi_pcim_iomap(struct pci_dev *, int, unsigned long);
void linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res);
int linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask,
const char *name);
+int linuxkpi_pci_request_region(struct pci_dev *, int, const char *);
int linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name);
+int linuxkpi_pcim_request_all_regions(struct pci_dev *, const char *);
void linuxkpi_pci_release_region(struct pci_dev *pdev, int bar);
void linuxkpi_pci_release_regions(struct pci_dev *pdev);
int linuxkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries,
@@ -561,12 +563,16 @@ done:
return (pdev->bus->self);
}
+#define pci_request_region(pdev, bar, res_name) \
+ linuxkpi_pci_request_region(pdev, bar, res_name)
#define pci_release_region(pdev, bar) \
linuxkpi_pci_release_region(pdev, bar)
-#define pci_release_regions(pdev) \
- linuxkpi_pci_release_regions(pdev)
#define pci_request_regions(pdev, res_name) \
linuxkpi_pci_request_regions(pdev, res_name)
+#define pci_release_regions(pdev) \
+ linuxkpi_pci_release_regions(pdev)
+#define pcim_request_all_regions(pdev, name) \
+ linuxkpi_pcim_request_all_regions(pdev, name)
static inline void
lkpi_pci_disable_msix(struct pci_dev *pdev)
@@ -803,6 +809,8 @@ static inline void pci_disable_sriov(struct pci_dev *dev)
linuxkpi_pci_iomap_range(pdev, mmio_bar, mmio_off, mmio_size)
#define pci_iomap(pdev, mmio_bar, mmio_size) \
linuxkpi_pci_iomap(pdev, mmio_bar, mmio_size)
+#define pcim_iomap(pdev, bar, maxlen) \
+ linuxkpi_pcim_iomap(pdev, bar, maxlen)
#define pci_iounmap(pdev, res) \
linuxkpi_pci_iounmap(pdev, res)
@@ -824,6 +832,19 @@ lkpi_pci_restore_state(struct pci_dev *pdev)
#define pci_restore_state(dev) lkpi_pci_restore_state(dev)
static inline int
+linuxkpi_pci_enable_wake(struct pci_dev *pdev, pci_power_t state, bool ena)
+{
+ /*
+ * We do not currently support this in device.h either to
+ * check if the device is allowed to wake up in first place.
+ */
+ pr_debug("%s: TODO\n", __func__);
+ return (0);
+}
+#define pci_enable_wake(dev, state, ena) \
+ linuxkpi_pci_enable_wake(dev, state, ena)
+
+static inline int
pci_reset_function(struct pci_dev *pdev)
{
@@ -1324,6 +1345,12 @@ struct pci_dev *lkpi_pci_get_domain_bus_and_slot(int domain,
#define pci_get_domain_bus_and_slot(domain, bus, devfn) \
lkpi_pci_get_domain_bus_and_slot(domain, bus, devfn)
+struct pci_dev *lkpi_pci_get_slot(struct pci_bus *, unsigned int);
+#ifndef WANT_NATIVE_PCI_GET_SLOT
+#define pci_get_slot(_pbus, _devfn) \
+ lkpi_pci_get_slot(_pbus, _devfn)
+#endif
+
static inline int
pci_domain_nr(struct pci_bus *pbus)
{
@@ -1445,6 +1472,9 @@ linuxkpi_pci_get_device(uint32_t vendor, uint32_t device, struct pci_dev *odev)
return (lkpi_pci_get_device(vendor, device, odev));
}
+#define for_each_pci_dev(_pdev) \
+ while ((_pdev = linuxkpi_pci_get_device(PCI_ANY_ID, PCI_ANY_ID, _pdev)) != NULL)
+
/* This is a FreeBSD extension so we can use bus_*(). */
static inline void
linuxkpi_pcim_want_to_use_bus_functions(struct pci_dev *pdev)
diff --git a/sys/compat/linuxkpi/common/include/linux/platform_device.h b/sys/compat/linuxkpi/common/include/linux/platform_device.h
index 6853e709cb70..dba79f5936cc 100644
--- a/sys/compat/linuxkpi/common/include/linux/platform_device.h
+++ b/sys/compat/linuxkpi/common/include/linux/platform_device.h
@@ -39,7 +39,7 @@ struct platform_device {
};
struct platform_driver {
- int (*remove)(struct platform_device *);
+ void (*remove)(struct platform_device *);
struct device_driver driver;
};
diff --git a/sys/compat/linuxkpi/common/include/linux/pm.h b/sys/compat/linuxkpi/common/include/linux/pm.h
index c8d943027909..932697e0eda8 100644
--- a/sys/compat/linuxkpi/common/include/linux/pm.h
+++ b/sys/compat/linuxkpi/common/include/linux/pm.h
@@ -97,4 +97,18 @@ pm_wakeup_event(struct device *dev __unused, unsigned int x __unused)
pr_debug("%s: TODO\n", __func__);
}
+/*
+ * We do not need to specify anything here as a VT switch always happens on
+ * suspend/resume.
+ */
+static inline void
+pm_vt_switch_required(struct device *dev __unused, bool required __unused)
+{
+}
+
+static inline void
+pm_vt_switch_unregister(struct device *dev __unused)
+{
+}
+
#endif /* _LINUXKPI_LINUX_PM_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/rcupdate.h b/sys/compat/linuxkpi/common/include/linux/rcupdate.h
index 85d766c8dbc9..4aceb7296cd6 100644
--- a/sys/compat/linuxkpi/common/include/linux/rcupdate.h
+++ b/sys/compat/linuxkpi/common/include/linux/rcupdate.h
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2016-2017 Mellanox Technologies, Ltd.
* All rights reserved.
- * Copyright (c) 2024 The FreeBSD Foundation
+ * Copyright (c) 2024-2025 The FreeBSD Foundation
*
* Portions of this software were developed by Björn Zeeb
* under sponsorship from the FreeBSD Foundation.
@@ -35,6 +35,7 @@
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/kernel.h>
+#include <linux/cleanup.h>
#include <machine/atomic.h>
@@ -162,4 +163,6 @@ void linux_synchronize_rcu(unsigned type);
#define init_rcu_head_on_stack(...)
#define destroy_rcu_head_on_stack(...)
+DEFINE_LOCK_GUARD_0(rcu, rcu_read_lock(), rcu_read_unlock())
+
#endif /* _LINUXKPI_LINUX_RCUPDATE_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h
index 6e41c368a8b8..2e560a120e41 100644
--- a/sys/compat/linuxkpi/common/include/linux/skbuff.h
+++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h
@@ -1159,6 +1159,9 @@ skb_cow_head(struct sk_buff *skb, unsigned int headroom)
return (-1);
}
+/* Misplaced here really but sock comes from skbuff. */
+#define sk_pacing_shift_update(sock, n)
+
#define SKB_WITH_OVERHEAD(_s) \
(_s) - ALIGN(sizeof(struct skb_shared_info), CACHE_LINE_SIZE)
diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h
index 47e3d133eb6c..0e649e1e3c4a 100644
--- a/sys/compat/linuxkpi/common/include/linux/slab.h
+++ b/sys/compat/linuxkpi/common/include/linux/slab.h
@@ -40,8 +40,10 @@
#include <linux/compat.h>
#include <linux/types.h>
#include <linux/gfp.h>
+#include <linux/err.h>
#include <linux/llist.h>
#include <linux/overflow.h>
+#include <linux/cleanup.h>
MALLOC_DECLARE(M_KMALLOC);
@@ -153,6 +155,8 @@ kfree(const void *ptr)
lkpi_kfree(ptr);
}
+DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T))
+
/*
* Other k*alloc() funtions using the above as underlying allocator.
*/
diff --git a/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h b/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h
index 903053e7f6e8..9f3a1ee4c139 100644
--- a/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h
+++ b/sys/compat/linuxkpi/common/include/linux/soc/mediatek/mtk_wed.h
@@ -1,54 +1,36 @@
/*-
- * 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.
+ * Copyright (c) 2022-2025 Bjoern A. Zeeb
*
- * 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.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H
#define _LINUXKPI_LINUX_SOC_MEDIATEK_MTK_WED_H
+#include <linux/kernel.h> /* pr_debug */
+
struct mtk_wed_device {
};
#define WED_WO_STA_REC 0x6
-#define mtk_wed_device_start(_dev, _mask) do { } while(0)
-#define mtk_wed_device_detach(_dev) do { } while(0)
+#define mtk_wed_device_start(_dev, _mask) do { pr_debug("%s: TODO\n", __func__); } while(0)
+#define mtk_wed_device_detach(_dev) do { pr_debug("%s: TODO\n", __func__); } while(0)
#define mtk_wed_device_irq_get(_dev, _mask) 0
-#define mtk_wed_device_irq_set_mask(_dev, _mask) do { } 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_irq_set_mask(_dev, _mask) do { pr_debug("%s: TODO\n", __func__); } while(0)
+#define mtk_wed_device_update_msg(_dev, _id, _msg, _len) ({ pr_debug("%s: TODO\n", __func__); -ENODEV; })
+#define mtk_wed_device_dma_reset(_dev) do { pr_debug("%s: TODO\n", __func__); } while (0)
#define mtk_wed_device_ppe_check(_dev, _skb, _reason, _entry) \
- do {} 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)
+ do { pr_debug("%s: TODO\n", __func__); } while (0)
+#define mtk_wed_device_stop(_dev) do { pr_debug("%s: TODO\n", __func__); } while(0)
+#define mtk_wed_device_start_hw_rro(_dev, _mask, _b) do { pr_debug("%s: TODO\n", __func__); } while(0)
+#define mtk_wed_device_setup_tc(_dev, _ndev, _type, _tdata) ({ pr_debug("%s: TODO\n", __func__); -EOPNOTSUPP; })
static inline bool
mtk_wed_device_active(struct mtk_wed_device *dev __unused)
{
+ pr_debug("%s: TODO\n", __func__);
return (false);
}
@@ -56,6 +38,7 @@ static inline bool
mtk_wed_get_rx_capa(struct mtk_wed_device *dev __unused)
{
+ pr_debug("%s: TODO\n", __func__);
return (false);
}
diff --git a/sys/compat/linuxkpi/common/include/linux/string_choices.h b/sys/compat/linuxkpi/common/include/linux/string_choices.h
new file mode 100644
index 000000000000..74aa3fd019b2
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/string_choices.h
@@ -0,0 +1,71 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LINUXKPI_LINUX_STRING_CHOICES_H_
+#define _LINUXKPI_LINUX_STRING_CHOICES_H_
+
+#include <sys/types.h>
+
+static inline const char *
+str_yes_no(bool value)
+{
+ if (value)
+ return "yes";
+ else
+ return "no";
+}
+
+static inline const char *
+str_on_off(bool value)
+{
+ if (value)
+ return "on";
+ else
+ return "off";
+}
+
+static inline const char *
+str_enabled_disabled(bool value)
+{
+ if (value)
+ return "enabled";
+ else
+ return "disabled";
+}
+
+static inline const char *
+str_enable_disable(bool value)
+{
+ if (value)
+ return "enable";
+ else
+ return "disable";
+}
+
+#define str_disable_enable(_v) str_enable_disable(!(_v))
+
+#endif
diff --git a/sys/compat/linuxkpi/common/include/linux/string_helpers.h b/sys/compat/linuxkpi/common/include/linux/string_helpers.h
index 2c6fe0b1708d..07d113c0cb21 100644
--- a/sys/compat/linuxkpi/common/include/linux/string_helpers.h
+++ b/sys/compat/linuxkpi/common/include/linux/string_helpers.h
@@ -1,71 +1,12 @@
-/*-
- * 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.
+/*
+ * Copyright (c) 2025 The FreeBSD Foundation
*
- * 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.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
#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";
-}
-
-#define str_disable_enable(_v) str_enable_disable(!(_v))
+#include <linux/string_choices.h>
#endif
diff --git a/sys/compat/linuxkpi/common/include/linux/timer.h b/sys/compat/linuxkpi/common/include/linux/timer.h
index a635f0faea59..d48939e28a02 100644
--- a/sys/compat/linuxkpi/common/include/linux/timer.h
+++ b/sys/compat/linuxkpi/common/include/linux/timer.h
@@ -49,8 +49,13 @@ extern unsigned long linux_timer_hz_mask;
#define TIMER_IRQSAFE 0x0001
+#if defined(LINUXKPI_VERSION) && (LINUXKPI_VERSION < 61600)
#define from_timer(var, arg, field) \
container_of(arg, typeof(*(var)), field)
+#else
+#define timer_container_of(var, arg, field) \
+ container_of(arg, typeof(*(var)), field)
+#endif
#define timer_setup(timer, func, flags) do { \
CTASSERT(((flags) & ~TIMER_IRQSAFE) == 0); \
@@ -79,11 +84,23 @@ extern unsigned long linux_timer_hz_mask;
extern int mod_timer(struct timer_list *, unsigned long);
extern void add_timer(struct timer_list *);
extern void add_timer_on(struct timer_list *, int cpu);
-extern int del_timer(struct timer_list *);
-extern int del_timer_sync(struct timer_list *);
+
+extern int timer_delete(struct timer_list *);
extern int timer_delete_sync(struct timer_list *);
extern int timer_shutdown_sync(struct timer_list *);
+static inline int
+del_timer(struct timer_list *tl)
+{
+ return (timer_delete(tl));
+}
+
+static inline int
+del_timer_sync(struct timer_list *tl)
+{
+ return (timer_delete_sync(tl));
+}
+
#define timer_pending(timer) callout_pending(&(timer)->callout)
#define round_jiffies(j) \
((unsigned long)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask))
diff --git a/sys/compat/linuxkpi/common/include/net/cfg80211.h b/sys/compat/linuxkpi/common/include/net/cfg80211.h
index 239b4a5ae7b8..305026b34451 100644
--- a/sys/compat/linuxkpi/common/include/net/cfg80211.h
+++ b/sys/compat/linuxkpi/common/include/net/cfg80211.h
@@ -56,7 +56,7 @@ extern int linuxkpi_debug_80211;
#define D80211_IMPROVE 0x2
#endif
#define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \
- printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
+ printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
#define IMPROVE(fmt, ...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \
printf("%s:%d: XXX LKPI80211 IMPROVE " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
@@ -260,6 +260,19 @@ enum ieee80211_vht_opmode {
IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT = 4,
};
+struct cfg80211_bss_ies {
+ uint8_t *data;
+ size_t len;
+};
+
+struct cfg80211_bss {
+ /* XXX TODO */
+ struct cfg80211_bss_ies *ies;
+ struct cfg80211_bss_ies *beacon_ies;
+ uint64_t ts_boottime;
+ int32_t signal;
+};
+
struct cfg80211_connect_resp_params {
/* XXX TODO */
uint8_t *bssid;
@@ -267,7 +280,13 @@ struct cfg80211_connect_resp_params {
const uint8_t *resp_ie;
uint32_t req_ie_len;
uint32_t resp_ie_len;
- int status;
+ int status;
+ struct {
+ const uint8_t *addr;
+ const uint8_t *bssid;
+ struct cfg80211_bss *bss;
+ uint16_t status;
+ } links[IEEE80211_MLD_MAX_NUM_LINKS];
};
struct cfg80211_inform_bss {
@@ -284,19 +303,12 @@ struct cfg80211_roam_info {
uint32_t req_ie_len;
uint32_t resp_ie_len;
struct linuxkpi_ieee80211_channel *channel;
-};
-
-struct cfg80211_bss_ies {
- uint8_t *data;
- size_t len;
-};
-
-struct cfg80211_bss {
- /* XXX TODO */
- struct cfg80211_bss_ies *ies;
- struct cfg80211_bss_ies *beacon_ies;
-
- int32_t signal;
+ struct {
+ const uint8_t *addr;
+ const uint8_t *bssid;
+ struct cfg80211_bss *bss;
+ struct linuxkpi_ieee80211_channel *channel;
+ } links[IEEE80211_MLD_MAX_NUM_LINKS];
};
struct cfg80211_chan_def {
@@ -404,6 +416,7 @@ struct cfg80211_scan_request {
bool no_cck;
bool scan_6ghz;
bool duration_mandatory;
+ bool first_part;
int8_t tsf_report_link_id;
uint16_t duration;
uint32_t flags;
@@ -463,6 +476,24 @@ struct cfg80211_beacon_data {
uint32_t assocresp_ies_len;
};
+struct cfg80211_ap_update {
+ /* XXX TODO */
+ struct cfg80211_beacon_data beacon;
+};
+
+struct cfg80211_crypto_settings {
+ /* XXX TODO */
+ enum nl80211_wpa_versions wpa_versions;
+ uint32_t cipher_group; /* WLAN_CIPHER_SUITE_* */
+ uint32_t *akm_suites;
+ uint32_t *ciphers_pairwise;
+ const uint8_t *sae_pwd;
+ const uint8_t *psk;
+ int n_akm_suites;
+ int n_ciphers_pairwise;
+ int sae_pwd_len;
+};
+
struct cfg80211_ap_settings {
/* XXX TODO */
int auth_type, beacon_interval, dtim_period, hidden_ssid, inactivity_timeout;
@@ -470,6 +501,7 @@ struct cfg80211_ap_settings {
size_t ssid_len;
struct cfg80211_beacon_data beacon;
struct cfg80211_chan_def chandef;
+ struct cfg80211_crypto_settings crypto;
};
struct cfg80211_bss_selection {
@@ -484,23 +516,12 @@ struct cfg80211_bss_selection {
} param;
};
-struct cfg80211_crypto { /* XXX made up name */
- /* XXX TODO */
- enum nl80211_wpa_versions wpa_versions;
- uint32_t cipher_group; /* WLAN_CIPHER_SUITE_* */
- uint32_t *akm_suites;
- uint32_t *ciphers_pairwise;
- const uint8_t *sae_pwd;
- const uint8_t *psk;
- int n_akm_suites;
- int n_ciphers_pairwise;
- int sae_pwd_len;
-};
-
struct cfg80211_connect_params {
/* XXX TODO */
struct linuxkpi_ieee80211_channel *channel;
+ struct linuxkpi_ieee80211_channel *channel_hint;
uint8_t *bssid;
+ uint8_t *bssid_hint;
const uint8_t *ie;
const uint8_t *ssid;
uint32_t ie_len;
@@ -509,7 +530,7 @@ struct cfg80211_connect_params {
uint32_t key_len;
int auth_type, key_idx, privacy, want_1x;
struct cfg80211_bss_selection bss_select;
- struct cfg80211_crypto crypto;
+ struct cfg80211_crypto_settings crypto;
};
enum bss_param_flags { /* Used as bitflags. XXX FIXME values? */
@@ -538,6 +559,14 @@ struct cfg80211_mgmt_tx_params {
int wait;
};
+struct cfg80211_external_auth_params {
+ uint8_t bssid[ETH_ALEN];
+ uint16_t status;
+ enum nl80211_external_auth_action action;
+ unsigned int key_mgmt_suite;
+ struct cfg80211_ssid ssid;
+};
+
struct cfg80211_pmk_conf {
/* XXX TODO */
const uint8_t *pmk;
@@ -548,6 +577,8 @@ struct cfg80211_pmksa {
/* XXX TODO */
const uint8_t *bssid;
const uint8_t *pmkid;
+ const uint8_t *ssid;
+ size_t ssid_len;
};
struct station_del_parameters {
@@ -961,6 +992,27 @@ struct cfg80211_set_hw_timestamp {
bool enable;
};
+struct survey_info { /* net80211::struct ieee80211_channel_survey */
+ /* TODO FIXME */
+ uint32_t filled;
+#define SURVEY_INFO_TIME 0x0001
+#define SURVEY_INFO_TIME_RX 0x0002
+#define SURVEY_INFO_TIME_SCAN 0x0004
+#define SURVEY_INFO_TIME_TX 0x0008
+#define SURVEY_INFO_TIME_BSS_RX 0x0010
+#define SURVEY_INFO_TIME_BUSY 0x0020
+#define SURVEY_INFO_IN_USE 0x0040
+#define SURVEY_INFO_NOISE_DBM 0x0080
+ uint32_t noise;
+ uint64_t time;
+ uint64_t time_bss_rx;
+ uint64_t time_busy;
+ uint64_t time_rx;
+ uint64_t time_scan;
+ uint64_t time_tx;
+ struct linuxkpi_ieee80211_channel *channel;
+};
+
enum wiphy_vendor_cmd_need_flags {
WIPHY_VENDOR_CMD_NEED_NETDEV = 0x01,
WIPHY_VENDOR_CMD_NEED_RUNNING = 0x02,
@@ -1118,49 +1170,53 @@ struct wireless_dev {
struct cfg80211_ops {
/* XXX TODO */
struct wireless_dev *(*add_virtual_intf)(struct wiphy *, const char *, unsigned char, enum nl80211_iftype, struct vif_params *);
- int (*del_virtual_intf)(struct wiphy *, struct wireless_dev *);
- s32 (*change_virtual_intf)(struct wiphy *, struct net_device *, enum nl80211_iftype, struct vif_params *);
- s32 (*scan)(struct wiphy *, struct cfg80211_scan_request *);
- s32 (*set_wiphy_params)(struct wiphy *, u32);
- s32 (*join_ibss)(struct wiphy *, struct net_device *, struct cfg80211_ibss_params *);
- s32 (*leave_ibss)(struct wiphy *, struct net_device *);
- s32 (*get_station)(struct wiphy *, struct net_device *, const u8 *, struct station_info *);
- int (*dump_station)(struct wiphy *, struct net_device *, int, u8 *, struct station_info *);
- s32 (*set_tx_power)(struct wiphy *, struct wireless_dev *, enum nl80211_tx_power_setting, s32);
- s32 (*get_tx_power)(struct wiphy *, struct wireless_dev *, s32 *);
- s32 (*add_key)(struct wiphy *, struct net_device *, u8, bool, const u8 *, struct key_params *);
- s32 (*del_key)(struct wiphy *, struct net_device *, u8, bool, const u8 *);
- s32 (*get_key)(struct wiphy *, struct net_device *, u8, bool, const u8 *, void *, void(*)(void *, struct key_params *));
- s32 (*set_default_key)(struct wiphy *, struct net_device *, u8, bool, bool);
- s32 (*set_default_mgmt_key)(struct wiphy *, struct net_device *, u8);
- s32 (*set_power_mgmt)(struct wiphy *, struct net_device *, bool, s32);
- s32 (*connect)(struct wiphy *, struct net_device *, struct cfg80211_connect_params *);
- s32 (*disconnect)(struct wiphy *, struct net_device *, u16);
- s32 (*suspend)(struct wiphy *, struct cfg80211_wowlan *);
- s32 (*resume)(struct wiphy *);
- s32 (*set_pmksa)(struct wiphy *, struct net_device *, struct cfg80211_pmksa *);
- s32 (*del_pmksa)(struct wiphy *, struct net_device *, struct cfg80211_pmksa *);
- s32 (*flush_pmksa)(struct wiphy *, struct net_device *);
- s32 (*start_ap)(struct wiphy *, struct net_device *, struct cfg80211_ap_settings *);
- int (*stop_ap)(struct wiphy *, struct net_device *);
- s32 (*change_beacon)(struct wiphy *, struct net_device *, struct cfg80211_beacon_data *);
- int (*del_station)(struct wiphy *, struct net_device *, struct station_del_parameters *);
- int (*change_station)(struct wiphy *, struct net_device *, const u8 *, struct station_parameters *);
+ int (*del_virtual_intf)(struct wiphy *, struct wireless_dev *);
+ int (*change_virtual_intf)(struct wiphy *, struct net_device *, enum nl80211_iftype, struct vif_params *);
+ int (*scan)(struct wiphy *, struct cfg80211_scan_request *);
+ int (*set_wiphy_params)(struct wiphy *, int, uint32_t);
+ int (*join_ibss)(struct wiphy *, struct net_device *, struct cfg80211_ibss_params *);
+ int (*leave_ibss)(struct wiphy *, struct net_device *);
+ int (*get_station)(struct wiphy *, struct net_device *, const uint8_t *, struct station_info *);
+ int (*dump_station)(struct wiphy *, struct net_device *, int, uint8_t *, struct station_info *);
+ int (*set_tx_power)(struct wiphy *, struct wireless_dev *, int, enum nl80211_tx_power_setting, int);
+ int (*get_tx_power)(struct wiphy *, struct wireless_dev *, int, unsigned int, int *);
+ int (*add_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, const uint8_t *, struct key_params *);
+ int (*del_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, const uint8_t *);
+ int (*get_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, const uint8_t *, void *, void(*)(void *, struct key_params *));
+ int (*set_default_key)(struct wiphy *, struct net_device *, int, uint8_t, bool, bool);
+ int (*set_default_mgmt_key)(struct wiphy *, struct net_device *, int, uint8_t);
+ int (*set_power_mgmt)(struct wiphy *, struct net_device *, bool, int);
+ int (*connect)(struct wiphy *, struct net_device *, struct cfg80211_connect_params *);
+ int (*disconnect)(struct wiphy *, struct net_device *, uint16_t);
+ int (*suspend)(struct wiphy *, struct cfg80211_wowlan *);
+ int (*resume)(struct wiphy *);
+ int (*set_pmksa)(struct wiphy *, struct net_device *, struct cfg80211_pmksa *);
+ int (*del_pmksa)(struct wiphy *, struct net_device *, struct cfg80211_pmksa *);
+ int (*flush_pmksa)(struct wiphy *, struct net_device *);
+ int (*start_ap)(struct wiphy *, struct net_device *, struct cfg80211_ap_settings *);
+ int (*stop_ap)(struct wiphy *, struct net_device *, unsigned int);
+ int (*change_beacon)(struct wiphy *, struct net_device *, struct cfg80211_ap_update *);
+ int (*del_station)(struct wiphy *, struct net_device *, struct station_del_parameters *);
+ int (*change_station)(struct wiphy *, struct net_device *, const uint8_t *, struct station_parameters *);
int (*sched_scan_start)(struct wiphy *, struct net_device *, struct cfg80211_sched_scan_request *);
- int (*sched_scan_stop)(struct wiphy *, struct net_device *, u64);
+ int (*sched_scan_stop)(struct wiphy *, struct net_device *, uint64_t);
void (*update_mgmt_frame_registrations)(struct wiphy *, struct wireless_dev *, struct mgmt_frame_regs *);
- int (*mgmt_tx)(struct wiphy *, struct wireless_dev *, struct cfg80211_mgmt_tx_params *, u64 *);
- int (*cancel_remain_on_channel)(struct wiphy *, struct wireless_dev *, u64);
- int (*get_channel)(struct wiphy *, struct wireless_dev *, struct cfg80211_chan_def *);
- int (*crit_proto_start)(struct wiphy *, struct wireless_dev *, enum nl80211_crit_proto_id, u16);
+ int (*mgmt_tx)(struct wiphy *, struct wireless_dev *, struct cfg80211_mgmt_tx_params *, uint64_t *);
+ int (*cancel_remain_on_channel)(struct wiphy *, struct wireless_dev *, uint64_t);
+ int (*get_channel)(struct wiphy *, struct wireless_dev *, unsigned int, struct cfg80211_chan_def *);
+ int (*crit_proto_start)(struct wiphy *, struct wireless_dev *, enum nl80211_crit_proto_id, uint16_t);
void (*crit_proto_stop)(struct wiphy *, struct wireless_dev *);
- int (*tdls_oper)(struct wiphy *, struct net_device *, const u8 *, enum nl80211_tdls_operation);
- int (*update_connect_params)(struct wiphy *, struct net_device *, struct cfg80211_connect_params *, u32);
- int (*set_pmk)(struct wiphy *, struct net_device *, const struct cfg80211_pmk_conf *);
- int (*del_pmk)(struct wiphy *, struct net_device *, const u8 *);
- int (*remain_on_channel)(struct wiphy *, struct wireless_dev *, struct linuxkpi_ieee80211_channel *, unsigned int, u64 *);
- int (*start_p2p_device)(struct wiphy *, struct wireless_dev *);
- void (*stop_p2p_device)(struct wiphy *, struct wireless_dev *);
+ int (*tdls_oper)(struct wiphy *, struct net_device *, const uint8_t *, enum nl80211_tdls_operation);
+ int (*update_connect_params)(struct wiphy *, struct net_device *, struct cfg80211_connect_params *, uint32_t);
+ int (*set_pmk)(struct wiphy *, struct net_device *, const struct cfg80211_pmk_conf *);
+ int (*del_pmk)(struct wiphy *, struct net_device *, const uint8_t *);
+ int (*remain_on_channel)(struct wiphy *, struct wireless_dev *, struct linuxkpi_ieee80211_channel *, unsigned int, uint64_t *);
+ int (*start_p2p_device)(struct wiphy *, struct wireless_dev *);
+ void (*stop_p2p_device)(struct wiphy *, struct wireless_dev *);
+ int (*dump_survey)(struct wiphy *, struct net_device *, int, struct survey_info *);
+ int (*external_auth)(struct wiphy *, struct net_device *, struct cfg80211_external_auth_params *);
+ int (*set_cqm_rssi_range_config)(struct wiphy *, struct net_device *, int, int);
+
};
@@ -1179,6 +1235,8 @@ void linuxkpi_wiphy_delayed_work_queue(struct wiphy *,
struct wiphy_delayed_work *, unsigned long);
void linuxkpi_wiphy_delayed_work_cancel(struct wiphy *,
struct wiphy_delayed_work *);
+void linuxkpi_wiphy_delayed_work_flush(struct wiphy *,
+ struct wiphy_delayed_work *);
int linuxkpi_regulatory_set_wiphy_regd_sync(struct wiphy *wiphy,
struct linuxkpi_ieee80211_regdomain *regd);
@@ -1247,6 +1305,21 @@ wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked,
/* -------------------------------------------------------------------------- */
+static inline int
+cfg80211_register_netdevice(struct net_device *ndev)
+{
+ TODO();
+ return (-ENXIO);
+}
+
+static inline void
+cfg80211_unregister_netdevice(struct net_device *ndev)
+{
+ TODO();
+}
+
+/* -------------------------------------------------------------------------- */
+
static inline struct cfg80211_bss *
cfg80211_get_bss(struct wiphy *wiphy, struct linuxkpi_ieee80211_channel *chan,
const uint8_t *bssid, const uint8_t *ssid, size_t ssid_len,
@@ -1309,15 +1382,15 @@ reg_query_regdb_wmm(uint8_t *alpha2, uint32_t center_freq,
return (-ENODATA);
}
-static __inline const u8 *
-cfg80211_find_ie_match(uint32_t f, const u8 *ies, size_t ies_len,
- const u8 *match, int x, int y)
+static __inline const uint8_t *
+cfg80211_find_ie_match(uint32_t f, const uint8_t *ies, size_t ies_len,
+ const uint8_t *match, int x, int y)
{
TODO();
return (NULL);
}
-static __inline const u8 *
+static __inline const uint8_t *
cfg80211_find_ie(uint8_t eid, const uint8_t *ie, uint32_t ielen)
{
TODO();
@@ -1339,6 +1412,36 @@ cfg80211_pmsr_report(struct wireless_dev *wdev,
TODO();
}
+static inline int
+nl80211_chan_width_to_mhz(enum nl80211_chan_width width)
+{
+ switch (width) {
+ case NL80211_CHAN_WIDTH_5:
+ return (5);
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ return (10);
+ break;
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ return (20);
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ return (40);
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ case NL80211_CHAN_WIDTH_80P80:
+ return (80);
+ break;
+ case NL80211_CHAN_WIDTH_160:
+ return (160);
+ break;
+ case NL80211_CHAN_WIDTH_320:
+ return (320);
+ break;
+ }
+}
+
static inline void
cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
struct linuxkpi_ieee80211_channel *chan, enum nl80211_channel_type chan_type)
@@ -1347,7 +1450,7 @@ cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
KASSERT(chandef != NULL, ("%s: chandef is NULL\n", __func__));
KASSERT(chan != NULL, ("%s: chan is NULL\n", __func__));
- /* memset(chandef, 0, sizeof(*chandef)); */
+ memset(chandef, 0, sizeof(*chandef));
chandef->chan = chan;
chandef->center_freq1 = chan->center_freq;
/* chandef->width, center_freq2, punctured */
@@ -1377,6 +1480,12 @@ cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
return (false);
}
+static inline int
+cfg80211_chandef_get_width(const struct cfg80211_chan_def *chandef)
+{
+ return (nl80211_chan_width_to_mhz(chandef->width));
+}
+
static __inline bool
cfg80211_chandef_dfs_usable(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef)
{
@@ -1688,8 +1797,8 @@ cfg80211_disconnected(struct net_device *ndev, uint16_t reason,
}
static __inline int
-cfg80211_get_p2p_attr(const u8 *ie, u32 ie_len,
- enum ieee80211_p2p_attr_ids attr, u8 *p, size_t p_len)
+cfg80211_get_p2p_attr(const uint8_t *ie, uint32_t ie_len,
+ enum ieee80211_p2p_attr_ids attr, uint8_t *p, size_t p_len)
{
TODO();
return (-1);
@@ -1725,13 +1834,13 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
static __inline void
cfg80211_mgmt_tx_status(struct wireless_dev *wdev, uint64_t cookie,
- const u8 *buf, size_t len, bool ack, gfp_t gfp)
+ const uint8_t *buf, size_t len, bool ack, gfp_t gfp)
{
TODO();
}
static __inline void
-cfg80211_michael_mic_failure(struct net_device *ndev, const uint8_t *addr,
+cfg80211_michael_mic_failure(struct net_device *ndev, const uint8_t addr[ETH_ALEN],
enum nl80211_key_type key_type, int _x, void *p, gfp_t gfp)
{
TODO();
@@ -1751,8 +1860,8 @@ cfg80211_del_sta(struct net_device *ndev, const uint8_t *addr, gfp_t gfp)
}
static __inline void
-cfg80211_port_authorized(struct net_device *ndev, const uint8_t *bssid,
- gfp_t gfp)
+cfg80211_port_authorized(struct net_device *ndev, const uint8_t *addr,
+ const uint8_t *bitmap, uint8_t len, gfp_t gfp)
{
TODO();
}
@@ -1935,7 +2044,7 @@ cfg80211_background_radar_event(struct wiphy *wiphy,
TODO();
}
-static __inline const u8 *
+static __inline const uint8_t *
cfg80211_find_ext_ie(uint8_t eid, const uint8_t *p, size_t len)
{
TODO();
@@ -2033,6 +2142,14 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype iftype)
return (NULL);
}
+static inline int
+cfg80211_external_auth_request(struct net_device *ndev,
+ struct cfg80211_external_auth_params *params, gfp_t gfp)
+{
+ TODO();
+ return (-ENXIO);
+}
+
static inline uint16_t
ieee80211_get_he_6ghz_capa(const struct ieee80211_supported_band *sband,
enum nl80211_iftype iftype)
@@ -2041,36 +2158,6 @@ ieee80211_get_he_6ghz_capa(const struct ieee80211_supported_band *sband,
return (0);
}
-static inline int
-nl80211_chan_width_to_mhz(enum nl80211_chan_width width)
-{
- switch (width) {
- case NL80211_CHAN_WIDTH_5:
- return (5);
- break;
- case NL80211_CHAN_WIDTH_10:
- return (10);
- break;
- case NL80211_CHAN_WIDTH_20_NOHT:
- case NL80211_CHAN_WIDTH_20:
- return (20);
- break;
- case NL80211_CHAN_WIDTH_40:
- return (40);
- break;
- case NL80211_CHAN_WIDTH_80:
- case NL80211_CHAN_WIDTH_80P80:
- return (80);
- break;
- case NL80211_CHAN_WIDTH_160:
- return (160);
- break;
- case NL80211_CHAN_WIDTH_320:
- return (320);
- break;
- }
-}
-
static __inline ssize_t
wiphy_locked_debugfs_read(struct wiphy *wiphy, struct file *file,
char *buf, size_t bufsize, const char __user *userbuf, size_t count,
@@ -2093,6 +2180,13 @@ wiphy_locked_debugfs_write(struct wiphy *wiphy, struct file *file,
return (-ENXIO);
}
+static inline void
+cfg80211_cqm_rssi_notify(struct net_device *dev,
+ enum nl80211_cqm_rssi_threshold_event rssi_te, int32_t rssi, gfp_t gfp)
+{
+ TODO();
+}
+
/* -------------------------------------------------------------------------- */
static inline void
@@ -2140,6 +2234,12 @@ wiphy_delayed_work_cancel(struct wiphy *wiphy, struct wiphy_delayed_work *wdwk)
linuxkpi_wiphy_delayed_work_cancel(wiphy, wdwk);
}
+static inline void
+wiphy_delayed_work_flush(struct wiphy *wiphy, struct wiphy_delayed_work *wdwk)
+{
+ linuxkpi_wiphy_delayed_work_flush(wiphy, wdwk);
+}
+
/* -------------------------------------------------------------------------- */
#define wiphy_err(_wiphy, _fmt, ...) \
diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h
index 8de03410c6b6..0eda07a8235c 100644
--- a/sys/compat/linuxkpi/common/include/net/mac80211.h
+++ b/sys/compat/linuxkpi/common/include/net/mac80211.h
@@ -166,7 +166,7 @@ enum ieee80211_bss_changed {
#define WLAN_AKM_SUITE_PSK_SHA256 WLAN_AKM_SUITE(6)
/* TDLS 7 */
#define WLAN_AKM_SUITE_SAE WLAN_AKM_SUITE(8)
-/* FToSAE 9 */
+#define WLAN_AKM_SUITE_FT_OVER_SAE WLAN_AKM_SUITE(9)
/* AP peer key 10 */
/* 802.1x suite B 11 */
/* 802.1x suite B 384 12 */
@@ -857,7 +857,8 @@ struct ieee80211_vif_chanctx_switch {
};
struct ieee80211_prep_tx_info {
- u16 duration;
+ uint16_t duration;
+ uint16_t subtype;
bool success;
bool was_assoc;
int link_id;
@@ -904,27 +905,6 @@ struct linuxkpi_ieee80211_tim_ie {
};
#define ieee80211_tim_ie linuxkpi_ieee80211_tim_ie
-struct survey_info { /* net80211::struct ieee80211_channel_survey */
- /* TODO FIXME */
- uint32_t filled;
-#define SURVEY_INFO_TIME 0x0001
-#define SURVEY_INFO_TIME_RX 0x0002
-#define SURVEY_INFO_TIME_SCAN 0x0004
-#define SURVEY_INFO_TIME_TX 0x0008
-#define SURVEY_INFO_TIME_BSS_RX 0x0010
-#define SURVEY_INFO_TIME_BUSY 0x0020
-#define SURVEY_INFO_IN_USE 0x0040
-#define SURVEY_INFO_NOISE_DBM 0x0080
- uint32_t noise;
- uint64_t time;
- uint64_t time_bss_rx;
- uint64_t time_busy;
- uint64_t time_rx;
- uint64_t time_scan;
- uint64_t time_tx;
- struct ieee80211_channel *channel;
-};
-
enum ieee80211_iface_iter {
IEEE80211_IFACE_ITER_NORMAL = BIT(0),
IEEE80211_IFACE_ITER_RESUME_ALL = BIT(1),
@@ -976,7 +956,7 @@ struct ieee80211_ops {
int (*start)(struct ieee80211_hw *);
void (*stop)(struct ieee80211_hw *, bool);
- int (*config)(struct ieee80211_hw *, u32);
+ int (*config)(struct ieee80211_hw *, int, u32);
void (*reconfig_complete)(struct ieee80211_hw *, enum ieee80211_reconfig_type);
void (*prep_add_interface)(struct ieee80211_hw *, enum nl80211_iftype);
@@ -1003,7 +983,7 @@ struct ieee80211_ops {
void (*flush)(struct ieee80211_hw *, struct ieee80211_vif *, u32, bool);
void (*flush_sta)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *);
- int (*set_frag_threshold)(struct ieee80211_hw *, u32);
+ int (*set_frag_threshold)(struct ieee80211_hw *, int, u32);
void (*sync_rx_queues)(struct ieee80211_hw *);
@@ -1046,8 +1026,8 @@ struct ieee80211_ops {
void (*unassign_vif_chanctx)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, struct ieee80211_chanctx_conf *);
int (*switch_vif_chanctx)(struct ieee80211_hw *, struct ieee80211_vif_chanctx_switch *, int, enum ieee80211_chanctx_switch_mode);
- int (*get_antenna)(struct ieee80211_hw *, u32 *, u32 *);
- int (*set_antenna)(struct ieee80211_hw *, u32, u32);
+ int (*get_antenna)(struct ieee80211_hw *, int, u32 *, u32 *);
+ int (*set_antenna)(struct ieee80211_hw *, int, u32, u32);
int (*remain_on_channel)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_channel *, int, enum ieee80211_roc_type);
int (*cancel_remain_on_channel)(struct ieee80211_hw *, struct ieee80211_vif *);
@@ -1058,7 +1038,7 @@ struct ieee80211_ops {
void (*bss_info_changed)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, u64);
void (*link_info_changed)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_bss_conf *, u64);
- int (*set_rts_threshold)(struct ieee80211_hw *, u32);
+ int (*set_rts_threshold)(struct ieee80211_hw *, int, u32);
void (*event_callback)(struct ieee80211_hw *, struct ieee80211_vif *, const struct ieee80211_event *);
int (*get_survey)(struct ieee80211_hw *, int, struct survey_info *);
int (*get_ftm_responder_stats)(struct ieee80211_hw *, struct ieee80211_vif *, struct cfg80211_ftm_responder_stats *);
@@ -1068,7 +1048,7 @@ struct ieee80211_ops {
void (*offset_tsf)(struct ieee80211_hw *, struct ieee80211_vif *, s64);
int (*set_bitrate_mask)(struct ieee80211_hw *, struct ieee80211_vif *, const struct cfg80211_bitrate_mask *);
- void (*set_coverage_class)(struct ieee80211_hw *, s16);
+ void (*set_coverage_class)(struct ieee80211_hw *, int, s16);
int (*set_tim)(struct ieee80211_hw *, struct ieee80211_sta *, bool);
int (*set_key)(struct ieee80211_hw *, enum set_key_cmd, struct ieee80211_vif *, struct ieee80211_sta *, struct ieee80211_key_conf *);
@@ -1335,7 +1315,7 @@ ieee80211_hw_restart_disconnect(struct ieee80211_vif *vif)
for (_linkid = 0; _linkid < nitems((_sta)->link); _linkid++) \
if ( ((_vif)->active_links == 0 /* no MLO */ || \
((_vif)->active_links & BIT(_linkid)) != 0) && \
- (_linksta = link_sta_dereference_protected((_sta), (_linkid))) )
+ (_linksta = link_sta_dereference_check((_sta), (_linkid))) )
/* -------------------------------------------------------------------------- */
@@ -1553,6 +1533,15 @@ ieee80211_iter_chan_contexts_atomic(struct ieee80211_hw *hw,
}
static __inline void
+ieee80211_iter_chan_contexts_mtx(struct ieee80211_hw *hw,
+ void (*iterfunc)(struct ieee80211_hw *, struct ieee80211_chanctx_conf *, void *),
+ void *arg)
+{
+ IMPROVE("XXX LKPI80211 TODO MTX\n");
+ linuxkpi_ieee80211_iterate_chan_contexts(hw, iterfunc, arg);
+}
+
+static __inline void
ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
void (*iterfunc)(void *, struct ieee80211_sta *), void *arg)
{
@@ -2063,7 +2052,7 @@ ieee80211_tx_dequeue_ni(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
static __inline void
ieee80211_update_mu_groups(struct ieee80211_vif *vif,
- u_int _i, uint8_t *ms, uint8_t *up)
+ u_int link_id, const uint8_t *ms, const uint8_t *up)
{
TODO();
}
@@ -2417,7 +2406,7 @@ ieee80211_remove_key(struct ieee80211_key_conf *key)
static __inline struct ieee80211_key_conf *
ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
- struct ieee80211_key_conf *key, int link_id)
+ uint16_t keyidx, uint8_t *key, size_t keylen, int link_id)
{
TODO();
return (NULL);
diff --git a/sys/compat/linuxkpi/common/include/net/netmem.h b/sys/compat/linuxkpi/common/include/net/netmem.h
new file mode 100644
index 000000000000..c8de09a2e8c2
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/net/netmem.h
@@ -0,0 +1,21 @@
+/*-
+ * Copyright (c) 2023-2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _LINUXKPI_NET_NETMEM_H
+#define _LINUXKPI_NET_NETMEM_H
+
+struct page_pool;
+
+struct netmem_desc {
+ struct page_pool *pp;
+};
+
+#define pp_page_to_nmdesc(page) \
+ (_Generic((page), \
+ const struct page *: (const struct netmem_desc *)(page), \
+ struct page *: (struct netmem_desc *)(page)))
+
+#endif /* _LINUXKPI_NET_NETMEM_H */
diff --git a/sys/compat/linuxkpi/common/include/net/page_pool.h b/sys/compat/linuxkpi/common/include/net/page_pool.h
deleted file mode 100644
index 2dc8f74b31f3..000000000000
--- a/sys/compat/linuxkpi/common/include/net/page_pool.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*-
- * 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_NET_PAGE_POOL_H
-#define _LINUXKPI_NET_PAGE_POOL_H
-
-#include <linux/kernel.h> /* pr_debug */
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/netdevice.h>
-
-struct device;
-
-struct page_pool_params {
- struct device *dev;
- uint32_t flags;
- uint32_t order;
- uint32_t pool_size;
- uint32_t max_len;
- uint32_t offset;
- int nid; /* NUMA */
- enum dma_data_direction dma_dir;
- struct napi_struct *napi;
-};
-
-struct page_pool {
-};
-
-#define PP_FLAG_DMA_MAP BIT(0)
-#define PP_FLAG_DMA_SYNC_DEV BIT(1)
-#define PP_FLAG_PAGE_FRAG BIT(2)
-
-static inline struct page_pool *
-page_pool_create(const struct page_pool_params *ppparams)
-{
-
- pr_debug("%s: TODO\n", __func__);
- return (NULL);
-}
-
-static inline void
-page_pool_destroy(struct page_pool *ppool)
-{
-
- pr_debug("%s: TODO\n", __func__);
-}
-
-static inline struct page *
-page_pool_dev_alloc_frag(struct page_pool *ppool, uint32_t *offset,
- size_t size)
-{
-
- pr_debug("%s: TODO\n", __func__);
- return (NULL);
-}
-
-static inline dma_addr_t
-page_pool_get_dma_addr(struct page *page)
-{
-
- pr_debug("%s: TODO\n", __func__);
- return (0);
-}
-
-static inline enum dma_data_direction
-page_pool_get_dma_dir(const struct page_pool *ppool)
-{
-
- pr_debug("%s: TODO\n", __func__);
- return (DMA_BIDIRECTIONAL);
-}
-
-static inline void
-page_pool_put_full_page(struct page_pool *ppool, struct page *page,
- bool allow_direct)
-{
-
- pr_debug("%s: TODO\n", __func__);
-}
-
-static inline int
-page_pool_ethtool_stats_get_count(void)
-{
-
- pr_debug("%s: TODO\n", __func__);
- return (0);
-}
-
-static inline uint8_t *
-page_pool_ethtool_stats_get_strings(uint8_t *x)
-{
-
- pr_debug("%s: TODO\n", __func__);
- return (x);
-}
-
-#endif /* _LINUXKPI_NET_PAGE_POOL_H */
diff --git a/sys/compat/linuxkpi/common/include/net/page_pool/helpers.h b/sys/compat/linuxkpi/common/include/net/page_pool/helpers.h
new file mode 100644
index 000000000000..3469c39c7757
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/net/page_pool/helpers.h
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2023-2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _LINUXKPI_NET_PAGE_POOL_HELPERS_H
+#define _LINUXKPI_NET_PAGE_POOL_HELPERS_H
+
+#include <linux/kernel.h> /* pr_debug */
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <net/page_pool/types.h>
+
+static inline struct page_pool *
+page_pool_create(const struct page_pool_params *ppparams)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+ return (NULL);
+}
+
+static inline void
+page_pool_destroy(struct page_pool *ppool)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+}
+
+static inline struct page *
+page_pool_dev_alloc_frag(struct page_pool *ppool, uint32_t *offset,
+ size_t size)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+ return (NULL);
+}
+
+static inline dma_addr_t
+page_pool_get_dma_addr(struct page *page)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+ return (0);
+}
+
+static inline enum dma_data_direction
+page_pool_get_dma_dir(const struct page_pool *ppool)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+ return (DMA_BIDIRECTIONAL);
+}
+
+static inline void
+page_pool_put_full_page(struct page_pool *ppool, struct page *page,
+ bool allow_direct)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+}
+
+static inline int
+page_pool_ethtool_stats_get_count(void)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+ return (0);
+}
+
+static inline uint8_t *
+page_pool_ethtool_stats_get_strings(uint8_t *x)
+{
+
+ pr_debug("%s: TODO\n", __func__);
+ return (x);
+}
+
+#endif /* _LINUXKPI_NET_PAGE_POOL_HELPERS_H */
diff --git a/sys/compat/linuxkpi/common/include/net/page_pool/types.h b/sys/compat/linuxkpi/common/include/net/page_pool/types.h
new file mode 100644
index 000000000000..6747be50b9b2
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/net/page_pool/types.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2023-2025 Bjoern A. Zeeb
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _LINUXKPI_NET_PAGE_POOL_TYPES_H
+#define _LINUXKPI_NET_PAGE_POOL_TYPES_H
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <net/netmem.h>
+
+struct device;
+struct napi_struct;
+
+struct page_pool_params {
+ struct device *dev;
+ uint32_t flags;
+ uint32_t order;
+ uint32_t pool_size;
+ uint32_t max_len;
+ uint32_t offset;
+ int nid; /* NUMA */
+ enum dma_data_direction dma_dir;
+ struct napi_struct *napi;
+};
+
+struct page_pool {
+};
+
+#define PP_FLAG_DMA_MAP BIT(0)
+#define PP_FLAG_DMA_SYNC_DEV BIT(1)
+#define PP_FLAG_PAGE_FRAG BIT(2)
+
+#endif /* _LINUXKPI_NET_PAGE_POOL_TYPES_H */
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index f0881773726f..8b1f5f0e0399 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -832,6 +832,7 @@ lkpi_lsta_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN],
sta->deflink.smps_mode = IEEE80211_SMPS_OFF;
sta->deflink.bandwidth = IEEE80211_STA_RX_BW_20;
sta->deflink.rx_nss = 1;
+ sta->deflink.sta = sta;
lkpi_sta_sync_from_ni(hw, vif, sta, ni, false);
@@ -2308,6 +2309,10 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
lkpi_80211_mo_change_chanctx(hw, chanctx_conf, changed);
} else {
+ /* The device is no longer idle. */
+ IMPROVE("Once we do multi-vif, only do for 1st chanctx");
+ lkpi_hw_conf_idle(hw, false);
+
error = lkpi_80211_mo_add_chanctx(hw, chanctx_conf);
if (error == 0 || error == EOPNOTSUPP) {
vif->bss_conf.chanreq.oper.chan = chanctx_conf->def.chan;
@@ -2568,12 +2573,6 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
lvif->lvif_bss_synched = false;
LKPI_80211_LVIF_UNLOCK(lvif);
lkpi_lsta_remove(lsta, lvif);
- /*
- * The very last release the reference on the ni for the ni/lsta on
- * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
- * and potentially freed.
- */
- ieee80211_free_node(ni);
/* conf_tx */
@@ -2582,6 +2581,18 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
out:
wiphy_unlock(hw->wiphy);
IEEE80211_LOCK(vap->iv_ic);
+ if (error == 0) {
+ /*
+ * We do this outside the wiphy lock as net80211::node_free() may call
+ * into crypto code to delete keys and we have a recursed on
+ * non-recursive sx panic. Also only do this if we get here w/o error.
+ *
+ * The very last release the reference on the ni for the ni/lsta on
+ * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
+ * and potentially freed.
+ */
+ ieee80211_free_node(ni);
+ }
return (error);
}
@@ -2906,12 +2917,6 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i
lvif->lvif_bss_synched = false;
LKPI_80211_LVIF_UNLOCK(lvif);
lkpi_lsta_remove(lsta, lvif);
- /*
- * The very last release the reference on the ni for the ni/lsta on
- * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
- * and potentially freed.
- */
- ieee80211_free_node(ni);
/* conf_tx */
@@ -2921,6 +2926,18 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i
out:
wiphy_unlock(hw->wiphy);
IEEE80211_LOCK(vap->iv_ic);
+ if (error == EALREADY) {
+ /*
+ * We do this outside the wiphy lock as net80211::node_free() may call
+ * into crypto code to delete keys and we have a recursed on
+ * non-recursive sx panic. Also only do this if we get here w/o error.
+ *
+ * The very last release the reference on the ni for the ni/lsta on
+ * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
+ * and potentially freed.
+ */
+ ieee80211_free_node(ni);
+ }
outni:
return (error);
}
@@ -3069,8 +3086,6 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int
lsta->in_mgd = false;
}
- lkpi_hw_conf_idle(hw, false);
-
/*
* And then:
* - (more packets)?
@@ -3522,12 +3537,6 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
lvif->lvif_bss = NULL;
lvif->lvif_bss_synched = false;
LKPI_80211_LVIF_UNLOCK(lvif);
- /*
- * The very last release the reference on the ni for the ni/lsta on
- * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
- * and potentially freed.
- */
- ieee80211_free_node(ni);
/* conf_tx */
@@ -3537,6 +3546,18 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
out:
wiphy_unlock(hw->wiphy);
IEEE80211_LOCK(vap->iv_ic);
+ if (error == EALREADY) {
+ /*
+ * We do this outside the wiphy lock as net80211::node_free() may call
+ * into crypto code to delete keys and we have a recursed on
+ * non-recursive sx panic. Also only do this if we get here w/o error.
+ *
+ * The very last release the reference on the ni for the ni/lsta on
+ * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
+ * and potentially freed.
+ */
+ ieee80211_free_node(ni);
+ }
outni:
return (error);
}
@@ -6886,17 +6907,23 @@ linuxkpi_ieee80211_iterate_interfaces(struct ieee80211_hw *hw,
if (flags & ~(IEEE80211_IFACE_ITER_NORMAL|
IEEE80211_IFACE_ITER_RESUME_ALL|
IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER|
- IEEE80211_IFACE_ITER_ACTIVE|IEEE80211_IFACE_ITER__ATOMIC)) {
+ IEEE80211_IFACE_ITER_ACTIVE|IEEE80211_IFACE_ITER__ATOMIC|
+ IEEE80211_IFACE_ITER__MTX)) {
ic_printf(lhw->ic, "XXX TODO %s flags(%#x) not yet supported.\n",
__func__, flags);
}
+ if ((flags & IEEE80211_IFACE_ITER__MTX) != 0)
+ lockdep_assert_wiphy(hw->wiphy);
+
active = (flags & IEEE80211_IFACE_ITER_ACTIVE) != 0;
atomic = (flags & IEEE80211_IFACE_ITER__ATOMIC) != 0;
nin_drv = (flags & IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER) != 0;
- if (atomic)
+ if (atomic) {
+ IMPROVE("LKPI_80211_LHW_LVIF_LOCK atomic assume to be rcu?");
LKPI_80211_LHW_LVIF_LOCK(lhw);
+ }
TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
struct ieee80211vap *vap;
@@ -7814,8 +7841,8 @@ lkpi_wiphy_delayed_work_timer(struct timer_list *tl)
{
struct wiphy_delayed_work *wdwk;
- wdwk = from_timer(wdwk, tl, timer);
- wiphy_work_queue(wdwk->wiphy, &wdwk->work);
+ wdwk = timer_container_of(wdwk, tl, timer);
+ wiphy_work_queue(wdwk->wiphy, &wdwk->work);
}
void
@@ -7840,6 +7867,16 @@ linuxkpi_wiphy_delayed_work_cancel(struct wiphy *wiphy,
wiphy_work_cancel(wiphy, &wdwk->work);
}
+void
+linuxkpi_wiphy_delayed_work_flush(struct wiphy *wiphy,
+ struct wiphy_delayed_work *wdwk)
+{
+ lockdep_assert_held(&wiphy->mtx);
+
+ del_timer_sync(&wdwk->timer);
+ wiphy_work_flush(wiphy, &wdwk->work);
+}
+
/* -------------------------------------------------------------------------- */
struct wiphy *
diff --git a/sys/compat/linuxkpi/common/src/linux_80211_macops.c b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
index 1046b753574f..d9e82a6d64ee 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211_macops.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
@@ -42,7 +42,7 @@
if (linuxkpi_debug_80211 & D80211_TRACE_MO) \
printf("LKPI_80211_TRACE_MO %s:%d: %d %d %lu: " fmt "\n", \
__func__, __LINE__, curcpu, curthread->td_tid, \
- jiffies, __VA_ARGS__)
+ jiffies, ##__VA_ARGS__)
#else
#define LKPI_80211_TRACE_MO(...) do { } while(0)
#endif
@@ -102,7 +102,8 @@ lkpi_80211_mo_get_antenna(struct ieee80211_hw *hw, u32 *txs, u32 *rxs)
}
LKPI_80211_TRACE_MO("hw %p", hw);
- error = lhw->ops->get_antenna(hw, txs, rxs);
+ LKPI_80211_TRACE_MO("TODO link/radio_idx");
+ error = lhw->ops->get_antenna(hw, 0, txs, rxs);
out:
return (error);
@@ -121,7 +122,8 @@ lkpi_80211_mo_set_frag_threshold(struct ieee80211_hw *hw, uint32_t frag_th)
}
LKPI_80211_TRACE_MO("hw %p frag_th %u", hw, frag_th);
- error = lhw->ops->set_frag_threshold(hw, frag_th);
+ LKPI_80211_TRACE_MO("TODO link/radio_idx");
+ error = lhw->ops->set_frag_threshold(hw, 0, frag_th);
out:
return (error);
@@ -140,7 +142,8 @@ lkpi_80211_mo_set_rts_threshold(struct ieee80211_hw *hw, uint32_t rts_th)
}
LKPI_80211_TRACE_MO("hw %p rts_th %u", hw, rts_th);
- error = lhw->ops->set_rts_threshold(hw, rts_th);
+ LKPI_80211_TRACE_MO("TODO link/radio_idx");
+ error = lhw->ops->set_rts_threshold(hw, 0, rts_th);
out:
return (error);
@@ -436,7 +439,8 @@ lkpi_80211_mo_config(struct ieee80211_hw *hw, uint32_t changed)
}
LKPI_80211_TRACE_MO("hw %p changed %u", hw, changed);
- error = lhw->ops->config(hw, changed);
+ LKPI_80211_TRACE_MO("TODO link/radio_idx");
+ error = lhw->ops->config(hw, 0, changed);
out:
return (error);
diff --git a/sys/compat/linuxkpi/common/src/linux_acpi.c b/sys/compat/linuxkpi/common/src/linux_acpi.c
index 43783bb8727b..c7d62c745c7e 100644
--- a/sys/compat/linuxkpi/common/src/linux_acpi.c
+++ b/sys/compat/linuxkpi/common/src/linux_acpi.c
@@ -33,6 +33,7 @@
#include <sys/bus.h>
#include <sys/eventhandler.h>
#include <sys/kernel.h>
+#include <sys/power.h>
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
@@ -118,20 +119,32 @@ acpi_evaluate_dsm(ACPI_HANDLE ObjHandle, const guid_t *guid,
}
static void
-linux_handle_power_suspend_event(void *arg __unused)
+linux_handle_power_suspend_event(void *arg __unused, enum power_stype stype)
{
- /*
- * Only support S3 for now.
- * acpi_sleep_event isn't always called so we use power_suspend_early
- * instead which means we don't know what state we're switching to.
- * TODO: Make acpi_sleep_event consistent
- */
- linux_acpi_target_sleep_state = ACPI_STATE_S3;
- pm_suspend_target_state = PM_SUSPEND_MEM;
+ switch (stype) {
+ case POWER_STYPE_SUSPEND_TO_IDLE:
+ /*
+ * XXX: obiwac Not 100% sure this is correct, but
+ * acpi_target_sleep_state does seem to be set to
+ * ACPI_STATE_S3 during s2idle on Linux.
+ */
+ linux_acpi_target_sleep_state = ACPI_STATE_S3;
+ pm_suspend_target_state = PM_SUSPEND_TO_IDLE;
+ break;
+ case POWER_STYPE_SUSPEND_TO_MEM:
+ linux_acpi_target_sleep_state = ACPI_STATE_S3;
+ pm_suspend_target_state = PM_SUSPEND_MEM;
+ break;
+ default:
+ printf("%s: sleep type %d not yet supported\n",
+ __func__, stype);
+ break;
+ }
}
static void
-linux_handle_power_resume_event(void *arg __unused)
+linux_handle_power_resume_event(void *arg __unused,
+ enum power_stype stype __unused)
{
linux_acpi_target_sleep_state = ACPI_STATE_S0;
pm_suspend_target_state = PM_SUSPEND_ON;
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index dcdec0dfcc78..ff0f477ea8cc 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -1171,12 +1171,14 @@ static const struct filterops linux_dev_kqfiltops_read = {
.f_isfd = 1,
.f_detach = linux_file_kqfilter_detach,
.f_event = linux_file_kqfilter_read_event,
+ .f_copy = knote_triv_copy,
};
static const struct filterops linux_dev_kqfiltops_write = {
.f_isfd = 1,
.f_detach = linux_file_kqfilter_detach,
.f_event = linux_file_kqfilter_write_event,
+ .f_copy = knote_triv_copy,
};
static void
@@ -2120,7 +2122,7 @@ add_timer_on(struct timer_list *timer, int cpu)
}
int
-del_timer(struct timer_list *timer)
+timer_delete(struct timer_list *timer)
{
if (callout_stop(&(timer)->callout) == -1)
@@ -2129,7 +2131,7 @@ del_timer(struct timer_list *timer)
}
int
-del_timer_sync(struct timer_list *timer)
+timer_delete_sync(struct timer_list *timer)
{
if (callout_drain(&(timer)->callout) == -1)
@@ -2138,13 +2140,6 @@ del_timer_sync(struct timer_list *timer)
}
int
-timer_delete_sync(struct timer_list *timer)
-{
-
- return (del_timer_sync(timer));
-}
-
-int
timer_shutdown_sync(struct timer_list *timer)
{
diff --git a/sys/compat/linuxkpi/common/src/linux_devres.c b/sys/compat/linuxkpi/common/src/linux_devres.c
index 84f03ba0dd7d..23c91cb5ab2f 100644
--- a/sys/compat/linuxkpi/common/src/linux_devres.c
+++ b/sys/compat/linuxkpi/common/src/linux_devres.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2020-2021 The FreeBSD Foundation
+ * Copyright (c) 2020-2025 The FreeBSD Foundation
*
* This software was developed by Bj\xc3\xb6rn Zeeb under sponsorship from
* the FreeBSD Foundation.
@@ -223,6 +223,30 @@ lkpi_devm_kmalloc_release(struct device *dev __unused, void *p __unused)
/* Nothing to do. Freed with the devres. */
}
+static int
+lkpi_devm_kmalloc_match(struct device *dev __unused, void *p, void *mp)
+{
+ return (p == mp);
+}
+
+void
+lkpi_devm_kfree(struct device *dev, const void *p)
+{
+ void *mp;
+ int error;
+
+ if (p == NULL)
+ return;
+
+ /* I assume Linux simply casts the const away... */
+ mp = __DECONST(void *, p);
+ error = lkpi_devres_destroy(dev, lkpi_devm_kmalloc_release,
+ lkpi_devm_kmalloc_match, mp);
+ if (error != 0)
+ dev_warn(dev, "%s: lkpi_devres_destroy failed with %d\n",
+ __func__, error);
+}
+
struct devres_action {
void *data;
void (*action)(void *);
diff --git a/sys/compat/linuxkpi/common/src/linux_page.c b/sys/compat/linuxkpi/common/src/linux_page.c
index 628af17df853..9cc981b2ba43 100644
--- a/sys/compat/linuxkpi/common/src/linux_page.c
+++ b/sys/compat/linuxkpi/common/src/linux_page.c
@@ -345,6 +345,10 @@ retry:
page = vm_page_grab_iter(vm_obj, pindex, VM_ALLOC_NOCREAT, &pages);
if (page == NULL) {
page = PHYS_TO_VM_PAGE(IDX_TO_OFF(pfn));
+ if (page == NULL) {
+ pctrie_iter_reset(&pages);
+ return (VM_FAULT_SIGBUS);
+ }
if (!vm_page_busy_acquire(page, VM_ALLOC_WAITFAIL)) {
pctrie_iter_reset(&pages);
goto retry;
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index d5bbbea1eb2c..8507a59a8df3 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -67,6 +67,7 @@
#include <linux/mm.h>
#include <linux/io.h>
#include <linux/vmalloc.h>
+#define WANT_NATIVE_PCI_GET_SLOT
#include <linux/pci.h>
#include <linux/compat.h>
@@ -111,6 +112,9 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_iov_uninit, linux_pci_iov_uninit),
DEVMETHOD(pci_iov_add_vf, linux_pci_iov_add_vf),
+ /* Bus interface. */
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+
/* backlight interface */
DEVMETHOD(backlight_update_status, linux_backlight_update_status),
DEVMETHOD(backlight_get_status, linux_backlight_get_status),
@@ -145,6 +149,23 @@ struct linux_dma_priv {
#define DMA_PRIV_LOCK(priv) mtx_lock(&(priv)->lock)
#define DMA_PRIV_UNLOCK(priv) mtx_unlock(&(priv)->lock)
+static void
+lkpi_set_pcim_iomap_devres(struct pcim_iomap_devres *dr, int bar,
+ void *res)
+{
+ dr->mmio_table[bar] = (void *)rman_get_bushandle(res);
+ dr->res_table[bar] = res;
+}
+
+static bool
+lkpi_pci_bar_id_valid(int bar)
+{
+ if (bar < 0 || bar > PCIR_MAX_BAR_0)
+ return (false);
+
+ return (true);
+}
+
static int
linux_pdev_dma_uninit(struct pci_dev *pdev)
{
@@ -289,12 +310,18 @@ lkpi_pci_get_device(uint32_t vendor, uint32_t device, struct pci_dev *odev)
{
struct pci_dev *pdev, *found;
- KASSERT(odev == NULL, ("%s: odev argument not yet supported\n", __func__));
-
found = NULL;
spin_lock(&pci_lock);
list_for_each_entry(pdev, &pci_devices, links) {
- if (pdev->vendor == vendor && pdev->device == device) {
+ /* Walk until we find odev. */
+ if (odev != NULL) {
+ if (pdev == odev)
+ odev = NULL;
+ continue;
+ }
+
+ if ((pdev->vendor == vendor || vendor == PCI_ANY_ID) &&
+ (pdev->device == device || device == PCI_ANY_ID)) {
found = pdev;
break;
}
@@ -316,6 +343,7 @@ lkpi_pci_dev_release(struct device *dev)
static int
lkpifill_pci_dev(device_t dev, struct pci_dev *pdev)
{
+ struct pci_devinfo *dinfo;
int error;
error = kobject_init_and_add(&pdev->dev.kobj, &linux_dev_ktype,
@@ -336,15 +364,24 @@ lkpifill_pci_dev(device_t dev, struct pci_dev *pdev)
pdev->path_name = kasprintf(GFP_KERNEL, "%04d:%02d:%02d.%d",
pci_get_domain(dev), pci_get_bus(dev), pci_get_slot(dev),
pci_get_function(dev));
+
pdev->bus = malloc(sizeof(*pdev->bus), M_DEVBUF, M_WAITOK | M_ZERO);
- /*
- * This should be the upstream bridge; pci_upstream_bridge()
- * handles that case on demand as otherwise we'll shadow the
- * entire PCI hierarchy.
- */
- pdev->bus->self = pdev;
pdev->bus->number = pci_get_bus(dev);
pdev->bus->domain = pci_get_domain(dev);
+
+ /* Check if we have reached the root to satisfy pci_is_root_bus() */
+ dinfo = device_get_ivars(dev);
+ if (dinfo->cfg.pcie.pcie_location != 0 &&
+ dinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT) {
+ pdev->bus->self = NULL;
+ } else {
+ /*
+ * This should be the upstream bridge; pci_upstream_bridge()
+ * handles that case on demand as otherwise we'll shadow the
+ * entire PCI hierarchy.
+ */
+ pdev->bus->self = pdev;
+ }
pdev->dev.bsddev = dev;
pdev->dev.parent = &linux_root_device;
pdev->dev.release = lkpi_pci_dev_release;
@@ -369,7 +406,7 @@ lkpinew_pci_dev_release(struct device *dev)
pdev = to_pci_dev(dev);
if (pdev->root != NULL)
pci_dev_put(pdev->root);
- if (pdev->bus->self != pdev)
+ if (pdev->bus->self != pdev && pdev->bus->self != NULL)
pci_dev_put(pdev->bus->self);
free(pdev->bus, M_DEVBUF);
if (pdev->msi_desc != NULL) {
@@ -449,6 +486,20 @@ lkpi_pci_get_domain_bus_and_slot(int domain, unsigned int bus,
return (pdev);
}
+struct pci_dev *
+lkpi_pci_get_slot(struct pci_bus *pbus, unsigned int devfn)
+{
+ device_t dev;
+ struct pci_dev *pdev;
+
+ dev = pci_find_bsf(pbus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ if (dev == NULL)
+ return (NULL);
+
+ pdev = lkpinew_pci_dev(dev);
+ return (pdev);
+}
+
static int
linux_pci_probe(device_t dev)
{
@@ -525,6 +576,7 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv,
{
struct resource_list_entry *rle;
device_t parent;
+ struct pci_dev *pbus, *ppbus;
uintptr_t rid;
int error;
bool isdrm;
@@ -568,6 +620,27 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv,
list_add(&pdev->links, &pci_devices);
spin_unlock(&pci_lock);
+ /*
+ * Create the hierarchy now as we cannot on demand later.
+ * Take special care of DRM as there is a non-PCI device in the chain.
+ */
+ pbus = pdev;
+ if (isdrm) {
+ pbus = lkpinew_pci_dev(parent);
+ if (pbus == NULL) {
+ error = ENXIO;
+ goto out_dma_init;
+ }
+ }
+ pcie_find_root_port(pbus);
+ if (isdrm)
+ pdev->root = pbus->root;
+ ppbus = pci_upstream_bridge(pbus);
+ while (ppbus != NULL && ppbus != pbus) {
+ pbus = ppbus;
+ ppbus = pci_upstream_bridge(pbus);
+ }
+
if (pdrv != NULL) {
error = pdrv->probe(pdev, id);
if (error)
@@ -575,6 +648,7 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv,
}
return (0);
+/* XXX the cleanup does not match the allocation up there. */
out_probe:
free(pdev->bus, M_DEVBUF);
spin_lock_destroy(&pdev->pcie_cap_lock);
@@ -757,6 +831,9 @@ _lkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen __unused)
struct pci_mmio_region *mmio, *p;
int type;
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
type = pci_resource_type(pdev, bar);
if (type < 0) {
device_printf(pdev->dev.bsddev, "%s: bar %d type %d\n",
@@ -797,6 +874,9 @@ linuxkpi_pci_iomap_range(struct pci_dev *pdev, int bar,
{
struct resource *res;
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
res = _lkpi_pci_iomap(pdev, bar, maxlen);
if (res == NULL)
return (NULL);
@@ -810,9 +890,41 @@ linuxkpi_pci_iomap_range(struct pci_dev *pdev, int bar,
void *
linuxkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
{
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
return (linuxkpi_pci_iomap_range(pdev, bar, 0, maxlen));
}
+void *
+linuxkpi_pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
+{
+ struct pcim_iomap_devres *dr;
+ void *res;
+
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
+ dr = lkpi_pcim_iomap_devres_find(pdev);
+ if (dr == NULL)
+ return (NULL);
+
+ if (dr->res_table[bar] != NULL)
+ return (dr->res_table[bar]);
+
+ res = linuxkpi_pci_iomap(pdev, bar, maxlen);
+ if (res == NULL) {
+ /*
+ * Do not free the devres in case there were
+ * other valid mappings before already.
+ */
+ return (NULL);
+ }
+ lkpi_set_pcim_iomap_devres(dr, bar, res);
+
+ return (res);
+}
+
void
linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res)
{
@@ -864,8 +976,7 @@ linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, const char *nam
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;
+ lkpi_set_pcim_iomap_devres(dr, bar, res);
mappings |= (1 << bar);
}
@@ -1099,8 +1210,9 @@ pci_resource_len(struct pci_dev *pdev, int bar)
return (rle->count);
}
-int
-pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
+static int
+lkpi_pci_request_region(struct pci_dev *pdev, int bar, const char *res_name,
+ bool managed)
{
struct resource *res;
struct pci_devres *dr;
@@ -1108,9 +1220,20 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
int rid;
int type;
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (-EINVAL);
+
+ /*
+ * If the bar is not valid, return success without adding the BAR;
+ * otherwise linuxkpi_pcim_request_all_regions() will error.
+ */
+ if (pci_resource_len(pdev, bar) == 0)
+ return (0);
+ /* Likewise if it is neither IO nor MEM, nothing to do for us. */
type = pci_resource_type(pdev, bar);
if (type < 0)
- return (-ENODEV);
+ return (0);
+
rid = PCIR_BAR(bar);
res = bus_alloc_resource_any(pdev->dev.bsddev, type, &rid,
RF_ACTIVE|RF_SHAREABLE);
@@ -1123,11 +1246,16 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
/*
* It seems there is an implicit devres tracking on these if the device
- * is managed; otherwise the resources are not automatiaclly freed on
- * FreeBSD/LinuxKPI tough they should be/are expected to be by Linux
- * drivers.
+ * is managed (lkpi_pci_devres_find() case); otherwise the resources are
+ * not automatically freed on FreeBSD/LinuxKPI though they should be/are
+ * expected to be by Linux drivers.
+ * Otherwise if we are called from a pcim-function with the managed
+ * argument set, we need to track devres independent of pdev->managed.
*/
- dr = lkpi_pci_devres_find(pdev);
+ if (managed)
+ dr = lkpi_pci_devres_get_alloc(pdev);
+ else
+ dr = lkpi_pci_devres_find(pdev);
if (dr != NULL) {
dr->region_mask |= (1 << bar);
dr->region_table[bar] = res;
@@ -1144,6 +1272,12 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
}
int
+linuxkpi_pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
+{
+ return (lkpi_pci_request_region(pdev, bar, res_name, false));
+}
+
+int
linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name)
{
int error;
@@ -1159,6 +1293,24 @@ linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name)
return (0);
}
+int
+linuxkpi_pcim_request_all_regions(struct pci_dev *pdev, const char *res_name)
+{
+ int bar, error;
+
+ for (bar = 0; bar <= PCIR_MAX_BAR_0; bar++) {
+ error = lkpi_pci_request_region(pdev, bar, res_name, true);
+ if (error != 0) {
+ device_printf(pdev->dev.bsddev, "%s: bar %d res_name '%s': "
+ "lkpi_pci_request_region returned %d\n", __func__,
+ bar, res_name, error);
+ pci_release_regions(pdev);
+ return (error);
+ }
+ }
+ return (0);
+}
+
void
linuxkpi_pci_release_region(struct pci_dev *pdev, int bar)
{
diff --git a/sys/compat/linuxkpi/dummy/include/kunit/skbuff.h b/sys/compat/linuxkpi/dummy/include/kunit/skbuff.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/sys/compat/linuxkpi/dummy/include/kunit/skbuff.h
diff --git a/sys/compat/linuxkpi/dummy/include/kunit/test-bug.h b/sys/compat/linuxkpi/dummy/include/kunit/test-bug.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/sys/compat/linuxkpi/dummy/include/kunit/test-bug.h
diff --git a/sys/compat/linuxkpi/dummy/include/kunit/test.h b/sys/compat/linuxkpi/dummy/include/kunit/test.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/sys/compat/linuxkpi/dummy/include/kunit/test.h