diff options
author | Bjoern A. Zeeb <bz@FreeBSD.org> | 2024-10-28 12:02:56 +0000 |
---|---|---|
committer | Bjoern A. Zeeb <bz@FreeBSD.org> | 2024-10-28 12:05:06 +0000 |
commit | ac1d519c01ca8beb59f27962c7052d09a03f72c8 (patch) | |
tree | fc60faac359efe37b1d91ed85683e8a3203dc4e3 | |
parent | 65691b2dafda23691c3989749def755a98e731ec (diff) | |
download | src-ac1d519c01ca.tar.gz src-ac1d519c01ca.zip |
LinuxKPI: 802.11: adjustments for v6.11 iwlwifi, rtw88 and rtw89
Bring ing the LinuxKPI 802.11 compat bits which are not altering
the mac80211 ops KPI.
* Add various functions for drvier updates.
* Add functions (some compat code to I assume cleanup some
mac80211 ops) emulating chanctx changes doing (*config) updates.
* Adjust structs and defines.
* Deal with an enum growing more than 32 bits in printf.
* Add a mtx to struct wiphy which is exposed to the drivers.
Handle initialization and destruction for now.
* Implementation of wiphy_work and wiphy_delayed_work.
* Set was_assoc for deassoc/deauth in prep_tx_info.
Sponsored by: The FreeBSD Foundation
MFC after: 3 days
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/ieee80211.h | 43 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/nl80211.h | 1 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/include/net/cfg80211.h | 250 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/include/net/mac80211.h | 173 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/src/linux_80211.c | 202 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/src/linux_80211.h | 19 |
6 files changed, 635 insertions, 53 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h index ce6a18f798d1..865d85c6f7b7 100644 --- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h +++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h @@ -42,8 +42,8 @@ extern int linuxkpi_debug_80211; #ifndef D80211_TODO #define D80211_TODO 0x1 #endif -#define TODO(...) if (linuxkpi_debug_80211 & D80211_TODO) \ - printf("%s:%d: XXX LKPI80211 TODO\n", __func__, __LINE__) +#define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ + printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) /* 9.4.2.55 Management MIC element (CMAC-256, GMAC-128, and GMAC-256). */ @@ -138,16 +138,18 @@ enum wlan_ht_cap_sm_ps { #define WLAN_PMKID_LEN 16 #define WLAN_PMK_LEN_SUITE_B_192 48 -#define WLAN_KEY_LEN_WEP40 5 -#define WLAN_KEY_LEN_WEP104 13 -#define WLAN_KEY_LEN_TKIP 32 -#define WLAN_KEY_LEN_CCMP 16 -#define WLAN_KEY_LEN_GCMP 16 -#define WLAN_KEY_LEN_AES_CMAC 16 -#define WLAN_KEY_LEN_GCMP_256 32 -#define WLAN_KEY_LEN_BIP_CMAC_256 32 -#define WLAN_KEY_LEN_BIP_GMAC_128 16 -#define WLAN_KEY_LEN_BIP_GMAC_256 32 +enum ieee80211_key_len { + WLAN_KEY_LEN_WEP40 = 5, + WLAN_KEY_LEN_WEP104 = 13, + WLAN_KEY_LEN_TKIP = 32, + WLAN_KEY_LEN_CCMP = 16, + WLAN_KEY_LEN_GCMP = 16, + WLAN_KEY_LEN_AES_CMAC = 16, + WLAN_KEY_LEN_GCMP_256 = 32, + WLAN_KEY_LEN_BIP_CMAC_256 = 32, + WLAN_KEY_LEN_BIP_GMAC_128 = 16, + WLAN_KEY_LEN_BIP_GMAC_256 = 32, +}; /* 802.11-2020, 9.4.2.55.3, Table 9-185 Subfields of the A-MPDU Parameters field */ enum ieee80211_min_mpdu_start_spacing { @@ -483,9 +485,14 @@ enum ieee80211_back { WLAN_ACTION_ADDBA_REQ = 0, }; +enum ieee80211_sa_query { + WLAN_ACTION_SA_QUERY_RESPONSE = 1, +}; + /* 802.11-2020, Table 9-51-Category values */ enum ieee80211_category { WLAN_CATEGORY_BACK = 3, + WLAN_CATEGORY_SA_QUERY = 8, /* net80211::IEEE80211_ACTION_CAT_SA_QUERY */ }; /* 80211-2020 9.3.3.2 Format of Management frames */ @@ -601,6 +608,7 @@ enum ieee80211_eid { WLAN_EID_TIM = 5, WLAN_EID_COUNTRY = 7, /* IEEE80211_ELEMID_COUNTRY */ WLAN_EID_REQUEST = 10, + WLAN_EID_QBSS_LOAD = 11, /* IEEE80211_ELEMID_BSSLOAD */ WLAN_EID_CHANNEL_SWITCH = 37, WLAN_EID_MEASURE_REPORT = 39, WLAN_EID_HT_CAPABILITY = 45, /* IEEE80211_ELEMID_HTCAP */ @@ -612,6 +620,7 @@ enum ieee80211_eid { WLAN_EID_MULTI_BSSID_IDX = 85, WLAN_EID_EXT_CAPABILITY = 127, WLAN_EID_VHT_CAPABILITY = 191, /* IEEE80211_ELEMID_VHT_CAP */ + WLAN_EID_S1G_TWT = 216, WLAN_EID_VENDOR_SPECIFIC = 221, /* IEEE80211_ELEMID_VENDOR */ }; @@ -760,6 +769,16 @@ enum ieee80211_tx_pwr_interpretation_subfield_enc { IEEE80211_TPE_REG_CLIENT_EIRP_PSD, }; +enum ieee80211_tx_pwr_category_6ghz { + IEEE80211_TPE_CAT_6GHZ_DEFAULT, +}; + +/* 802.11-2020, 9.4.2.27 BSS Load element */ +struct ieee80211_bss_load_elem { + uint16_t sta_count; + uint8_t channel_util; + uint16_t avail_adm_capa; +}; /* net80211: IEEE80211_IS_CTL() */ static __inline bool diff --git a/sys/compat/linuxkpi/common/include/linux/nl80211.h b/sys/compat/linuxkpi/common/include/linux/nl80211.h index 6916957731e2..254ed6e13f5c 100644 --- a/sys/compat/linuxkpi/common/include/linux/nl80211.h +++ b/sys/compat/linuxkpi/common/include/linux/nl80211.h @@ -84,6 +84,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_6GHZ_VLP_CLIENT = BIT(14), NL80211_RRF_NO_6GHZ_AFC_CLIENT = BIT(15), NL80211_RRF_PSD = BIT(16), + NL80211_RRF_ALLOW_6GHZ_VLP_AP = BIT(17), }; #define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS|NL80211_RRF_NO_HT40PLUS) diff --git a/sys/compat/linuxkpi/common/include/net/cfg80211.h b/sys/compat/linuxkpi/common/include/net/cfg80211.h index 7e57ce67cc26..f489e7a7da11 100644 --- a/sys/compat/linuxkpi/common/include/net/cfg80211.h +++ b/sys/compat/linuxkpi/common/include/net/cfg80211.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2023 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * Copyright (c) 2021-2022 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from @@ -39,6 +39,8 @@ #include <linux/netdevice.h> #include <linux/random.h> #include <linux/skbuff.h> +#include <linux/timer.h> +#include <linux/workqueue.h> #include <net/regulatory.h> /* linux_80211.c */ @@ -49,8 +51,8 @@ extern int linuxkpi_debug_80211; #ifndef D80211_IMPROVE #define D80211_IMPROVE 0x2 #endif -#define TODO(...) if (linuxkpi_debug_80211 & D80211_TODO) \ - printf("%s:%d: XXX LKPI80211 TODO\n", __func__, __LINE__) +#define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ + printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) #define IMPROVE(...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \ printf("%s:%d: XXX LKPI80211 IMPROVE\n", __func__, __LINE__) @@ -106,6 +108,11 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_NO_80MHZ = BIT(7), IEEE80211_CHAN_NO_160MHZ = BIT(8), IEEE80211_CHAN_NO_OFDM = BIT(9), + IEEE80211_CHAN_NO_6GHZ_VLP_CLIENT = BIT(10), + IEEE80211_CHAN_NO_6GHZ_AFC_CLIENT = BIT(11), + IEEE80211_CHAN_PSD = BIT(12), + IEEE80211_CHAN_ALLOW_6GHZ_VLP_AP = BIT(13), + IEEE80211_CHAN_CAN_MONITOR = BIT(14), }; #define IEEE80211_CHAN_NO_HT40 (IEEE80211_CHAN_NO_HT40MINUS|IEEE80211_CHAN_NO_HT40PLUS) @@ -275,6 +282,9 @@ struct cfg80211_bss_ies { struct cfg80211_bss { /* XXX TODO */ struct cfg80211_bss_ies *ies; + struct cfg80211_bss_ies *beacon_ies; + + int32_t signal; }; struct cfg80211_chan_def { @@ -283,6 +293,7 @@ struct cfg80211_chan_def { enum nl80211_chan_width width; uint32_t center_freq1; uint32_t center_freq2; + uint16_t punctured; }; struct cfg80211_ftm_responder_stats { @@ -378,11 +389,16 @@ struct cfg80211_match_set { struct cfg80211_scan_request { /* XXX TODO */ - int duration, duration_mandatory, flags; bool no_cck; bool scan_6ghz; + bool duration_mandatory; + int8_t tsf_report_link_id; + uint16_t duration; + uint32_t flags; struct wireless_dev *wdev; struct wiphy *wiphy; + uint64_t scan_start; + uint32_t rates[NUM_NL80211_BANDS]; int ie_len; uint8_t *ie; uint8_t mac_addr[ETH_ALEN], mac_addr_mask[ETH_ALEN]; @@ -774,6 +790,7 @@ struct linuxkpi_ieee80211_regdomain { #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 0x05 #define IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 0x06 #define IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991 0x07 +#define IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC 0x08 #define IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK 0x01 @@ -895,16 +912,26 @@ struct ieee80211_sta_he_6ghz_capa { }; struct ieee80211_eht_mcs_nss_supp_20mhz_only { - uint8_t rx_tx_mcs7_max_nss; - uint8_t rx_tx_mcs9_max_nss; - uint8_t rx_tx_mcs11_max_nss; - uint8_t rx_tx_mcs13_max_nss; + union { + struct { + uint8_t rx_tx_mcs7_max_nss; + uint8_t rx_tx_mcs9_max_nss; + uint8_t rx_tx_mcs11_max_nss; + uint8_t rx_tx_mcs13_max_nss; + }; + uint8_t rx_tx_max_nss[4]; + }; }; struct ieee80211_eht_mcs_nss_supp_bw { - uint8_t rx_tx_mcs9_max_nss; - uint8_t rx_tx_mcs11_max_nss; - uint8_t rx_tx_mcs13_max_nss; + union { + struct { + uint8_t rx_tx_mcs9_max_nss; + uint8_t rx_tx_mcs11_max_nss; + uint8_t rx_tx_mcs13_max_nss; + }; + uint8_t rx_tx_max_nss[3]; + }; }; struct ieee80211_eht_cap_elem_fixed { @@ -1096,7 +1123,7 @@ struct wiphy_iftype_ext_capab { const uint8_t *extended_capabilities_mask; uint8_t extended_capabilities_len; uint16_t eml_capabilities; - + uint16_t mld_capa_and_ops; }; struct tid_config_support { @@ -1133,10 +1160,23 @@ enum wiphy_flags { WIPHY_FLAG_4ADDR_AP = BIT(14), WIPHY_FLAG_4ADDR_STATION = BIT(15), WIPHY_FLAG_SUPPORTS_MLO = BIT(16), + WIPHY_FLAG_DISABLE_WEXT = BIT(17), }; -struct wiphy { +struct wiphy_work; +typedef void (*wiphy_work_fn)(struct wiphy *, struct wiphy_work *); +struct wiphy_work { + struct list_head entry; + wiphy_work_fn fn; +}; +struct wiphy_delayed_work { + struct wiphy_work work; + struct wiphy *wiphy; + struct timer_list timer; +}; +struct wiphy { + struct mutex mtx; struct device *dev; struct mac_address *addresses; int n_addresses; @@ -1185,6 +1225,9 @@ struct wiphy { uint8_t priv[0] __aligned(CACHE_LINE_SIZE); }; +#define lockdep_assert_wiphy(wiphy) \ + lockdep_assert_held(&(wiphy)->mtx) + struct wireless_dev { /* XXX TODO, like ic? */ int iftype; @@ -1249,6 +1292,15 @@ struct cfg80211_ops { struct wiphy *linuxkpi_wiphy_new(const struct cfg80211_ops *, size_t); void linuxkpi_wiphy_free(struct wiphy *wiphy); +void linuxkpi_wiphy_work_queue(struct wiphy *, struct wiphy_work *); +void linuxkpi_wiphy_work_cancel(struct wiphy *, struct wiphy_work *); +void linuxkpi_wiphy_work_flush(struct wiphy *, struct wiphy_work *); +void lkpi_wiphy_delayed_work_timer(struct timer_list *); +void linuxkpi_wiphy_delayed_work_queue(struct wiphy *, + struct wiphy_delayed_work *, unsigned long); +void linuxkpi_wiphy_delayed_work_cancel(struct wiphy *, + struct wiphy_delayed_work *); + int linuxkpi_regulatory_set_wiphy_regd_sync(struct wiphy *wiphy, struct linuxkpi_ieee80211_regdomain *regd); uint32_t linuxkpi_ieee80211_channel_to_frequency(uint32_t, enum nl80211_band); @@ -1300,16 +1352,8 @@ wiphy_dev(struct wiphy *wiphy) return (wiphy->dev); } -#define wiphy_err(_wiphy, _fmt, ...) \ - dev_err((_wiphy)->dev, _fmt, __VA_ARGS__) - -static __inline const struct linuxkpi_ieee80211_regdomain * -wiphy_dereference(struct wiphy *wiphy, - const struct linuxkpi_ieee80211_regdomain *regd) -{ - TODO(); - return (NULL); -} +#define wiphy_dereference(wiphy, p) \ + rcu_dereference_check(p, lockdep_is_held(&(wiphy)->mtx)) static __inline void wiphy_lock(struct wiphy *wiphy) @@ -1661,6 +1705,12 @@ wiphy_ext_feature_set(struct wiphy *wiphy, enum nl80211_ext_feature ef) set_bit(ef, wiphy->ext_features); } +static inline bool +wiphy_ext_feature_isset(struct wiphy *wiphy, enum nl80211_ext_feature ef) +{ + return (test_bit(ef, wiphy->ext_features)); +} + static __inline void * wiphy_net(struct wiphy *wiphy) { @@ -1984,6 +2034,44 @@ cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) return (false); } +static __inline bool +cfg80211_chandef_dfs_usable(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef) +{ + TODO(); + return (false); +} + +static __inline unsigned int +cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef) +{ + TODO(); + return (0); +} + +static inline void +_ieee80211_set_sband_iftype_data(struct ieee80211_supported_band *band, + struct ieee80211_sband_iftype_data *iftype_data, size_t nitems) +{ + band->iftype_data = iftype_data; + band->n_iftype_data = nitems; +} + +static inline const struct ieee80211_sband_iftype_data * +ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *band, + enum nl80211_iftype iftype) +{ + const struct ieee80211_sband_iftype_data *iftype_data; + int i; + + for (i = 0; i < band->n_iftype_data; i++) { + iftype_data = (const void *)&band->iftype_data[i]; + if (iftype_data->types_mask & BIT(iftype)) + return (iftype_data); + } + + return (NULL); +} + static __inline const struct ieee80211_sta_eht_cap * ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *band, enum nl80211_iftype iftype) @@ -1992,8 +2080,122 @@ ieee80211_get_eht_iftype_cap(const struct ieee80211_supported_band *band, return (NULL); } +static inline bool +cfg80211_ssid_eq(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2) +{ + int error; + + if (ssid1 == NULL || ssid2 == NULL) /* Can we KASSERT this? */ + return (false); + + if (ssid1->ssid_len != ssid2->ssid_len) + return (false); + error = memcmp(ssid1->ssid, ssid2->ssid, ssid2->ssid_len); + if (error != 0) + return (false); + return (true); +} + +static inline void +cfg80211_rx_unprot_mlme_mgmt(struct net_device *ndev, const uint8_t *hdr, + uint32_t len) +{ + TODO(); +} + +static inline const struct wiphy_iftype_ext_capab * +cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype iftype) +{ + + TODO(); + return (NULL); +} + +static inline int +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 +wiphy_work_init(struct wiphy_work *wwk, wiphy_work_fn fn) +{ + INIT_LIST_HEAD(&wwk->entry); + wwk->fn = fn; +} + +static inline void +wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + linuxkpi_wiphy_work_queue(wiphy, wwk); +} + +static inline void +wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + linuxkpi_wiphy_work_cancel(wiphy, wwk); +} + +static inline void +wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + linuxkpi_wiphy_work_flush(wiphy, wwk); +} + +static inline void +wiphy_delayed_work_init(struct wiphy_delayed_work *wdwk, wiphy_work_fn fn) +{ + wiphy_work_init(&wdwk->work, fn); + timer_setup(&wdwk->timer, lkpi_wiphy_delayed_work_timer, 0); +} + +static inline void +wiphy_delayed_work_queue(struct wiphy *wiphy, struct wiphy_delayed_work *wdwk, + unsigned long delay) +{ + linuxkpi_wiphy_delayed_work_queue(wiphy, wdwk, delay); +} + +static inline void +wiphy_delayed_work_cancel(struct wiphy *wiphy, struct wiphy_delayed_work *wdwk) +{ + linuxkpi_wiphy_delayed_work_cancel(wiphy, wdwk); +} + +/* -------------------------------------------------------------------------- */ + +#define wiphy_err(_wiphy, _fmt, ...) \ + dev_err((_wiphy)->dev, _fmt, __VA_ARGS__) #define wiphy_info(wiphy, fmt, ...) \ - printf("%s:%d XXX TODO " fmt, __func__, __LINE__, __VA_ARGS__) + dev_info(&(wiphy)->dev, fmt, ##__VA_ARGS__) +#define wiphy_info_once(wiphy, fmt, ...) \ + dev_info_once(&(wiphy)->dev, fmt, ##__VA_ARGS__) #ifndef LINUXKPI_NET80211 #define ieee80211_channel linuxkpi_ieee80211_channel diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h index c3b07b68090a..6dbf07c85bb8 100644 --- a/sys/compat/linuxkpi/common/include/net/mac80211.h +++ b/sys/compat/linuxkpi/common/include/net/mac80211.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2023 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * Copyright (c) 2020-2022 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from @@ -83,6 +83,7 @@ enum mcast_filter_flags { FIF_OTHER_BSS = BIT(4), FIF_PSPOLL = BIT(5), FIF_CONTROL = BIT(6), + FIF_MCAST_ACTION = BIT(7), }; enum ieee80211_bss_changed { @@ -117,6 +118,9 @@ enum ieee80211_bss_changed { BSS_CHANGED_TWT = BIT(28), BSS_CHANGED_UNSOL_BCAST_PROBE_RESP = BIT(30), BSS_CHANGED_EHT_PUNCTURING = BIT(31), + BSS_CHANGED_MLD_VALID_LINKS = BIT_ULL(32), + BSS_CHANGED_MLD_TTLM = BIT_ULL(33), + BSS_CHANGED_TPE = BIT_ULL(34), }; /* 802.11 Figure 9-256 Suite selector format. [OUI(3), SUITE TYPE(1)] */ @@ -167,13 +171,24 @@ enum ieee80211_bss_changed { #define TKIP_PN_TO_IV16(_x) ((uint16_t)(_x & 0xffff)) #define TKIP_PN_TO_IV32(_x) ((uint32_t)((_x >> 16) & 0xffffffff)) -struct ieee80211_sta; +enum ieee80211_neg_ttlm_res { + NEG_TTLM_RES_ACCEPT, + NEG_TTLM_RES_REJECT, +}; + +#define IEEE80211_TTLM_NUM_TIDS 8 +struct ieee80211_neg_ttlm { + uint16_t downlink[IEEE80211_TTLM_NUM_TIDS]; + uint16_t uplink[IEEE80211_TTLM_NUM_TIDS]; +}; /* 802.11-2020 9.4.2.55.3 A-MPDU Parameters field */ #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x3 #define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 #define IEEE80211_HT_AMPDU_PARM_DENSITY (0x7 << IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) +struct ieee80211_sta; + struct ieee80211_ampdu_params { struct ieee80211_sta *sta; enum ieee80211_ampdu_mlme_action action; @@ -217,11 +232,13 @@ struct mac80211_fils_discovery { }; struct ieee80211_chanctx_conf { - /* TODO FIXME */ - int rx_chains_dynamic, rx_chains_static; - bool radar_enabled; struct cfg80211_chan_def def; struct cfg80211_chan_def min_def; + struct cfg80211_chan_def ap; + + uint8_t rx_chains_dynamic; + uint8_t rx_chains_static; + bool radar_enabled; /* Must stay last. */ uint8_t drv_priv[0] __aligned(CACHE_LINE_SIZE); @@ -240,12 +257,39 @@ struct ieee80211_ema_beacons { } bcn[0]; }; +struct ieee80211_chanreq { + struct cfg80211_chan_def oper; +}; + #define WLAN_MEMBERSHIP_LEN (8) #define WLAN_USER_POSITION_LEN (16) +/* + * 802.11ac-2013, 8.4.2.164 VHT Transmit Power Envelope element + * 802.11-???? ? + */ +struct ieee80211_parsed_tpe_eirp { + int8_t power[5]; + uint8_t count; + bool valid; +}; +struct ieee80211_parsed_tpe_psd { + int8_t power[16]; + uint8_t count; + bool valid; +}; +struct ieee80211_parsed_tpe { + /* We see access to [0] so assume at least 2. */ + struct ieee80211_parsed_tpe_eirp max_local[2]; + struct ieee80211_parsed_tpe_eirp max_reg_client[2]; + struct ieee80211_parsed_tpe_psd psd_local[2]; + struct ieee80211_parsed_tpe_psd psd_reg_client[2]; +}; + struct ieee80211_bss_conf { /* TODO FIXME */ struct ieee80211_vif *vif; + struct cfg80211_bss *bss; const uint8_t *bssid; uint8_t addr[ETH_ALEN]; uint8_t link_id; @@ -308,6 +352,7 @@ struct ieee80211_bss_conf { struct mac80211_fils_discovery fils_discovery; struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_vif *mbssid_tx_vif; + struct ieee80211_parsed_tpe tpe; int ack_enabled, bssid_index, bssid_indicator, cqm_rssi_hyst, cqm_rssi_thold, ema_ap, frame_time_rts_th, ftm_responder; int htc_trig_based_pkt_ext; @@ -322,6 +367,7 @@ struct ieee80211_bss_conf { struct ieee80211_channel_switch { /* TODO FIXME */ int block_tx, count, delay, device_timestamp, timestamp; + uint8_t link_id; struct cfg80211_chan_def chandef; }; @@ -444,6 +490,10 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, IEEE80211_HW_SUPPORTS_RC_TABLE, IEEE80211_HW_DETECTS_COLOR_COLLISION, + IEEE80211_HW_DISALLOW_PUNCTURING, + IEEE80211_HW_DISALLOW_PUNCTURING_5GHZ, + IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN, + IEEE80211_HW_HANDLES_QUIET_CSA, /* Keep last. */ NUM_IEEE80211_HW_FLAGS @@ -500,6 +550,7 @@ enum ieee802111_key_flag { IEEE80211_KEY_FLAG_GENERATE_IV_MGMT = BIT(6), IEEE80211_KEY_FLAG_GENERATE_MMIE = BIT(7), IEEE80211_KEY_FLAG_RESERVE_TAILROOM = BIT(8), + IEEE80211_KEY_FLAG_SPP_AMSDU = BIT(9), }; struct ieee80211_key_conf { @@ -569,6 +620,9 @@ enum ieee80211_rx_status_flags { RX_FLAG_SKIP_MONITOR = BIT(26), RX_FLAG_8023 = BIT(27), RX_FLAG_RADIOTAP_TLV_AT_END = BIT(28), + RX_FLAG_MACTIME = BIT(29), + RX_FLAG_MACTIME_IS_RTAP_TS64 = BIT(30), + RX_FLAG_FAILED_PLCP_CRC = BIT(31), }; enum mac80211_rx_encoding { @@ -742,7 +796,9 @@ enum ieee80211_vif_driver_flags { IEEE80211_VIF_BEACON_FILTER = BIT(0), IEEE80211_VIF_SUPPORTS_CQM_RSSI = BIT(1), IEEE80211_VIF_SUPPORTS_UAPSD = BIT(2), - IEEE80211_VIF_DISABLE_SMPS_OVERRIDE = BIT(3), + IEEE80211_VIF_DISABLE_SMPS_OVERRIDE = BIT(3), /* Renamed to IEEE80211_VIF_EML_ACTIVE. */ + IEEE80211_VIF_EML_ACTIVE = BIT(4), + IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW = BIT(5), }; #define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4 @@ -799,6 +855,8 @@ struct ieee80211_vif_chanctx_switch { struct ieee80211_prep_tx_info { u16 duration; bool success; + bool was_assoc; + int link_id; }; /* XXX-BZ too big, over-reduce size to u8, and array sizes to minuimum to fit in skb->cb. */ @@ -813,6 +871,7 @@ struct ieee80211_tx_info { struct { struct ieee80211_tx_rate rates[4]; bool use_rts; + uint8_t antennas:2; struct ieee80211_vif *vif; struct ieee80211_key_conf *hw_key; enum ieee80211_tx_control_flags flags; @@ -1044,6 +1103,8 @@ struct ieee80211_ops { int (*change_vif_links)(struct ieee80211_hw *, struct ieee80211_vif *, u16, u16, struct ieee80211_bss_conf *[IEEE80211_MLD_MAX_NUM_LINKS]); int (*change_sta_links)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, u16, u16); + bool (*can_activate_links)(struct ieee80211_hw *, struct ieee80211_vif *, u16); + enum ieee80211_neg_ttlm_res (*can_neg_ttlm)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_neg_ttlm *); /* #ifdef CONFIG_MAC80211_DEBUGFS */ /* Do not change depending on compile-time option. */ void (*sta_add_debugfs)(struct ieee80211_hw *, struct ieee80211_vif *, struct ieee80211_sta *, struct dentry *); @@ -2052,7 +2113,6 @@ ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *w) static __inline void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) { - linuxkpi_ieee80211_tx_status(hw, skb); } @@ -2060,14 +2120,14 @@ static __inline void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) { IMPROVE(); - ieee80211_tx_status(hw, skb); + linuxkpi_ieee80211_tx_status(hw, skb); } static __inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw, struct sk_buff *skb) { IMPROVE(); - ieee80211_tx_status(hw, skb); + linuxkpi_ieee80211_tx_status(hw, skb); } static __inline void @@ -2370,7 +2430,102 @@ ieee80211_get_eht_iftype_cap_vif(const struct ieee80211_supported_band *band, return (NULL); } +static inline uint32_t +ieee80211_vif_usable_links(const struct ieee80211_vif *vif) +{ + TODO(); + return (1); +} + +static inline bool +ieee80211_vif_link_active(const struct ieee80211_vif *vif, uint8_t link_id) +{ + if (ieee80211_vif_is_mld(vif)) + return (vif->active_links & BIT(link_id)); + return (link_id == 0); +} + +static inline void +ieee80211_set_active_links_async(struct ieee80211_vif *vif, + uint32_t new_active_links) +{ + TODO(); +} + +static inline int +ieee80211_set_active_links(struct ieee80211_vif *vif, + uint32_t active_links) +{ + TODO(); + return (-ENXIO); +} + +static inline void +ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp __unused) +{ + IMPROVE("we notify user space by a vap state change eventually"); + linuxkpi_ieee80211_beacon_loss(vif); +} + #define ieee80211_send_bar(_v, _r, _t, _s) \ linuxkpi_ieee80211_send_bar(_v, _r, _t, _s) +/* -------------------------------------------------------------------------- */ + +int lkpi_80211_update_chandef(struct ieee80211_hw *, + struct ieee80211_chanctx_conf *); + +static inline int +ieee80211_emulate_add_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *chanctx_conf) +{ + int error; + + hw->conf.radar_enabled = chanctx_conf->radar_enabled; + error = lkpi_80211_update_chandef(hw, chanctx_conf); + return (error); +} + +static inline void +ieee80211_emulate_remove_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *chanctx_conf __unused) +{ + hw->conf.radar_enabled = false; + lkpi_80211_update_chandef(hw, NULL); +} + +static inline void +ieee80211_emulate_change_chanctx(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *chanctx_conf, uint32_t changed __unused) +{ + hw->conf.radar_enabled = chanctx_conf->radar_enabled; + lkpi_80211_update_chandef(hw, chanctx_conf); +} + +static inline int +ieee80211_emulate_switch_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif_chanctx_switch *vifs, int n_vifs, + enum ieee80211_chanctx_switch_mode mode __unused) +{ + struct ieee80211_chanctx_conf *chanctx_conf; + int error; + + /* Sanity check. */ + if (n_vifs <= 0) + return (-EINVAL); + if (vifs == NULL || vifs[0].new_ctx == NULL) + return (-EINVAL); + + /* + * What to do if n_vifs > 1? + * Does that make sense for drivers not supporting chanctx? + */ + hw->conf.radar_enabled = vifs[0].new_ctx->radar_enabled; + chanctx_conf = vifs[0].new_ctx; + error = lkpi_80211_update_chandef(hw, chanctx_conf); + return (error); +} + +/* -------------------------------------------------------------------------- */ + #endif /* _LINUXKPI_NET_MAC80211_H */ diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 4171f0789977..9e4c368617b6 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2020-2023 The FreeBSD Foundation + * Copyright (c) 2020-2024 The FreeBSD Foundation * Copyright (c) 2020-2022 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from @@ -895,14 +895,14 @@ lkpi_update_dtim_tsf(struct ieee80211_vif *vif, struct ieee80211_node *ni, if (linuxkpi_debug_80211 & D80211_TRACE) printf("%s:%d [%s:%d] assoc %d aid %d beacon_int %u " "dtim_period %u sync_dtim_count %u sync_tsf %ju " - "sync_device_ts %u bss_changed %#08x\n", + "sync_device_ts %u bss_changed %#010jx\n", __func__, __LINE__, _f, _l, vif->cfg.assoc, vif->cfg.aid, vif->bss_conf.beacon_int, vif->bss_conf.dtim_period, vif->bss_conf.sync_dtim_count, (uintmax_t)vif->bss_conf.sync_tsf, vif->bss_conf.sync_device_ts, - bss_changed); + (uintmax_t)bss_changed); #endif if (vif->bss_conf.beacon_int != ni->ni_intval) { @@ -926,14 +926,14 @@ lkpi_update_dtim_tsf(struct ieee80211_vif *vif, struct ieee80211_node *ni, if (linuxkpi_debug_80211 & D80211_TRACE) printf("%s:%d [%s:%d] assoc %d aid %d beacon_int %u " "dtim_period %u sync_dtim_count %u sync_tsf %ju " - "sync_device_ts %u bss_changed %#08x\n", + "sync_device_ts %u bss_changed %#010jx\n", __func__, __LINE__, _f, _l, vif->cfg.assoc, vif->cfg.aid, vif->bss_conf.beacon_int, vif->bss_conf.dtim_period, vif->bss_conf.sync_dtim_count, (uintmax_t)vif->bss_conf.sync_tsf, vif->bss_conf.sync_device_ts, - bss_changed); + (uintmax_t)bss_changed); #endif return (bss_changed); @@ -1775,6 +1775,7 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i !lsta->in_mgd) { memset(&prep_tx_info, 0, sizeof(prep_tx_info)); prep_tx_info.duration = PREP_TX_INFO_DURATION; + prep_tx_info.was_assoc = true; lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info); lsta->in_mgd = true; } @@ -1809,6 +1810,7 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i if (lsta->in_mgd) { memset(&prep_tx_info, 0, sizeof(prep_tx_info)); prep_tx_info.success = false; + prep_tx_info.was_assoc = true; lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info); lsta->in_mgd = false; } @@ -2162,6 +2164,7 @@ lkpi_sta_run_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, int !lsta->in_mgd) { memset(&prep_tx_info, 0, sizeof(prep_tx_info)); prep_tx_info.duration = PREP_TX_INFO_DURATION; + prep_tx_info.was_assoc = true; lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info); lsta->in_mgd = true; } @@ -2196,6 +2199,7 @@ lkpi_sta_run_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, int if (lsta->in_mgd) { memset(&prep_tx_info, 0, sizeof(prep_tx_info)); prep_tx_info.success = false; + prep_tx_info.was_assoc = true; lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info); lsta->in_mgd = false; } @@ -2300,6 +2304,7 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int !lsta->in_mgd) { memset(&prep_tx_info, 0, sizeof(prep_tx_info)); prep_tx_info.duration = PREP_TX_INFO_DURATION; + prep_tx_info.was_assoc = true; lkpi_80211_mo_mgd_prepare_tx(hw, vif, &prep_tx_info); lsta->in_mgd = true; } @@ -2334,6 +2339,7 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int if (lsta->in_mgd) { memset(&prep_tx_info, 0, sizeof(prep_tx_info)); prep_tx_info.success = false; + prep_tx_info.was_assoc = true; lkpi_80211_mo_mgd_complete_tx(hw, vif, &prep_tx_info); lsta->in_mgd = false; } @@ -5331,18 +5337,158 @@ linuxkpi_ieee80211_get_tid(struct ieee80211_hdr *hdr, bool nonqos_ok) return (tid); } +/* -------------------------------------------------------------------------- */ + +static void +lkpi_wiphy_work(struct work_struct *work) +{ + struct lkpi_wiphy *lwiphy; + struct wiphy *wiphy; + struct wiphy_work *wk; + + lwiphy = container_of(work, struct lkpi_wiphy, wwk); + wiphy = LWIPHY_TO_WIPHY(lwiphy); + + wiphy_lock(wiphy); + + LKPI_80211_LWIPHY_WORK_LOCK(lwiphy); + wk = list_first_entry_or_null(&lwiphy->wwk_list, struct wiphy_work, entry); + /* If there is nothing we do nothing. */ + if (wk == NULL) { + LKPI_80211_LWIPHY_WORK_UNLOCK(lwiphy); + wiphy_unlock(wiphy); + return; + } + list_del_init(&wk->entry); + + /* More work to do? */ + if (!list_empty(&lwiphy->wwk_list)) + schedule_work(work); + LKPI_80211_LWIPHY_WORK_UNLOCK(lwiphy); + + /* Finally call the (*wiphy_work_fn)() function. */ + wk->fn(wiphy, wk); + + wiphy_unlock(wiphy); +} + +void +linuxkpi_wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + struct lkpi_wiphy *lwiphy; + + lwiphy = WIPHY_TO_LWIPHY(wiphy); + + LKPI_80211_LWIPHY_WORK_LOCK(lwiphy); + /* Do not double-queue. */ + if (list_empty(&wwk->entry)) + list_add_tail(&wwk->entry, &lwiphy->wwk_list); + LKPI_80211_LWIPHY_WORK_UNLOCK(lwiphy); + + /* + * See how ieee80211_queue_work() work continues in Linux or if things + * migrate here over time? + * Use a system queue from linux/workqueue.h for now. + */ + queue_work(system_wq, &lwiphy->wwk); +} + +void +linuxkpi_wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + struct lkpi_wiphy *lwiphy; + + lwiphy = WIPHY_TO_LWIPHY(wiphy); + + LKPI_80211_LWIPHY_WORK_LOCK(lwiphy); + /* Only cancel if queued. */ + if (!list_empty(&wwk->entry)) + list_del_init(&wwk->entry); + LKPI_80211_LWIPHY_WORK_UNLOCK(lwiphy); +} + +void +linuxkpi_wiphy_work_flush(struct wiphy *wiphy, struct wiphy_work *wwk) +{ + struct lkpi_wiphy *lwiphy; + struct wiphy_work *wk; + + lwiphy = WIPHY_TO_LWIPHY(wiphy); + LKPI_80211_LWIPHY_WORK_LOCK(lwiphy); + /* If wwk is unset, flush everything; called when wiphy is shut down. */ + if (wwk != NULL && list_empty(&wwk->entry)) { + LKPI_80211_LWIPHY_WORK_UNLOCK(lwiphy); + return; + } + + while (!list_empty(&lwiphy->wwk_list)) { + + wk = list_first_entry(&lwiphy->wwk_list, struct wiphy_work, + entry); + list_del_init(&wk->entry); + LKPI_80211_LWIPHY_WORK_UNLOCK(lwiphy); + wk->fn(wiphy, wk); + LKPI_80211_LWIPHY_WORK_LOCK(lwiphy); + if (wk == wwk) + break; + } + LKPI_80211_LWIPHY_WORK_UNLOCK(lwiphy); +} + +void +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); +} + +void +linuxkpi_wiphy_delayed_work_queue(struct wiphy *wiphy, + struct wiphy_delayed_work *wdwk, unsigned long delay) +{ + if (delay == 0) { + /* Run right away. */ + del_timer(&wdwk->timer); + wiphy_work_queue(wiphy, &wdwk->work); + } else { + wdwk->wiphy = wiphy; + mod_timer(&wdwk->timer, jiffies + delay); + } +} + +void +linuxkpi_wiphy_delayed_work_cancel(struct wiphy *wiphy, + struct wiphy_delayed_work *wdwk) +{ + del_timer_sync(&wdwk->timer); + wiphy_work_cancel(wiphy, &wdwk->work); +} + +/* -------------------------------------------------------------------------- */ + struct wiphy * linuxkpi_wiphy_new(const struct cfg80211_ops *ops, size_t priv_len) { struct lkpi_wiphy *lwiphy; + struct wiphy *wiphy; lwiphy = kzalloc(sizeof(*lwiphy) + priv_len, GFP_KERNEL); if (lwiphy == NULL) return (NULL); lwiphy->ops = ops; - /* XXX TODO */ - return (LWIPHY_TO_WIPHY(lwiphy)); + LKPI_80211_LWIPHY_WORK_LOCK_INIT(lwiphy); + INIT_LIST_HEAD(&lwiphy->wwk_list); + INIT_WORK(&lwiphy->wwk, lkpi_wiphy_work); + + wiphy = LWIPHY_TO_WIPHY(lwiphy); + + mutex_init(&wiphy->mtx); + TODO(); + + return (wiphy); } void @@ -5353,7 +5499,12 @@ linuxkpi_wiphy_free(struct wiphy *wiphy) if (wiphy == NULL) return; + linuxkpi_wiphy_work_flush(wiphy, NULL); + mutex_destroy(&wiphy->mtx); + lwiphy = WIPHY_TO_LWIPHY(wiphy); + LKPI_80211_LWIPHY_WORK_LOCK_DESTROY(lwiphy); + kfree(lwiphy); } @@ -6290,6 +6441,43 @@ linuxkpi_cfg80211_bss_flush(struct wiphy *wiphy) /* -------------------------------------------------------------------------- */ +/* + * hw->conf get initialized/set in various places for us: + * - linuxkpi_ieee80211_alloc_hw(): flags + * - linuxkpi_ieee80211_ifattach(): chandef + * - lkpi_ic_vap_create(): listen_interval + * - lkpi_ic_set_channel(): chandef, flags + */ + +int lkpi_80211_update_chandef(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *new) +{ + struct cfg80211_chan_def *cd; + uint32_t changed; + int error; + + changed = 0; + if (new == NULL || new->def.chan == NULL) + cd = NULL; + else + cd = &new->def; + + if (cd && cd->chan != hw->conf.chandef.chan) { + /* Copy; the chan pointer is fine and will stay valid. */ + hw->conf.chandef = *cd; + changed |= IEEE80211_CONF_CHANGE_CHANNEL; + } + IMPROVE("IEEE80211_CONF_CHANGE_PS, IEEE80211_CONF_CHANGE_POWER"); + + if (changed == 0) + return (0); + + error = lkpi_80211_mo_config(hw, changed); + return (error); +} + +/* -------------------------------------------------------------------------- */ + MODULE_VERSION(linuxkpi_wlan, 1); MODULE_DEPEND(linuxkpi_wlan, linuxkpi, 1, 1, 1); MODULE_DEPEND(linuxkpi_wlan, wlan, 1, 1, 1); diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h index 7675a8b6cebf..b6ac3e85f80f 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.h +++ b/sys/compat/linuxkpi/common/src/linux_80211.h @@ -205,7 +205,7 @@ struct lkpi_hw { /* name it mac80211_sc? */ TAILQ_HEAD(, lkpi_vif) lvif_head; struct sx lvif_sx; - struct sx sx; + struct sx sx; /* XXX-BZ Can this be wiphy->mtx in the future? */ struct mtx txq_mtx; uint32_t txq_generation[IEEE80211_NUM_ACS]; @@ -284,12 +284,29 @@ struct lkpi_chanctx { struct lkpi_wiphy { const struct cfg80211_ops *ops; + struct work_struct wwk; + struct list_head wwk_list; + struct mtx wwk_mtx; + /* Must be last! */ struct wiphy wiphy __aligned(CACHE_LINE_SIZE); }; #define WIPHY_TO_LWIPHY(_wiphy) container_of(_wiphy, struct lkpi_wiphy, wiphy) #define LWIPHY_TO_WIPHY(_lwiphy) (&(_lwiphy)->wiphy) +#define LKPI_80211_LWIPHY_WORK_LOCK_INIT(_lwiphy) \ + mtx_init(&(_lwiphy)->wwk_mtx, "lwiphy-work", NULL, MTX_DEF); +#define LKPI_80211_LWIPHY_WORK_LOCK_DESTROY(_lwiphy) \ + mtx_destroy(&(_lwiphy)->wwk_mtx) +#define LKPI_80211_LWIPHY_WORK_LOCK(_lwiphy) \ + mtx_lock(&(_lwiphy)->wwk_mtx) +#define LKPI_80211_LWIPHY_WORK_UNLOCK(_lwiphy) \ + mtx_unlock(&(_lwiphy)->wwk_mtx) +#define LKPI_80211_LWIPHY_WORK_LOCK_ASSERT(_lwiphy) \ + mtx_assert(&(_lwiphy)->wwk_mtx, MA_OWNED) +#define LKPI_80211_LWIPHY_WORK_UNLOCK_ASSERT(_lwiphy) \ + mtx_assert(&(_lwiphy)->wwk_mtx, MA_NOTOWNED) + #define LKPI_80211_LHW_LOCK_INIT(_lhw) \ sx_init_flags(&(_lhw)->sx, "lhw", SX_RECURSE); #define LKPI_80211_LHW_LOCK_DESTROY(_lhw) \ |