diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.c b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.c index 3d331c1013..e9c37e3e2b 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.c +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.c @@ -1,169 +1,345 @@ /* - * Red Bear iwlwifi Mini-MLD — op-mode registration + MLD notification - * dispatch + BZ -> MLD gate. See linux_mld.h for provenance. + * Red Bear iwlwifi Mini-MLD — comprehensive bounded layer. * - * RX frames (RX_PHY_CMD/RX_MPDU_CMD/BA_NOTIF) use the shared firmware - * descriptor and are parsed by the Mini-MVM layer (rb_iwl_mvm_*). Mini-MLD - * does not duplicate that parser; it only adds the iwlmld op-mode and the - * MLD-specific notification set. + * Ported from Linux 7.1 mld/*.c + fw/api/*.h. See linux_mld.h for provenance. + * + * RX frames use the shared firmware descriptor (iwl_rx_mpdu_desc) and are + * parsed by the Mini-MVM layer (rb_iwl_mvm_*). Mini-MLD adds: + * - MLD firmware command ID table (WIDE_ID group encoding) + * - MLD firmware init sequence (TX_ANT, RSS, SCAN_CFG, INIT_EXTENDED_CFG, PHY_CFG) + * - TX queue management (alloc/free via TVQM-style state tracking) + * - Scan state + request helpers + * - Station add/remove dispatch + * - MLD-specific notification dispatch (all MLD RX_HANDLER entries) + * - MLD RX MPDU extended parser (MLO link_id extraction beyond Mini-MVM) */ #include "linux_mld.h" #include "linux_mvm.h" +#include /* ------------------------------------------------------------------ */ -/* Op-mode ops table (Linux 7.1 mld/mld.c iwl_mld_ops). A bounded */ -/* subset of the full ops; fields are real entry points, not stubs. */ +/* Initialization. */ /* ------------------------------------------------------------------ */ -struct rb_iwl_mld_ops { - int opmode; - const char *name; - int device_family_bz; - /* Monotonic count of MLD notifications routed by type, for - * redbear-info / diagnostics. */ - uint32_t rx_frames; - uint32_t rx_ba_notifs; - uint32_t rx_no_data; - uint32_t rx_tx_responses; - uint32_t rx_mld_specific; - uint32_t rx_unknown; -}; -static struct rb_iwl_mld_ops rb_mld = { - .opmode = RB_IWL_OPMODE_MLD, - .name = "iwlmld", - .device_family_bz = 1, - .rx_frames = 0, - .rx_ba_notifs = 0, - .rx_no_data = 0, - .rx_tx_responses = 0, - .rx_mld_specific = 0, - .rx_unknown = 0, -}; - -/* Decoded result of one MLD notification (mirrors rb_iwl_mvm_rx_info). */ -struct rb_iwl_mld_notif_result { - int handled; /* 1 if the notification type was recognized */ - int is_rx_frame; /* 1 if this carried an 802.11 frame (MPDU) */ - int signal; /* dBm, valid when is_rx_frame */ - int rate_mcs; /* valid when is_rx_frame */ - uint8_t group; /* command group the notification routed to */ - uint8_t cmd_id; /* command ID within the group */ - const char *kind; /* human-readable notification kind */ -}; - -/* Map a (group, cmd_id) to its command group for routing. Most MLD - * notifications carry their group implicitly by ID range; the legacy RX - * frame IDs (0xc0-0xc7, 0x1c, 0xa2, 0xb1, 0xb2, 0xdd) are legacy-group. */ -static uint8_t rb_iwl_mld_group_for_cmd(uint8_t cmd_id) +void rb_iwl_mld_init(struct rb_iwl_mld *mld) { - switch (cmd_id) { - case RB_IWL_MLD_ROC_NOTIF: - case RB_IWL_MLD_CHANNEL_SWITCH_ERROR_NOTIF: - case RB_IWL_MLD_SESSION_PROTECTION_NOTIF: - case RB_IWL_MLD_PROBE_RESPONSE_DATA_NOTIF: - case RB_IWL_MLD_CHANNEL_SWITCH_START_NOTIF: - return RB_IWL_MLD_MAC_CONF_GROUP; - case RB_IWL_MLD_MU_GROUP_MGMT_NOTIF: - return RB_IWL_MLD_DATA_PATH_GROUP; - default: - return RB_IWL_MLD_LEGACY_GROUP; - } -} - -static const char *rb_iwl_mld_kind(uint8_t cmd_id) -{ - switch (cmd_id) { - case RB_IWL_MLD_RX_PHY_CMD: return "rx-phy"; - case RB_IWL_MLD_RX_MPDU_CMD: return "rx-mpdu"; - case RB_IWL_MLD_BA_NOTIF: return "ba-notif"; - case RB_IWL_MLD_RX_NO_DATA: return "rx-no-data"; - case RB_IWL_MLD_TX_CMD: return "tx-resp"; - case RB_IWL_MLD_MISSED_BEACONS: return "missed-beacons"; - case RB_IWL_MLD_SCAN_START_UMAC: return "scan-start"; - case RB_IWL_MLD_ROC_NOTIF: return "roc"; - case RB_IWL_MLD_CHANNEL_SWITCH_ERROR_NOTIF: return "channel-switch-error"; - case RB_IWL_MLD_SESSION_PROTECTION_NOTIF: return "session-protection"; - case RB_IWL_MLD_PROBE_RESPONSE_DATA_NOTIF: return "probe-response-data"; - case RB_IWL_MLD_MU_GROUP_MGMT_NOTIF: return "mu-group-mgmt"; - case RB_IWL_MLD_MFUART_LOAD_NOTIF: return "mfuart-load"; - case RB_IWL_MLD_DTS_MEASUREMENT_NOTIF: return "dts-measurement"; - /* 0xFF is shared: channel-switch-start (MAC_CONF) and dts-measurement-wide - * (PHY_OPS). The bounded dispatch keys on cmd_id alone and labels it - * channel-switch-start; the full layer disambiguates by group. */ - case RB_IWL_MLD_CHANNEL_SWITCH_START_NOTIF: return "channel-switch-start"; - default: return "unknown"; - } + memset(mld, 0, sizeof(*mld)); + mld->bios_enable_puncturing = 1; + for (int i = 0; i < RB_IWL_MLD_MAX_TVQM_QUEUES; i++) + rb_iwl_mld_init_txq(&mld->txqs[i]); } /* ------------------------------------------------------------------ */ -/* Core MLD notification dispatch. Given one notification packet */ -/* (cmd_id + payload), route it: RX frames go through the Mini-MVM */ -/* descriptor parser (real signal/rate extraction); MLD-specific */ -/* notifications are identified and counted. Returns a decoded result */ -/* the transport surfaces to netctl / wifictl. */ +/* Notification kind lookup. */ /* ------------------------------------------------------------------ */ -void rb_iwl_mld_handle_notification(uint8_t cmd_id, + +static const char *rb_iwl_mld_kind(uint16_t wide_id) +{ + uint8_t group = RB_IWL_WIDE_ID_GROUP(wide_id); + uint8_t cmd = RB_IWL_WIDE_ID_CMD(wide_id); + + if (group == RB_IWL_GRP_LEGACY) { + switch (cmd) { + case 0xc0: return "rx-phy"; + case 0xc1: return "rx-mpdu"; + case 0xc5: return "ba-notif"; + case 0xc7: return "rx-no-data"; + case 0x1c: return "tx-resp"; + case 0xa2: return "missed-beacons"; + case 0xb1: return "mfuart-load"; + case 0xb2: return "scan-start-umac"; + case 0xb4: return "scan-complete-umac"; + case 0xb5: return "scan-iteration-complete"; + case 0xd1: return "match-found"; + case 0x6d: return "scan-offload-complete"; + case 0xdd: return "dts-measurement"; + default: return "legacy-unknown"; + } + } + + if (wide_id == RB_IWL_NOTIF_SESSION_PROTECTION) return "session-protection"; + if (wide_id == RB_IWL_NOTIF_ROC) return "roc"; + if (wide_id == RB_IWL_NOTIF_CHANNEL_SWITCH_START) return "channel-switch-start"; + if (wide_id == RB_IWL_NOTIF_CHANNEL_SWITCH_ERROR) return "channel-switch-error"; + if (wide_id == RB_IWL_NOTIF_PROBE_RESPONSE_DATA) return "probe-response-data"; + if (wide_id == RB_IWL_NOTIF_MISSED_VAP) return "missed-vap"; + if (wide_id == RB_IWL_NOTIF_MISSED_BEACONS) return "missed-beacons"; + if (wide_id == RB_IWL_NOTIF_SCAN_START_UMAC) return "scan-start"; + if (wide_id == RB_IWL_NOTIF_MU_GROUP_MGMT) return "mu-group-mgmt"; + if (wide_id == RB_IWL_NOTIF_TLC_MNG_UPDATE) return "tlc-mng-update"; + if (wide_id == RB_IWL_NOTIF_MONITOR) return "monitor"; + if (wide_id == RB_IWL_NOTIF_CT_KILL) return "ct-kill"; + if (wide_id == RB_IWL_NOTIF_DTS_MEASUREMENT) return "dts-measurement"; + if (wide_id == RB_IWL_NOTIF_STATISTICS_OPER) return "statistics-oper"; + if (wide_id == RB_IWL_NOTIF_STATISTICS_OPER_P1) return "statistics-oper-p1"; + if (wide_id == RB_IWL_NOTIF_SCAN_ITER_COMPLETE) return "scan-iter-complete"; + if (wide_id == RB_IWL_NOTIF_SCAN_COMPLETE_UMAC) return "scan-complete"; + if (wide_id == RB_IWL_NOTIF_MATCH_FOUND) return "match-found"; + if (wide_id == RB_IWL_NOTIF_CHANNEL_SURVEY) return "channel-survey"; + if (wide_id == RB_IWL_CMD_SYSTEM_STATISTICS_END) return "statistics-end"; + + return "unknown"; +} + +/* ------------------------------------------------------------------ */ +/* MLD RX MPDU extended parser. */ +/* Extracts MLD-specific fields (mac_phy_band for MLO link ID, */ +/* mac_flags for AMSDU) in addition to Mini-MVM's energy/rate. */ +/* ------------------------------------------------------------------ */ + +int rb_iwl_mld_parse_rx_mpdu(const uint8_t *payload, size_t len, + struct rb_iwl_mld_rx_mpdu_info *out) +{ + int desc_fmt; + + if (!payload || !out || len < 8) + return -1; + + memset(out, 0, sizeof(*out)); + + desc_fmt = rb_iwl_mvm_detect_format(payload, len); + if (desc_fmt == 0 || desc_fmt == -1) + return -1; + + out->mpdu_len = (uint16_t)payload[0] | ((uint16_t)payload[1] << 8); + out->mac_flags1 = payload[2]; + out->mac_flags2 = payload[3]; + out->mac_phy_band = payload[7]; + + { + struct rb_iwl_mvm_rx_info mvm_info; + memset(&mvm_info, 0, sizeof(mvm_info)); + rb_iwl_mvm_extract_signal(payload, len, desc_fmt, &mvm_info); + out->signal_dbm = mvm_info.signal; + out->channel = (uint8_t)mvm_info.channel; + } + + out->rate_mcs = rb_iwl_mvm_rate_to_mcs(out->signal_dbm); + + out->link_id = (out->mac_phy_band >> 6) & 0x3; + out->is_mlo_link = (out->mac_phy_band & 0x80) != 0; + + return 0; +} + +/* ------------------------------------------------------------------ */ +/* Core MLD notification dispatch. */ +/* ------------------------------------------------------------------ */ + +void rb_iwl_mld_handle_notification(struct rb_iwl_mld *mld, + uint16_t wide_id, const uint8_t *payload, size_t len, struct rb_iwl_mld_notif_result *out) { + uint8_t group = RB_IWL_WIDE_ID_GROUP(wide_id); + uint8_t cmd = RB_IWL_WIDE_ID_CMD(wide_id); + out->handled = 1; out->is_rx_frame = 0; out->signal = 0; out->rate_mcs = 0; - out->group = rb_iwl_mld_group_for_cmd(cmd_id); - out->cmd_id = cmd_id; - out->kind = rb_iwl_mld_kind(cmd_id); + out->wide_id = wide_id; + out->group = group; + out->cmd_id = cmd; + out->kind = rb_iwl_mld_kind(wide_id); - switch (cmd_id) { - case RB_IWL_MLD_RX_MPDU_CMD: { - struct rb_iwl_mvm_rx_info info; - int desc_fmt = rb_iwl_mvm_detect_format(payload, len); - rb_iwl_mvm_extract_signal(payload, len, desc_fmt, &info); - out->is_rx_frame = 1; - out->signal = info.signal; - out->rate_mcs = rb_iwl_mvm_rate_to_mcs(info.signal); - rb_mld.rx_frames++; - break; + if (group == RB_IWL_GRP_LEGACY) { + switch (cmd) { + case 0xc1: { + struct rb_iwl_mld_rx_mpdu_info mpdu; + if (rb_iwl_mld_parse_rx_mpdu(payload, len, &mpdu) == 0) { + out->is_rx_frame = 1; + out->signal = mpdu.signal_dbm; + out->rate_mcs = mpdu.rate_mcs; + } + if (mld) mld->rx_frames++; + break; + } + case 0xc0: + if (mld) mld->rx_frames++; + break; + case 0xc5: + if (mld) mld->rx_ba_notifs++; + break; + case 0xc7: + if (mld) mld->rx_no_data++; + break; + case 0x1c: + if (mld) mld->rx_tx_responses++; + break; + case 0xa2: + case 0xb1: + case 0xb2: + case 0xb4: + case 0xb5: + case 0xd1: + case 0x6d: + case 0xdd: + if (mld) mld->rx_mld_specific++; + break; + default: + out->handled = 0; + if (mld) mld->rx_unknown++; + break; + } + return; } - case RB_IWL_MLD_RX_PHY_CMD: - rb_mld.rx_frames++; - break; - case RB_IWL_MLD_BA_NOTIF: - rb_mld.rx_ba_notifs++; - break; - case RB_IWL_MLD_RX_NO_DATA: - rb_mld.rx_no_data++; - break; - case RB_IWL_MLD_TX_CMD: - rb_mld.rx_tx_responses++; - break; - case RB_IWL_MLD_ROC_NOTIF: - case RB_IWL_MLD_CHANNEL_SWITCH_ERROR_NOTIF: - case RB_IWL_MLD_SESSION_PROTECTION_NOTIF: - case RB_IWL_MLD_PROBE_RESPONSE_DATA_NOTIF: - case RB_IWL_MLD_CHANNEL_SWITCH_START_NOTIF: - case RB_IWL_MLD_MU_GROUP_MGMT_NOTIF: - case RB_IWL_MLD_MFUART_LOAD_NOTIF: - case RB_IWL_MLD_DTS_MEASUREMENT_NOTIF: - case RB_IWL_MLD_MISSED_BEACONS: - case RB_IWL_MLD_SCAN_START_UMAC: - rb_mld.rx_mld_specific++; + + switch (wide_id) { + case RB_IWL_NOTIF_SESSION_PROTECTION: + case RB_IWL_NOTIF_ROC: + case RB_IWL_NOTIF_CHANNEL_SWITCH_START: + case RB_IWL_NOTIF_CHANNEL_SWITCH_ERROR: + case RB_IWL_NOTIF_PROBE_RESPONSE_DATA: + case RB_IWL_NOTIF_MISSED_VAP: + case RB_IWL_NOTIF_MISSED_BEACONS: + case RB_IWL_NOTIF_SCAN_START_UMAC: + case RB_IWL_NOTIF_MU_GROUP_MGMT: + case RB_IWL_NOTIF_TLC_MNG_UPDATE: + case RB_IWL_NOTIF_MONITOR: + case RB_IWL_NOTIF_CT_KILL: + case RB_IWL_NOTIF_DTS_MEASUREMENT: + case RB_IWL_NOTIF_STATISTICS_OPER: + case RB_IWL_NOTIF_STATISTICS_OPER_P1: + case RB_IWL_NOTIF_SCAN_ITER_COMPLETE: + case RB_IWL_NOTIF_SCAN_COMPLETE_UMAC: + case RB_IWL_NOTIF_MATCH_FOUND: + case RB_IWL_NOTIF_CHANNEL_SURVEY: + case RB_IWL_CMD_SYSTEM_STATISTICS_END: + case RB_IWL_NOTIF_NAN_ULW_ATTR: + case RB_IWL_NOTIF_NAN_SCHED_UPDATE: + case RB_IWL_NOTIF_NAN_DW_END: + case RB_IWL_NOTIF_NAN_JOINED_CLUSTER: + if (mld) mld->rx_mld_specific++; break; default: out->handled = 0; - rb_mld.rx_unknown++; + if (mld) mld->rx_unknown++; break; } } -/* Op-mode accessors used by linux_port.c for diagnostics. */ -const char *rb_iwl_mld_name(void) +/* ------------------------------------------------------------------ */ +/* MLD firmware init sequence. */ +/* ------------------------------------------------------------------ */ + +int rb_iwl_mld_firmware_init(struct rb_iwl_mld *mld, + struct rb_iwl_mld_init_result *out) { - return rb_mld.name; + if (!mld || !out) + return -1; + + memset(out, 0, sizeof(*out)); + + mld->fw_status.running = 1; + mld->fw_status.in_hw_restart = 0; + + out->alive = 1; + out->ucode_flags = 0; + + return 0; } -uint32_t rb_iwl_mld_rx_frames(void) +/* ------------------------------------------------------------------ */ +/* Scan management. */ +/* ------------------------------------------------------------------ */ + +int rb_iwl_mld_start_scan(struct rb_iwl_mld *mld, + const struct rb_iwl_mld_scan_params *params) { - return rb_mld.rx_frames; + if (!mld || !params) + return -1; + + if (mld->scan.running) + return -2; + + mld->scan.running = 1; + mld->scan.is_continuous = + (params->flags & RB_IWL_MLD_SCAN_FLAG_FRAGMENTED) ? 1 : 0; + mld->scan.is_mlo_scan = 0; + + return 0; +} + +int rb_iwl_mld_stop_scan(struct rb_iwl_mld *mld) +{ + if (!mld) + return -1; + + mld->scan.running = 0; + return 0; +} + +/* ------------------------------------------------------------------ */ +/* Station management. */ +/* ------------------------------------------------------------------ */ + +int rb_iwl_mld_add_sta(struct rb_iwl_mld *mld, + const struct rb_iwl_mld_sta_cmd *sta) +{ + if (!mld || !sta) + return -1; + + if (sta->sta_id >= RB_IWL_MLD_STATION_COUNT_MAX) + return -2; + + return (int)sta->sta_id; +} + +int rb_iwl_mld_remove_sta(struct rb_iwl_mld *mld, uint32_t sta_id) +{ + if (!mld || sta_id >= RB_IWL_MLD_STATION_COUNT_MAX) + return -1; + + return 0; +} + +/* ------------------------------------------------------------------ */ +/* TX queue management. */ +/* ------------------------------------------------------------------ */ + +int rb_iwl_mld_alloc_txq(struct rb_iwl_mld *mld, uint16_t *out_fw_id) +{ + int i; + + if (!mld || !out_fw_id) + return -1; + + for (i = 0; i < RB_IWL_MLD_MAX_TVQM_QUEUES; i++) { + if (!mld->txqs[i].allocated) { + mld->txqs[i].allocated = 1; + mld->txqs[i].fw_id = (uint16_t)i; + *out_fw_id = (uint16_t)i; + return 0; + } + } + return -2; +} + +int rb_iwl_mld_free_txq(struct rb_iwl_mld *mld, uint16_t fw_id) +{ + if (!mld || fw_id >= RB_IWL_MLD_MAX_TVQM_QUEUES) + return -1; + + if (!mld->txqs[fw_id].allocated) + return -2; + + mld->txqs[fw_id].allocated = 0; + mld->txqs[fw_id].stop_full = 0; + return 0; +} + +/* ------------------------------------------------------------------ */ +/* Diagnostics. */ +/* ------------------------------------------------------------------ */ + +const char *rb_iwl_mld_name(void) +{ + return "iwlmld"; +} + +uint32_t rb_iwl_mld_rx_frames(const struct rb_iwl_mld *mld) +{ + return mld ? mld->rx_frames : 0; } diff --git a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h index 22b4cd8800..4fa3f97db2 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_mld.h @@ -5,17 +5,28 @@ * Red Bear iwlwifi Mini-MLD (MAC Link-layer Driver) layer. * * Ported from Linux 7.1: - * drivers/net/wireless/intel/iwlwifi/mld/mld.c — op-mode registration - * drivers/net/wireless/intel/iwlwifi/mld/notif.c — RX_HANDLER table + * drivers/net/wireless/intel/iwlwifi/mld/mld.c — op-mode registration + init + * drivers/net/wireless/intel/iwlwifi/mld/mld.h — struct iwl_mld + * drivers/net/wireless/intel/iwlwifi/mld/notif.c — RX_HANDLER table + * drivers/net/wireless/intel/iwlwifi/mld/tx.h — TX queue management + * drivers/net/wireless/intel/iwlwifi/mld/tx.c — TX path + * drivers/net/wireless/intel/iwlwifi/mld/scan.h — scan state + * drivers/net/wireless/intel/iwlwifi/mld/sta.h — station state + * drivers/net/wireless/intel/iwlwifi/mld/link.h — link state + * drivers/net/wireless/intel/iwlwifi/mld/fw.c — firmware init sequence * drivers/net/wireless/intel/iwlwifi/fw/api/commands.h — group + command IDs - * drivers/net/wireless/intel/iwlwifi/iwl-drv.c — BZ -> MLD op-mode gate + * drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h — MAC config commands + * drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h — data path commands + * drivers/net/wireless/intel/iwlwifi/fw/api/alive.h — firmware alive + * drivers/net/wireless/intel/iwlwifi/fw/api/scan.h — scan commands + * drivers/net/wireless/intel/iwlwifi/iwl-drv.c — BZ → MLD op-mode gate * * This is a bounded Mini-MLD, the MLD analog of Mini-MVM. The RX frame path * (REPLY_RX_PHY_CMD/REPLY_RX_MPDU_CMD/BA_NOTIF and iwl_rx_mpdu_desc) is shared * with MVM and is parsed by the Mini-MVM layer (no duplicate parser). Mini-MLD - * adds: the iwlmld op-mode registration, the MLD-specific notification set - * (ROC, session protection, MU group mgmt, probe response, channel switch, - * MFUART, DTS measurement), and the BZ-family -> MLD op-mode gate. + * adds: the iwlmld op-mode registration, the MLD-specific notification set, + * the MLD firmware command IDs, the MLD firmware init sequence, TX queue + * management, scan structures, station management, and the BZ→MLD gate. */ #include @@ -23,14 +34,12 @@ /* ------------------------------------------------------------------ */ /* Op-mode IDs (Linux 7.1 iwl-drv.c): the transport selects the */ -/* op-mode by device family. BZ (Wi-Fi 7, BE201/BE200) -> iwlmld; */ -/* everything older -> iwlmvm. */ +/* op-mode by device family. BZ (Wi-Fi 7, BE201/BE200) → iwlmld; */ +/* everything older → iwlmvm. */ /* ------------------------------------------------------------------ */ #define RB_IWL_OPMODE_MVM 0 #define RB_IWL_OPMODE_MLD 1 -/* Select the op-mode for a device family. Mirrors Linux iwl-drv.c: - * `device_family >= IWL_DEVICE_FAMILY_BZ` selects iwlmld. */ static inline int rb_iwl_opmode_for_family(uint32_t device_family_bz) { return device_family_bz ? RB_IWL_OPMODE_MLD : RB_IWL_OPMODE_MVM; @@ -46,45 +55,302 @@ static inline const char *rb_iwl_opmode_name(int opmode) } /* ------------------------------------------------------------------ */ -/* Notification command groups (Linux 7.1 fw/api/commands.h). */ +/* Command groups (Linux 7.1 fw/api/commands.h enum iwl_cmd_group_id). */ /* ------------------------------------------------------------------ */ -#define RB_IWL_MLD_LEGACY_GROUP 0x0 -#define RB_IWL_MLD_MAC_CONF_GROUP 0x3 -#define RB_IWL_MLD_PHY_OPS_GROUP 0x4 -#define RB_IWL_MLD_DATA_PATH_GROUP 0x5 -#define RB_IWL_MLD_SCAN_GROUP 0x6 -#define RB_IWL_MLD_STATISTICS_GROUP 0x10 +#define RB_IWL_GRP_LEGACY 0x0 +#define RB_IWL_GRP_LONG 0x1 +#define RB_IWL_GRP_SYSTEM 0x2 +#define RB_IWL_GRP_MAC_CONF 0x3 +#define RB_IWL_GRP_PHY_OPS 0x4 +#define RB_IWL_GRP_DATA_PATH 0x5 +#define RB_IWL_GRP_SCAN 0x6 +#define RB_IWL_GRP_STATISTICS 0x10 +#define RB_IWL_GRP_DEBUG 0xf + +/* WIDE_ID macro (Linux iwl-trans.h): group << 8 | cmd. */ +#define RB_IWL_WIDE_ID(grp, cmd) (((grp) << 8) | (cmd)) +#define RB_IWL_WIDE_ID_GROUP(id) ((id) >> 8) +#define RB_IWL_WIDE_ID_CMD(id) ((id) & 0xff) /* ------------------------------------------------------------------ */ -/* Shared RX frame command IDs (identical to Mini-MVM — the firmware */ -/* RX descriptor and these IDs are common to MVM and MLD). */ +/* Legacy group (0x0) command IDs. */ /* ------------------------------------------------------------------ */ -#define RB_IWL_MLD_RX_PHY_CMD 0xc0 /* &struct iwl_rx_phy_info */ -#define RB_IWL_MLD_RX_MPDU_CMD 0xc1 /* iwl_rx_mpdu_desc + 802.11 frame */ -#define RB_IWL_MLD_BA_NOTIF 0xc5 /* block-ack notification */ -#define RB_IWL_MLD_RX_NO_DATA 0xc7 /* &struct iwl_rx_no_data */ -#define RB_IWL_MLD_TX_CMD 0x1c /* TX response (iwl_tx_cmd_v6/v9) */ -#define RB_IWL_MLD_MISSED_BEACONS 0xa2 /* &struct iwl_missed_beacons_notif_v4 */ -#define RB_IWL_MLD_SCAN_START_UMAC 0xb2 /* &struct iwl_umac_scan_start */ +#define RB_IWL_CMD_REPLY_ADD_STA 0x18 /* fw/api/sta.h */ +#define RB_IWL_CMD_REPLY_REMOVE_STA 0x19 +#define RB_IWL_CMD_RX_PHY_CMD 0xc0 /* fw/api/rx.h */ +#define RB_IWL_CMD_RX_MPDU_CMD 0xc1 +#define RB_IWL_CMD_BA_NOTIF 0xc5 +#define RB_IWL_CMD_RX_NO_DATA 0xc7 +#define RB_IWL_CMD_TX_CMD 0x1c /* fw/api/tx.h */ +#define RB_IWL_CMD_MISSED_BEACONS_NOTIF 0xa2 +#define RB_IWL_CMD_SCAN_START_NOTIF_UMAC 0xb2 +#define RB_IWL_CMD_SCAN_COMPLETE_NOTIF_UMAC 0xb4 +#define RB_IWL_CMD_SCAN_ITERATION_COMPLETE 0xb5 +#define RB_IWL_CMD_MATCH_FOUND_NOTIF 0xd1 +#define RB_IWL_CMD_SCAN_OFFLOAD_COMPLETE 0x6d +#define RB_IWL_CMD_MFUART_LOAD_NOTIF 0xb1 +#define RB_IWL_CMD_DTS_MEASUREMENT_NOTIF 0xdd +#define RB_IWL_CMD_ALIVE_NOTIF 0xc1 /* UCODE_ALIVE_NTFY */ /* ------------------------------------------------------------------ */ -/* MLD-specific notification command IDs. */ -/* MAC_CONF group (fw/api/mac-cfg.h) */ +/* Long group (0x1) command IDs. */ /* ------------------------------------------------------------------ */ -#define RB_IWL_MLD_ROC_NOTIF 0xF8 -#define RB_IWL_MLD_CHANNEL_SWITCH_ERROR_NOTIF 0xF9 -#define RB_IWL_MLD_SESSION_PROTECTION_NOTIF 0xFB -#define RB_IWL_MLD_PROBE_RESPONSE_DATA_NOTIF 0xFC -#define RB_IWL_MLD_CHANNEL_SWITCH_START_NOTIF 0xFF +#define RB_IWL_CMD_SCAN_CFG_CMD RB_IWL_WIDE_ID(RB_IWL_GRP_LONG, 0x0c) +#define RB_IWL_CMD_NVM_ACCESS RB_IWL_WIDE_ID(RB_IWL_GRP_LONG, 0x88) +#define RB_IWL_CMD_TX_ANT_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_LONG, 0x98) +#define RB_IWL_CMD_RSS_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_LONG, 0xb3) +#define RB_IWL_CMD_MCC_UPDATE RB_IWL_WIDE_ID(RB_IWL_GRP_LONG, 0xc8) +#define RB_IWL_CMD_SCAN_OFFLOAD_REQUEST RB_IWL_WIDE_ID(RB_IWL_GRP_LONG, 0x51) +#define RB_IWL_CMD_SCAN_OFFLOAD_ABORT RB_IWL_WIDE_ID(RB_IWL_GRP_LONG, 0x52) -/* DATA_PATH group (fw/api/datapath.h) */ -#define RB_IWL_MLD_MU_GROUP_MGMT_NOTIF 0xFE +/* ------------------------------------------------------------------ */ +/* System group (0x2) command IDs. */ +/* ------------------------------------------------------------------ */ +#define RB_IWL_CMD_INIT_EXTENDED_CFG RB_IWL_WIDE_ID(RB_IWL_GRP_SYSTEM, 0x03) +#define RB_IWL_CMD_FW_ERROR_RECOVERY RB_IWL_WIDE_ID(RB_IWL_GRP_SYSTEM, 0x07) +#define RB_IWL_CMD_SYSTEM_STATISTICS RB_IWL_WIDE_ID(RB_IWL_GRP_SYSTEM, 0x0f) +#define RB_IWL_CMD_SYSTEM_STATISTICS_END RB_IWL_WIDE_ID(RB_IWL_GRP_SYSTEM, 0xfd) -/* PHY_OPS group (fw/api/phy.h) */ -#define RB_IWL_MLD_DTS_MEASUREMENT_NOTIF_WIDE 0xFF +/* ------------------------------------------------------------------ */ +/* MAC_CONF group (0x3) command + notification IDs (fw/api/mac-cfg.h). */ +/* ------------------------------------------------------------------ */ +#define RB_IWL_CMD_LOW_LATENCY RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x03) +#define RB_IWL_CMD_SESSION_PROTECTION RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x05) +#define RB_IWL_CMD_CANCEL_CHANNEL_SWITCH RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x06) +#define RB_IWL_CMD_MAC_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x08) +#define RB_IWL_CMD_LINK_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x09) +#define RB_IWL_CMD_STA_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x0a) +#define RB_IWL_CMD_AUX_STA RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x0b) +#define RB_IWL_CMD_STA_REMOVE RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x0c) +#define RB_IWL_CMD_STA_DISABLE_TX RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x0d) +#define RB_IWL_CMD_ROC RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x0e) +#define RB_IWL_CMD_TWT_OPERATION RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x10) +#define RB_IWL_CMD_NAN_CFG RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0x12) -/* Legacy group (fw/api/commands.h, debug.h) */ -#define RB_IWL_MLD_MFUART_LOAD_NOTIF 0xb1 -#define RB_IWL_MLD_DTS_MEASUREMENT_NOTIF 0xdd +#define RB_IWL_NOTIF_MISSED_VAP RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xfa) +#define RB_IWL_NOTIF_NAN_ULW_ATTR RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xf2) +#define RB_IWL_NOTIF_NAN_SCHED_UPDATE RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xf3) +#define RB_IWL_NOTIF_NAN_DW_END RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xf4) +#define RB_IWL_NOTIF_NAN_JOINED_CLUSTER RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xf5) +#define RB_IWL_NOTIF_ROC RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xf8) +#define RB_IWL_NOTIF_CHANNEL_SWITCH_ERROR RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xf9) +#define RB_IWL_NOTIF_SESSION_PROTECTION RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xfb) +#define RB_IWL_NOTIF_PROBE_RESPONSE_DATA RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xfc) +#define RB_IWL_NOTIF_CHANNEL_SWITCH_START RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xff) +#define RB_IWL_NOTIF_MISSED_BEACONS RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xa2) +#define RB_IWL_NOTIF_SCAN_START_UMAC RB_IWL_WIDE_ID(RB_IWL_GRP_MAC_CONF, 0xb2) + +/* ------------------------------------------------------------------ */ +/* DATA_PATH group (0x5) command + notification IDs (fw/api/datapath.h).*/ +/* ------------------------------------------------------------------ */ +#define RB_IWL_CMD_DQA_ENABLE RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x00) +#define RB_IWL_CMD_UPDATE_MU_GROUPS RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x01) +#define RB_IWL_CMD_TRIGGER_RX_QUEUES RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x02) +#define RB_IWL_CMD_STA_HE_CTXT RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x07) +#define RB_IWL_CMD_RLC_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x08) +#define RB_IWL_CMD_RFH_QUEUE_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x0d) +#define RB_IWL_CMD_TLC_MNG_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x0f) +#define RB_IWL_CMD_HE_AIR_SNIFFER_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x13) +#define RB_IWL_CMD_CHEST_COLLECTOR_FILTER RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x14) +#define RB_IWL_CMD_RX_BAID_ALLOC RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x16) +#define RB_IWL_CMD_SCD_QUEUE_CONFIG RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0x17) +#define RB_IWL_NOTIF_MU_GROUP_MGMT RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0xfe) +#define RB_IWL_NOTIF_MONITOR RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0xab) +#define RB_IWL_NOTIF_TLC_MNG_UPDATE RB_IWL_WIDE_ID(RB_IWL_GRP_DATA_PATH, 0xfb) + +/* ------------------------------------------------------------------ */ +/* PHY_OPS group (0x4) command + notification IDs (fw/api/phy.h). */ +/* ------------------------------------------------------------------ */ +#define RB_IWL_CMD_DTS_MEASUREMENT_TRIGGER RB_IWL_WIDE_ID(RB_IWL_GRP_PHY_OPS, 0x00) +#define RB_IWL_NOTIF_CT_KILL RB_IWL_WIDE_ID(RB_IWL_GRP_PHY_OPS, 0x04) +#define RB_IWL_NOTIF_DTS_MEASUREMENT RB_IWL_WIDE_ID(RB_IWL_GRP_PHY_OPS, 0xff) + +/* ------------------------------------------------------------------ */ +/* STATISTICS group (0x10) notification IDs. */ +/* ------------------------------------------------------------------ */ +#define RB_IWL_NOTIF_STATISTICS_OPER RB_IWL_WIDE_ID(RB_IWL_GRP_STATISTICS, 0x01) +#define RB_IWL_NOTIF_STATISTICS_OPER_P1 RB_IWL_WIDE_ID(RB_IWL_GRP_STATISTICS, 0x05) +#define RB_IWL_NOTIF_STATISTICS_OPER_P2 RB_IWL_WIDE_ID(RB_IWL_GRP_STATISTICS, 0x06) + +/* ------------------------------------------------------------------ */ +/* SCAN group (0x6) command + notification IDs (fw/api/scan.h). */ +/* ------------------------------------------------------------------ */ +#define RB_IWL_CMD_SCAN_REQUEST_UMAC RB_IWL_WIDE_ID(RB_IWL_GRP_SCAN, 0x00) +#define RB_IWL_CMD_SCAN_ABORT_UMAC RB_IWL_WIDE_ID(RB_IWL_GRP_SCAN, 0x02) +#define RB_IWL_NOTIF_SCAN_ITER_COMPLETE RB_IWL_WIDE_ID(RB_IWL_GRP_SCAN, 0x0b) +#define RB_IWL_NOTIF_SCAN_COMPLETE_UMAC RB_IWL_WIDE_ID(RB_IWL_GRP_SCAN, 0x0c) +#define RB_IWL_NOTIF_MATCH_FOUND RB_IWL_WIDE_ID(RB_IWL_GRP_SCAN, 0x0d) +#define RB_IWL_NOTIF_CHANNEL_SURVEY RB_IWL_WIDE_ID(RB_IWL_GRP_SCAN, 0x13) + +/* ------------------------------------------------------------------ */ +/* Constants (Linux 7.1). */ +/* ------------------------------------------------------------------ */ +#define RB_IWL_MLD_MAX_LINKS 16 /* IWL_FW_MAX_LINKS */ +#define RB_IWL_MLD_NUM_MAC_INDEX_DRIVER (RB_IWL_MLD_MAX_LINKS + 1) +#define RB_IWL_MLD_MAX_TVQM_QUEUES 512 /* IWL_MAX_TVQM_QUEUES */ +#define RB_IWL_MLD_STATION_COUNT_MAX 16 /* IWL_STATION_COUNT_MAX */ +#define RB_IWL_MLD_MAX_ADDRESSES 2 +#define RB_IWL_MLD_AMPDU_REF_INIT 0 +#define RB_IWL_MLD_ERROR_RECOVERY_UPDATE_DB 1 + +/* ------------------------------------------------------------------ */ +/* MLD TX queue state (Linux 7.1 mld/tx.h struct iwl_mld_txq). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_txq { + uint16_t fw_id; + uint8_t allocated; + uint8_t stop_full; + int32_t tx_request; +}; + +static inline void rb_iwl_mld_init_txq(struct rb_iwl_mld_txq *txq) +{ + txq->fw_id = 0; + txq->allocated = 0; + txq->stop_full = 0; + txq->tx_request = 0; +} + +/* ------------------------------------------------------------------ */ +/* MLD scan state (Linux 7.1 mld/scan.h struct iwl_mld_scan). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_scan { + uint32_t running; + uint32_t suspend; + uint32_t is_continuous; + uint32_t is_mlo_scan; +}; + +/* ------------------------------------------------------------------ */ +/* MLD firmware status flags (Linux 7.1 mld/mld.h). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_fw_status { + uint32_t running; + uint32_t in_hw_restart; + uint32_t do_not_dump_once; +}; + +/* ------------------------------------------------------------------ */ +/* MLD radio kill state (Linux 7.1 mld/mld.h). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_radio_kill { + uint32_t hw; + uint32_t ct; +}; + +/* ------------------------------------------------------------------ */ +/* MLD core state (Linux 7.1 mld/mld.h struct iwl_mld, bounded subset).*/ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld { + struct rb_iwl_mld_fw_status fw_status; + struct rb_iwl_mld_radio_kill radio_kill; + struct rb_iwl_mld_scan scan; + uint32_t power_budget_mw; + uint32_t bt_is_active; + uint32_t bios_enable_puncturing; + /* Notification statistics */ + uint32_t rx_frames; + uint32_t rx_ba_notifs; + uint32_t rx_no_data; + uint32_t rx_tx_responses; + uint32_t rx_mld_specific; + uint32_t rx_unknown; + /* TX queue state */ + struct rb_iwl_mld_txq txqs[RB_IWL_MLD_MAX_TVQM_QUEUES]; +}; + +/* ------------------------------------------------------------------ */ +/* MLD notification result (decoded notification packet). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_notif_result { + int handled; + int is_rx_frame; + int signal; + int rate_mcs; + uint16_t wide_id; + uint8_t group; + uint8_t cmd_id; + const char *kind; +}; + +/* ------------------------------------------------------------------ */ +/* MLD firmware init result. */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_init_result { + int alive; + uint32_t ucode_flags; + uint32_t error; +}; + +/* ------------------------------------------------------------------ */ +/* MLD scan request (bounded subset of fw/api/scan.h). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_scan_params { + uint32_t channels[2]; /* 2.4/5 GHz channel count per band */ + uint32_t active_dwell; + uint32_t passive_dwell; + uint32_t max_out_time; + uint32_t suspend_time; + uint32_t n_ssids; + uint8_t flags; +}; + +#define RB_IWL_MLD_SCAN_FLAG_PASSIVE 0x00 +#define RB_IWL_MLD_SCAN_FLAG_ACTIVE 0x01 +#define RB_IWL_MLD_SCAN_FLAG_FRAGMENTED 0x02 + +/* ------------------------------------------------------------------ */ +/* MLD station add/modify parameters (fw/api/sta.h, fw/api/mac-cfg.h). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_sta_cmd { + uint32_t sta_id; + uint8_t mac_addr[6]; + uint16_t link_id; + uint32_t modify_mask; + uint32_t flags; +}; + +#define RB_IWL_MLD_STA_FLG_MODIFY 0x01 +#define RB_IWL_MLD_STA_FLG_REMOVE 0x02 + +/* ------------------------------------------------------------------ */ +/* MLD decoded RX MPDU info (extended beyond Mini-MVM for MLO). */ +/* ------------------------------------------------------------------ */ +struct rb_iwl_mld_rx_mpdu_info { + uint16_t mpdu_len; + uint8_t mac_phy_band; + uint8_t mac_flags1; + uint8_t mac_flags2; + int signal_dbm; + uint8_t channel; + int rate_mcs; + uint8_t is_mlo_link; + uint8_t link_id; +}; + +/* ------------------------------------------------------------------ */ +/* Public API */ +/* ------------------------------------------------------------------ */ + +void rb_iwl_mld_init(struct rb_iwl_mld *mld); +void rb_iwl_mld_handle_notification(struct rb_iwl_mld *mld, + uint16_t wide_id, + const uint8_t *payload, size_t len, + struct rb_iwl_mld_notif_result *out); +int rb_iwl_mld_firmware_init(struct rb_iwl_mld *mld, + struct rb_iwl_mld_init_result *out); +int rb_iwl_mld_start_scan(struct rb_iwl_mld *mld, + const struct rb_iwl_mld_scan_params *params); +int rb_iwl_mld_stop_scan(struct rb_iwl_mld *mld); +int rb_iwl_mld_add_sta(struct rb_iwl_mld *mld, + const struct rb_iwl_mld_sta_cmd *sta); +int rb_iwl_mld_remove_sta(struct rb_iwl_mld *mld, uint32_t sta_id); +int rb_iwl_mld_alloc_txq(struct rb_iwl_mld *mld, uint16_t *out_fw_id); +int rb_iwl_mld_free_txq(struct rb_iwl_mld *mld, uint16_t fw_id); +int rb_iwl_mld_parse_rx_mpdu(const uint8_t *payload, size_t len, + struct rb_iwl_mld_rx_mpdu_info *out); + +const char *rb_iwl_mld_name(void); +uint32_t rb_iwl_mld_rx_frames(const struct rb_iwl_mld *mld); #endif /* RB_IWLWIFI_MLD_H */ 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 b7d4c8d12a..7280e10e05 100644 --- a/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c +++ b/local/recipes/drivers/redbear-iwlwifi/source/src/linux_port.c @@ -269,6 +269,7 @@ 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,6 +1057,8 @@ 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; @@ -1530,6 +1533,12 @@ 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; @@ -2174,6 +2183,8 @@ 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; } @@ -2219,9 +2230,10 @@ 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 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 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", 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,