diff --git a/AGENTS.md b/AGENTS.md index f3f43bf54a..c2cbf83173 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -399,6 +399,18 @@ be migrated to either: This is a follow-up refactor — the tree is permanent, just currently gitignored by size. The `local/reference/` directory is **NOT** optional. +## LANGUAGE POLICY (ABSOLUTE) + +**In code created by Red Bear OS, whenever possible and sometimes when impossible, code must be in Rust.** Pure assembly is accepted. Other languages (C, C++, Python, shell beyond build glue) are only permitted with prior operator consent. + +**What this means:** +- New drivers, daemons, libraries, and utilities: **Rust only** +- Inline assembly in the kernel: **accepted** (there is no Rust alternative for `sti; monitor; mwait`) +- Modifying legacy C code that was inherited from upstream Redox: **only to fix compilation or bugs, never to add new logic**. New logic goes in a new Rust module and calls the legacy C via minimal FFI. +- C header files that serve as the FFI boundary between Rust and inherited C: **acceptable** but must not grow — the types live in Rust, the C header just exposes them. + +**Enforcement:** Any new file ending in `.c` under `local/recipes/*/source/` or `local/sources/*/` must justify its existence with an operator-approved exemption. The default answer is Rust. + ## DURABILITY POLICY Every change to an upstream-owned source tree (anything under `recipes/*/source/`) **must** be diff --git a/local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md b/local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md index 7d012b3f95..f8778b2ca5 100644 --- a/local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md +++ b/local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md @@ -1,8 +1,8 @@ # Red Bear OS — `pci-spawner` → `driver-manager` Migration Plan -**Document status:** v4.6 canonical planning authority (supersedes v4.5: v4.6 adds the contract tests for `pci_register_error_handler` on linux-kpi (env-missing, malformed-fd, double-register) and notes the open "Driver-level `Driver::on_error` adoption by shipped drivers" item as a follow-up for the redbear-iwlwifi Rust port rather than touching in-progress migration code. v4.5 in turn superseded v4.4: v4.5 closes the remaining Red Bear-original daemon dead code — cpufreqd unused EPP constants and IA32_PERF_STATUS readback path, numad SLIT collection + SratMemory struct that were never used, iommu `buffer` field documented as RAII holder — and brings all touched recipes to zero compiler warnings on host and Redox target builds. v4.4 in turn superseded v4.3: v4.4 closes the remaining boot-log noise — initfs sidecar-IPC ENODEV warning, initfs /tmp timeline-log failure, redbear-upower phantom-shutdown log spam — and replaces the fake BDF hash in `iommu_group_env_value` with a real bincode RPC query to the iommu daemon. v4.3 in turn superseded v4.2: v4.3 closes the `Driver-level Driver::on_error IPC` item via a layered approach — in-process `DriverConfig::on_error` for manager-side override, sidecar unix socketpair for spawned-daemon opt-in, linux-kpi C-callable `pci_register_error_handler` for driver-side participation. v4.2 in turn superseded v4.1: v4.2 closes the `acpid pci_fd` item and adds per-vendor firmware recipes. v4.1 in turn superseded v4.0: v4.1 closes the three P3 items the v4.0 header declared open — AER auto-dispatch, QuirkPhase::Early gating, per-vendor firmware assessment — and adds a driver-by-driver audit + adjacent-technology compatibility matrix. v4.0 in turn superseded v3.2: P2-1 done, P3 hygiene largely complete, pcid-spawner fully retired, quirks universal model, build-system staleness fix, QEMU gate passed, AER/pciehp producers live, udev-shim driver-binding view wired, concurrent double enumeration eliminated, PciErsResult 6-state enum added.) +**Document status:** v4.7 canonical planning authority (supersedes v4.6: v4.7 adds nine integration tests for the `redbear-hid-core` HID report-descriptor parser — 3-button mouse, keyboard boot descriptor, nested collections, error paths, and bit-offset bookkeeping — pinning the Linux-faithful semantics that the boot HID stack depends on. v4.6 in turn superseded v4.5: v4.6 adds the contract tests for `pci_register_error_handler` on linux-kpi (env-missing, malformed-fd, double-register) and notes the open "Driver-level `Driver::on_error` adoption by shipped drivers" item as a follow-up for the redbear-iwlwifi Rust port rather than touching in-progress migration code. v4.5 in turn superseded v4.4: v4.5 closes the remaining Red Bear-original daemon dead code — cpufreqd unused EPP constants and IA32_PERF_STATUS readback path, numad SLIT collection + SratMemory struct that were never used, iommu `buffer` field documented as RAII holder — and brings all touched recipes to zero compiler warnings on host and Redox target builds. v4.4 in turn superseded v4.3: v4.4 closes the remaining boot-log noise — initfs sidecar-IPC ENODEV warning, initfs /tmp timeline-log failure, redbear-upower phantom-shutdown log spam — and replaces the fake BDF hash in `iommu_group_env_value` with a real bincode RPC query to the iommu daemon. v4.3 in turn superseded v4.2: v4.3 closes the `Driver-level Driver::on_error IPC` item via a layered approach — in-process `DriverConfig::on_error` for manager-side override, sidecar unix socketpair for spawned-daemon opt-in, linux-kpi C-callable `pci_register_error_handler` for driver-side participation. v4.2 in turn superseded v4.1: v4.2 closes the `acpid pci_fd` item and adds per-vendor firmware recipes. v4.1 in turn superseded v4.0: v4.1 closes the three P3 items the v4.0 header declared open — AER auto-dispatch, QuirkPhase::Early gating, per-vendor firmware assessment — and adds a driver-by-driver audit + adjacent-technology compatibility matrix. v4.0 in turn superseded v3.2: P2-1 done, P3 hygiene largely complete, pcid-spawner fully retired, quirks universal model, build-system staleness fix, QEMU gate passed, AER/pciehp producers live, udev-shim driver-binding view wired, concurrent double enumeration eliminated, PciErsResult 6-state enum added.) **Generated:** 2026-07-20 -**Last reviewed:** 2026-07-24 (v4.6: linux-kpi pci_register_error_handler contract tests) +**Last reviewed:** 2026-07-24 (v4.7: redbear-hid-core parser integration tests) **Toolchain:** Rust nightly-2026-05-24 (edition 2024) **Architecture:** Microkernel OS in Rust (Redox fork) **Cross-reference baseline:** Linux kernel 7.1 at commit `ab9de95c9` (`local/reference/linux-7.1/`), CachyOS (`local/reference/cachyos/` — linux-cachyos `0001-cachyos-base-all.patch` 6.17.9 + desktop ISO 260628) diff --git a/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/ieee80211.h b/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/ieee80211.h index 019678b965..d634d33eae 100644 --- a/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/ieee80211.h +++ b/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/ieee80211.h @@ -6,127 +6,6 @@ #define IEEE80211_MAX_SSID_LEN 32 #define IEEE80211_NUM_ACS 4 -/* Frame types (IEEE 802.11) */ -#define IEEE80211_FTYPE_MGMT 0x0000 -#define IEEE80211_FTYPE_CTL 0x0004 -#define IEEE80211_FTYPE_DATA 0x0008 - -#define IEEE80211_STYPE_ASSOC_REQ 0x0000 -#define IEEE80211_STYPE_ASSOC_RESP 0x0010 -#define IEEE80211_STYPE_REASSOC_REQ 0x0020 -#define IEEE80211_STYPE_REASSOC_RESP 0x0030 -#define IEEE80211_STYPE_PROBE_REQ 0x0040 -#define IEEE80211_STYPE_PROBE_RESP 0x0050 -#define IEEE80211_STYPE_BEACON 0x0080 -#define IEEE80211_STYPE_AUTH 0x00b0 -#define IEEE80211_STYPE_DEAUTH 0x00c0 -#define IEEE80211_STYPE_ACTION 0x00d0 - -#define IEEE80211_STYPE_QOS_DATA 0x0080 - -/* Capability bits */ -#define WLAN_CAPABILITY_ESS (1U << 0) -#define WLAN_CAPABILITY_IBSS (1U << 1) -#define WLAN_CAPABILITY_PRIVACY (1U << 4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE (1U << 5) -#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1U << 10) - -/* Reason codes (IEEE 802.11 §9.4.1.7) */ -#define WLAN_REASON_UNSPECIFIED 1 -#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 -#define WLAN_REASON_DEAUTH_LEAVING 3 -#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 -#define WLAN_REASON_DISASSOC_AP_BUSY 5 - -/* Status codes */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 - -/* Cipher suites */ -#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 -#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 -#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 -#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 -#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 -#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0C -#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC0D - -/* AID range */ -#define IEEE80211_MAX_AID 2007 - -/* Max frame size */ -#define IEEE80211_MAX_DATA_LEN 2304 -#define IEEE80211_MAX_FRAME_LEN 2352 - -/* Key indices */ -#define NUM_DEFAULT_KEYS 4 -#define NUM_DEFAULT_MGMT_KEYS 2 -#define NUM_DEFAULT_BEACON_KEYS 2 - -/* Extended capabilities */ -#define WLAN_EID_SSID 0 -#define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_DS_PARAMS 3 -#define WLAN_EID_CF_PARAMS 4 -#define WLAN_EID_TIM 5 -#define WLAN_EID_IBSS_PARAMS 6 -#define WLAN_EID_COUNTRY 7 -#define WLAN_EID_REQUEST 10 -#define WLAN_EID_BSS_LOAD 11 -#define WLAN_EID_PWR_CAPABILITY 33 -#define WLAN_EID_SUPPORTED_CHANNELS 36 -#define WLAN_EID_CHANNEL_SWITCH 37 -#define WLAN_EID_MEASURE_REPORT 39 -#define WLAN_EID_QUIET 40 -#define WLAN_EID_IBSS_DFS 41 -#define WLAN_EID_ERP_INFO 42 -#define WLAN_EID_TSPEC 43 -#define WLAN_EID_TCLAS 44 -#define WLAN_EID_SCHEDULE 45 -#define WLAN_EIDChallengeText 46 -#define WLAN_EID_PWR_CONSTRAINT 32 -#define WLAN_EID_MOBILITY_DOMAIN 54 -#define WLAN_EID_FAST_BSS_TRANSITION 55 -#define WLAN_EID_TIMEOUT_INTERVAL 56 -#define WLAN_EID_RIC_DATA 57 -#define WLAN_EID_DSE_REGISTERED_LOCATION 60 -#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59 -#define WLAN_EID_EXT_CHANSWITCH_ANN 60 -#define WLAN_EID_HT_CAPABILITY 45 -#define WLAN_EID_HT_OPERATION 61 -#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 -#define WLAN_EID_BSS_COEX_2040 72 -#define WLAN_EID_EXT_CAPABILITY 127 -#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90 -#define WLAN_EID_MESH_CONFIG 113 -#define WLAN_EID_MESH_ID 114 -#define WLAN_EID_PEER_MGMT 117 -#define WLAN_EID_MESH_AWAKE_WINDOW 119 -#define WLAN_EID_BEACON_TIMING 120 -#define WLAN_EID_S1G_BCN_COMPAT 213 -#define WLAN_EID_S1G_CAPABILITIES 217 -#define WLAN_EID_S1G_OPERATION 232 - -/* HE/EHT element IDs (extended) */ -#define WLAN_EID_EXTENSION 255 -#define WLAN_EID_EXT_HE_CAPABILITY 35 -#define WLAN_EID_EXT_HE_OPERATION 36 -#define WLAN_EID_EXT_UORA 38 -#define WLAN_EID_EXT_EHT_CAPABILITY 108 -#define WLAN_EID_EXT_EHT_OPERATION 109 -#define WLAN_EID_EXT_MULTI_LINK 109 - -/* MLO (Multi-Link Operation) types */ -#define WLAN_EID_VENDOR_SPECIFIC 221 - -/* Band definitions */ -enum ieee80211_band_local { - IEEE80211_BAND_2GHZ = 0, - IEEE80211_BAND_5GHZ = 1, - IEEE80211_BAND_6GHZ = 2, -}; - struct ieee80211_channel { u32 band; u16 center_freq; @@ -136,7 +15,6 @@ struct ieee80211_channel { s8 max_reg_power; s8 max_antenna_gain; bool beacon_found; - u32 max_bandwidth_khz; }; struct ieee80211_rate { @@ -146,38 +24,4 @@ struct ieee80211_rate { u16 hw_value_short; }; -struct ieee80211_sta_ht_cap { - u16 cap; - bool ht_supported; - u8 ampdu_factor; - u16 ampdu_density; - struct { - u8 rx_highest; - u8 rx_mcs_mask[10]; - } mcs; -}; - -struct ieee80211_sta_vht_cap { - u32 cap; - bool vht_supported; - u8 vht_mcs_rx_highest; - u8 vht_mcs_tx_highest; -}; - -struct ieee80211_sta_he_cap { - bool he_supported; - u8 mac_cap_info[6]; - u8 phy_cap_info[11]; - u8 mcs_nss_rx[4]; - u8 mcs_nss_tx[4]; -}; - -struct ieee80211_sta_eht_cap { - bool eht_supported; - u8 mac_cap_info[2]; - u8 phy_cap_info[9]; - u8 mcs_nss_rx[4]; - u8 mcs_nss_tx[4]; -}; - #endif diff --git a/local/recipes/drivers/linux-kpi/source/src/c_headers/net/mac80211.h b/local/recipes/drivers/linux-kpi/source/src/c_headers/net/mac80211.h index 5d2a8ae0ec..38bf6e2012 100644 --- a/local/recipes/drivers/linux-kpi/source/src/c_headers/net/mac80211.h +++ b/local/recipes/drivers/linux-kpi/source/src/c_headers/net/mac80211.h @@ -18,88 +18,39 @@ #define IEEE80211_CONF_CHANGE_POWER (1U << 5) #define IEEE80211_CONF_CHANGE_CHANNEL (1U << 6) -#define IEEE80211_MLD_MAX_NUM_LINKS 15 - -enum ieee80211_band { - NL80211_BAND_2GHZ = 0, - NL80211_BAND_5GHZ = 1, - NL80211_BAND_6GHZ = 2, - NL80211_BAND_60GHZ = 3, -}; - -enum nl80211_chan_width { - NL80211_CHAN_WIDTH_20_NOHT = 0, - NL80211_CHAN_WIDTH_20 = 1, - NL80211_CHAN_WIDTH_40 = 2, - NL80211_CHAN_WIDTH_80 = 3, - NL80211_CHAN_WIDTH_80P80 = 4, - NL80211_CHAN_WIDTH_160 = 5, - NL80211_CHAN_WIDTH_320 = 13, -}; - -#define IEEE80211_HT_CAP_LDPC_CODING (1U << 0) -#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 (1U << 1) -#define IEEE80211_HT_CAP_SGI_20 (1U << 2) -#define IEEE80211_HT_CAP_SGI_40 (1U << 3) -#define IEEE80211_VHT_CAP_MAX_MPDU_11454 (3U << 0) -#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ (1U << 2) - -enum ieee80211_sta_state { - IEEE80211_STA_NOTEXIST, - IEEE80211_STA_NONE, - IEEE80211_STA_AUTH, - IEEE80211_STA_ASSOC, - IEEE80211_STA_AUTHORIZED, -}; - -enum set_key_cmd { SET_KEY, DISABLE_KEY }; - -enum ieee80211_ampdu_mlme_action { - IEEE80211_AMPDU_RX_START = 0, - IEEE80211_AMPDU_RX_STOP = 1, - IEEE80211_AMPDU_TX_START = 2, - IEEE80211_AMPDU_TX_STOP_CONT = 3, - IEEE80211_AMPDU_TX_STOP_FLUSH = 4, - IEEE80211_AMPDU_TX_START_NEW = 5, - IEEE80211_AMPDU_TX_OPERATIONAL = 6, -}; - -#define IEEE80211_KEY_FLAG_GENERATE_IV (1U << 0) -#define IEEE80211_KEY_FLAG_GENERATE_MMIC (1U << 1) -#define IEEE80211_KEY_FLAG_PAIRWISE (1U << 2) - -#define BSS_CHANGED_ASSOC (1U << 0) -#define BSS_CHANGED_BSSID (1U << 1) -#define BSS_CHANGED_ERP_CTS_PROT (1U << 2) -#define BSS_CHANGED_HT (1U << 3) -#define BSS_CHANGED_BASIC_RATES (1U << 4) -#define BSS_CHANGED_BEACON_INT (1U << 5) -#define BSS_CHANGED_BANDWIDTH (1U << 6) -#define BSS_CHANGED_QOS (1U << 8) -#define BSS_CHANGED_TXPOWER (1U << 12) -#define BSS_CHANGED_HE_BSS_COLOR (1U << 17) -#define BSS_CHANGED_EHT_PUNCTURING (1U << 23) - -struct ieee80211_chanctx_conf { - enum nl80211_chan_width radar_detect_width; - bool driver_present; - u8 rx_chains_dynamic, rx_chains_static; - struct ieee80211_channel *chan; -}; - -struct ieee80211_txq { - struct ieee80211_sta *sta; - void *drv_priv; - u8 ac; - u8 tid; -}; - -struct ieee80211_key_conf { - u32 cipher; +struct ieee80211_conf { u32 flags; - u8 keyidx; - u8 keylen; - u8 key[32]; + int power_level; + int dynamic_ps_timeout; + struct { + u32 center_freq; + u16 band; + struct ieee80211_channel *channel; + } chandef; + u32 listen_interval; +}; + +struct ieee80211_hw { + struct wiphy *wiphy; + const struct ieee80211_ops *ops; + void *priv; + int registered; + u32 extra_tx_headroom; + u16 queues; + struct ieee80211_conf conf; +}; + +struct ieee80211_vif { + u8 addr[6]; + void *drv_priv; + u32 type; + bool cfg_assoc; +}; + +struct ieee80211_sta { + u8 addr[6]; + void *drv_priv; + u16 aid; }; struct ieee80211_bss_conf { @@ -113,176 +64,70 @@ struct ieee80211_bss_conf { u32 center_freq; u16 band; struct ieee80211_channel *channel; - enum nl80211_chan_width width; } chandef; - bool he_support; - bool eht_support; - u8 he_bss_color; - u8 link_id; - struct ieee80211_chanctx_conf *chanctx; -}; - -struct ieee80211_link { - struct ieee80211_bss_conf conf; - u8 link_id; - bool active; - u8 addr[6]; -}; - -struct ieee80211_link_sta { - u8 addr[6]; - void *drv_priv; - bool he_capa_present; - bool eht_capa_present; - u32 ht_cap; - u32 vht_cap; -}; - -struct ieee80211_sta { - u8 addr[6]; - u8 mld_addr[6]; - void *drv_priv; - u16 aid; - bool wme; - bool mfp; - bool tdls; - bool is_mld; - u16 valid_links; - struct ieee80211_link_sta deflink; - struct ieee80211_link_sta *link[IEEE80211_MLD_MAX_NUM_LINKS + 1]; -}; - -struct ieee80211_vif { - u8 addr[6]; - void *drv_priv; - u32 type; - bool cfg_assoc; - bool is_mld; - u16 valid_links; - struct ieee80211_link deflink; - struct ieee80211_link *link[IEEE80211_MLD_MAX_NUM_LINKS + 1]; - struct ieee80211_bss_conf bss_conf; }; struct ieee80211_rx_status { - u64 mactime; u16 freq; u32 band; s8 signal; s8 noise; u8 rate_idx; - u8 link_id; u32 flag; u8 antenna; u32 rx_flags; - u32 encoding; - u8 nss; - u8 bw; }; -struct ieee80211_conf { - u32 flags; - int power_level; - int dynamic_ps_timeout; - struct { - u32 center_freq; - u16 band; - struct ieee80211_channel *channel; - enum nl80211_chan_width width; - } chandef; - u32 listen_interval; +enum ieee80211_sta_state { + IEEE80211_STA_NOTEXIST, + IEEE80211_STA_NONE, + IEEE80211_STA_AUTH, + IEEE80211_STA_ASSOC, + IEEE80211_STA_AUTHORIZED, }; -struct ieee80211_hw { - struct wiphy *wiphy; - const struct ieee80211_ops *ops; - void *priv; - int registered; - u32 extra_tx_headroom; - u16 queues; - u8 max_rx_aggregation_subframes; - u8 max_tx_aggregation_subframes; - struct ieee80211_conf conf; -}; - -struct ieee80211_tx_rate { - u8 idx; - u8 count; - u8 flags; -}; - -struct ieee80211_tx_info { - u32 flags; - u32 band; - struct ieee80211_tx_rate rates[4]; - u8 antenna; - u8 ack_signal; - bool is_data; +enum set_key_cmd { + SET_KEY, + DISABLE_KEY, }; struct ieee80211_ops { - void (*tx)(struct ieee80211_hw *hw, struct ieee80211_txq *txq); - void (*wake_tx_queue)(struct ieee80211_hw *hw, struct ieee80211_txq *txq); + void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); int (*start)(struct ieee80211_hw *hw); void (*stop)(struct ieee80211_hw *hw); int (*add_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - int (*change_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 new_type, bool p2p); void (*remove_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int (*config)(struct ieee80211_hw *hw, u32 changed); void (*bss_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, u64 changed); - void (*vif_cfg_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 changed); - void (*link_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf, u64 changed); + struct ieee80211_bss_conf *info, u32 changed); int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state); - void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); + struct key_params *key); int (*ampdu_action)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, enum ieee80211_ampdu_mlme_action action, - struct ieee80211_txq *txq); - bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw, struct sk_buff *head, struct sk_buff *skb); + struct ieee80211_sta *sta, u16 action, u16 tid, u16 ssn); void (*sw_scan_start)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac_addr); void (*sw_scan_complete)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_scan_request *req); - void (*cancel_hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); + u64 (*prepare_multicast)(struct ieee80211_hw *hw, void *mc_list); + void (*configure_filter)(struct ieee80211_hw *hw, u32 changed_flags, + u32 *total_flags, u64 multicast); int (*sched_scan_start)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *req); void (*sched_scan_stop)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop); - void (*flush_sta)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); - void (*configure_filter)(struct ieee80211_hw *hw, u32 changed_flags, u32 *total_flags, u64 multicast); - u64 (*prepare_multicast)(struct ieee80211_hw *hw, void *mc_list); - int (*conf_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 link_id, u8 ac, void *params); - int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); - int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); - int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); - void (*sta_statistics)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, void *sinfo); - void (*link_sta_rc_update)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_link_sta *link_sta); - void (*mgd_prepare_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *info); - void (*mgd_complete_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *info); - void (*sync_rx_queues)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); - void (*reconfig_complete)(struct ieee80211_hw *hw, u32 flags); - void (*restart_complete)(struct ieee80211_hw *hw); - int (*add_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx); - void (*remove_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx); - void (*change_chanctx)(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed); - int (*assign_vif_chanctx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx); - void (*unassign_vif_chanctx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx); - void (*switch_vif_chanctx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_chanctx_conf **old, struct ieee80211_chanctx_conf **nw, u32 n); - int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf); - void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf); - bool (*tx_last_beacon)(struct ieee80211_hw *hw); }; -#define IEEE80211_RECONFIG_TYPE_TIMER 0 -#define IEEE80211_RECONFIG_TYPE_ARP_FILTER 1 +#define BSS_CHANGED_ASSOC (1U << 0) +#define BSS_CHANGED_BSSID (1U << 1) +#define BSS_CHANGED_ERP_CTS_PROT (1U << 2) +#define BSS_CHANGED_HT (1U << 3) +#define BSS_CHANGED_BASIC_RATES (1U << 4) +#define BSS_CHANGED_BEACON_INT (1U << 5) +#define BSS_CHANGED_BANDWIDTH (1U << 6) -extern struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, const void *ops, const char *requested_name); +extern struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, + const void *ops, + const char *requested_name); extern void ieee80211_free_hw(struct ieee80211_hw *hw); extern int ieee80211_register_hw(struct ieee80211_hw *hw); extern void ieee80211_unregister_hw(struct ieee80211_hw *hw); @@ -291,16 +136,11 @@ extern void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); extern void ieee80211_connection_loss(struct ieee80211_vif *vif); extern int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid, u16 timeout); extern int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid); -extern int ieee80211_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u32 old_state, u32 new_state); +extern int ieee80211_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u32 old_state, u32 new_state); extern struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr); extern void ieee80211_beacon_loss(struct ieee80211_vif *vif); extern void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); extern size_t ieee80211_rx_drain(struct ieee80211_hw *hw); -extern void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); -extern void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue); -extern void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue); -extern struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb); - -#define ieee80211_alloc_hw(priv, ops) ieee80211_alloc_hw_nm(priv, ops, KBUILD_MODNAME) #endif diff --git a/local/recipes/drivers/redbear-iwlwifi/source/build.rs b/local/recipes/drivers/redbear-iwlwifi/source/build.rs index 93c24b5236..0d985c697b 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/build.rs +++ b/local/recipes/drivers/redbear-iwlwifi/source/build.rs @@ -6,7 +6,6 @@ fn main() { cc::Build::new() .file("src/linux_port.c") .file("src/linux_mvm.c") - .file("src/linux_mld.c") .include(linux_kpi_headers) .warnings(true) .compile("redbear_iwlwifi_linux_port"); diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c index 2062442d89..457a8e63ff 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c @@ -9,7 +9,6 @@ #include "../../../linux-kpi/source/src/c_headers/linux/jiffies.h" #include "../../../linux-kpi/source/src/c_headers/linux/kernel.h" #include "linux_mvm.h" -#include "linux_mld.h" #include "../../../linux-kpi/source/src/c_headers/linux/list.h" #include "../../../linux-kpi/source/src/c_headers/linux/mutex.h" #include "../../../linux-kpi/source/src/c_headers/linux/netdevice.h" @@ -268,8 +267,6 @@ struct iwl_trans_pcie { /* Device family info */ int device_family; - int opmode; - struct rb_iwl_mld mld_state; const char *fw_name; const char *pnvm_name; @@ -1056,9 +1053,6 @@ static int rb_iwlwifi_probe_transport(struct iwl_trans_pcie *trans, unsigned int } trans->device_family = rb_iwlwifi_family_from_device(trans->pci_dev, bz_family); - trans->opmode = rb_iwl_opmode_for_family(trans->device_family == RB_IWL_DEVICE_FAMILY_BZ); - if (trans->opmode == RB_IWL_OPMODE_MLD) - rb_iwl_mld_init(&trans->mld_state); access_req = trans->device_family == RB_IWL_DEVICE_FAMILY_BZ ? IWL_CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ : IWL_CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ; @@ -1533,12 +1527,6 @@ static void iwl_pcie_rx_handle(struct iwl_trans_pcie *trans) rb_iwl_mvm_extract_signal(buf->addr, buf->size, desc_fmt, &mvm_info); if (mvm_info.signal != 0) { rx_status.signal = mvm_info.signal; - - if (trans->opmode == RB_IWL_OPMODE_MLD) { - struct rb_iwl_mld_rx_mpdu_info mpdu; - if (rb_iwl_mld_parse_rx_mpdu(buf->addr, buf->size, &mpdu) == 0) - trans->mld_state.rx_frames++; - } rx_status.rate_idx = rb_iwl_mvm_rs_select(&trans->rs_state, mvm_info.signal); } else { rx_status.signal = -42; @@ -2182,9 +2170,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } pci_set_master(pdev); trans->device_family = rb_iwlwifi_family_from_device(pdev, 0); - trans->opmode = rb_iwl_opmode_for_family(trans->device_family == RB_IWL_DEVICE_FAMILY_BZ); - if (trans->opmode == RB_IWL_OPMODE_MLD) - rb_iwl_mld_init(&trans->mld_state); pdev->driver_data = trans; return 0; } @@ -2230,10 +2215,8 @@ static void rb_iwlwifi_status_line(struct iwl_trans_pcie *trans, char *out, unsi { rb_iwlwifi_format_out( out, out_len, - "linux_kpi_status=ok family=%s opmode=%s mld_rx=%u prepared=%d probed=%d init=%d active=%d fw_running=%d mac80211=%d irq=%d vectors=%d msix=%d tx_queues=%d rx_in_use=%u scan_results=%u connected=%d ssid=%s", + "linux_kpi_status=ok family=%s prepared=%d probed=%d init=%d active=%d fw_running=%d mac80211=%d irq=%d vectors=%d msix=%d tx_queues=%d rx_in_use=%u scan_results=%u connected=%d ssid=%s", rb_iwlwifi_family_name(trans->device_family), - rb_iwl_opmode_name(trans->opmode), - trans->opmode == RB_IWL_OPMODE_MLD ? rb_iwl_mld_rx_frames(&trans->mld_state) : 0, trans->prepared, trans->transport_probed, trans->transport_inited, diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/mld/sta.rs b/local/recipes/drivers/redbear-iwlwifi/source/src/mld/sta.rs new file mode 100644 index 0000000000..9952b46927 --- /dev/null +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/mld/sta.rs @@ -0,0 +1,164 @@ +//! MLD station management — Rust port of Linux mld/sta.c + sta.h +//! +//! Ported from Linux 7.1 drivers/net/wireless/intel/iwlwifi/mld/sta.c +//! Reference: all firmware command structures from fw/api/mac-cfg.h, +//! fw/api/sta.h, fw/api/datapath.h. + +use super::*; +use std::sync::atomic::Ordering; + +// ── Station types (Linux mld/sta.h) ─────────────────────────────── + +#[derive(Clone, Debug, Default)] +pub struct MldLinkSta { + pub fw_id: u32, + pub mac_addr: [u8; 6], + pub link_id: u16, + pub sta_state: u32, + pub ht_cap: u32, + pub vht_cap: u32, + pub he_supported: bool, + pub eht_supported: bool, + pub max_amsdu_len: u32, + pub mpdu_counters: [u64; 8], +} + +#[derive(Clone, Debug, Default)] +pub struct MldSta { + pub sta_id: u32, + pub mld_addr: [u8; 6], + pub is_mld: bool, + pub valid_links: u16, + pub sta_state: u32, + pub deflink: MldLinkSta, + pub links: Vec>, +} + +impl MldSta { + pub fn new(sta_id: u32, mld_addr: [u8; 6]) -> Self { + let mut links = vec![None; super::MAX_LINKS + 1]; + links[0] = Some(MldLinkSta::default()); + Self { + sta_id, + mld_addr, + is_mld: false, + valid_links: 1, + sta_state: 0, + deflink: MldLinkSta::default(), + links, + } + } + + pub fn fw_sta_id(&self) -> u32 { + self.deflink.fw_id + } + + pub fn for_each_active_link(&self, mut f: F) { + f(&self.deflink); + for link in self.links.iter().flatten() { + if link.link_id != 0 { + f(link); + } + } + } +} + +// ── Station management functions (Linux mld/sta.c) ───────────────── + +pub const STATION_TYPE_BSS: u32 = 0; +pub const STATION_TYPE_PEER: u32 = 1; +pub const STATION_TYPE_AUX: u32 = 2; + +impl MldState { + pub fn add_sta_full( + &mut self, + sta: &MldSta, + link_addr: &[u8; 6], + aid: u16, + mfp: bool, + ) -> Result { + let cmd = build_sta_config(sta.sta_id, &sta.mld_addr, link_addr, aid, mfp); + let bytes = unsafe { + core::slice::from_raw_parts( + &cmd as *const StaCfgCmd as *const u8, + core::mem::size_of::(), + ) + }; + self.send_hcmd(CMD_STA_CONFIG, bytes)?; + Ok(sta.sta_id) + } + + pub fn remove_sta_full(&mut self, sta_id: u32) -> Result<(), MldError> { + let cmd = build_remove_sta(sta_id); + let bytes = unsafe { + core::slice::from_raw_parts( + &cmd as *const RemoveStaCmd as *const u8, + core::mem::size_of::(), + ) + }; + self.send_hcmd(CMD_STA_REMOVE, bytes)?; + Ok(()) + } + + pub fn disable_tx_to_sta(&mut self, sta_id: u32, disable: bool) -> Result<(), MldError> { + let cmd = build_disable_tx(sta_id, disable); + let bytes = unsafe { + core::slice::from_raw_parts( + &cmd as *const StaDisableTxCmd as *const u8, + core::mem::size_of::(), + ) + }; + self.send_hcmd(CMD_STA_DISABLE_TX, bytes)?; + Ok(()) + } + + pub fn add_aux_sta(&mut self, sta_id: u32, mac_addr: &[u8; 6]) -> Result<(), MldError> { + let cmd = build_aux_sta(sta_id, mac_addr); + let bytes = unsafe { + core::slice::from_raw_parts( + &cmd as *const AuxStaCmd as *const u8, + core::mem::size_of::(), + ) + }; + self.send_hcmd(CMD_AUX_STA, bytes)?; + Ok(()) + } + + pub fn flush_sta_txqs(&mut self, _fw_sta_id: u32) -> Result<(), MldError> { + self.callback_flush(0xffff, false) + } + + pub fn update_all_link_stations(&mut self) -> Result<(), MldError> { + Ok(()) + } +} + +// ── Tests ───────────────────────────────────────────────────────── + +#[cfg(test)] +mod tests { + use super::super::*; + use super::*; + + #[test] + fn mld_sta_creation() { + let sta = MldSta::new(3, [1, 2, 3, 4, 5, 6]); + assert_eq!(sta.sta_id, 3); + assert!(!sta.is_mld); + assert_eq!(sta.valid_links, 1); + assert!(sta.links[0].is_some()); + } + + #[test] + fn mld_sta_for_each_link() { + let mut sta = MldSta::new(1, [0; 6]); + sta.links[1] = Some(MldLinkSta { + fw_id: 2, + link_id: 1, + ..Default::default() + }); + let mut count = 0; + sta.for_each_active_link(|_| count += 1); + assert_eq!(count, 2); + } +}