1 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 2 /* 3 * Copyright (C) 2024-2025 Intel Corporation 4 */ 5 #ifndef __iwl_mld_h__ 6 #define __iwl_mld_h__ 7 8 #include <linux/leds.h> 9 #include <net/mac80211.h> 10 11 #include "iwl-trans.h" 12 #include "iwl-op-mode.h" 13 #include "fw/runtime.h" 14 #include "fw/notif-wait.h" 15 #include "fw/api/commands.h" 16 #include "fw/api/scan.h" 17 #include "fw/api/mac-cfg.h" 18 #include "fw/api/mac.h" 19 #include "fw/api/phy-ctxt.h" 20 #include "fw/api/datapath.h" 21 #include "fw/api/rx.h" 22 #include "fw/api/rs.h" 23 #include "fw/api/context.h" 24 #include "fw/api/coex.h" 25 #include "fw/api/location.h" 26 27 #include "fw/dbg.h" 28 29 #include "notif.h" 30 #include "scan.h" 31 #include "rx.h" 32 #include "thermal.h" 33 #include "low_latency.h" 34 #include "constants.h" 35 #include "ptp.h" 36 #include "time_sync.h" 37 #include "ftm-initiator.h" 38 #include "nan.h" 39 40 /** 41 * DOC: Introduction 42 * 43 * iwlmld is an operation mode (a.k.a. op_mode) for Intel wireless devices. 44 * It is used for devices that ship after 2024 which typically support 45 * the WiFi-7 features. MLD stands for multi-link device. Note that there are 46 * devices that do not support WiFi-7 or even WiFi 6E and yet use iwlmld, but 47 * the firmware APIs used in this driver are WiFi-7 compatible. 48 * 49 * In the architecture of iwlwifi, an op_mode is a layer that translates 50 * mac80211's APIs into commands for the firmware and, of course, notifications 51 * from the firmware to mac80211's APIs. An op_mode must implement the 52 * interface defined in iwl-op-mode.h to interact with the transport layer 53 * which allows to send and receive data to the device, start the hardware, 54 * etc... 55 */ 56 57 /** 58 * DOC: Locking policy 59 * 60 * iwlmld has a very simple locking policy: it doesn't have any mutexes. It 61 * relies on cfg80211's wiphy->mtx and takes the lock when needed. All the 62 * control flows originating from mac80211 already acquired the lock, so that 63 * part is trivial, but also notifications that are received from the firmware 64 * and handled asynchronously are handled only after having taken the lock. 65 * This is described in notif.c. 66 * There are spin_locks needed to synchronize with the data path, around the 67 * allocation of the queues, for example. 68 */ 69 70 /** 71 * DOC: Debugfs 72 * 73 * iwlmld adds its share of debugfs hooks and its handlers are synchronized 74 * with the wiphy_lock using wiphy_locked_debugfs. This avoids races against 75 * resources deletion while the debugfs hook is being used. 76 */ 77 78 /** 79 * DOC: Main resources 80 * 81 * iwlmld is designed with the life cycle of the resource in mind. The 82 * resources are: 83 * 84 * - struct iwl_mld (matches mac80211's struct ieee80211_hw) 85 * 86 * - struct iwl_mld_vif (matches macu80211's struct ieee80211_vif) 87 * iwl_mld_vif contains an array of pointers to struct iwl_mld_link 88 * which describe the links for this vif. 89 * 90 * - struct iwl_mld_sta (matches mac80211's struct ieee80211_sta) 91 * iwl_mld_sta contains an array of points to struct iwl_mld_link_sta 92 * which describes the link stations for this station 93 * 94 * Each object has properties that can survive a firmware reset or not. 95 * Asynchronous firmware notifications can declare themselves as dependent on a 96 * certain instance of those resources and that means that the notifications 97 * will be cancelled once the instance is destroyed. 98 */ 99 100 #define IWL_MLD_MAX_ADDRESSES 5 101 102 /** 103 * struct iwl_mld - MLD op mode 104 * 105 * @fw_id_to_bss_conf: maps a fw id of a link to the corresponding 106 * ieee80211_bss_conf. 107 * @fw_id_to_vif: maps a fw id of a MAC context to the corresponding 108 * ieee80211_vif. Mapping is valid only when the MAC exists in the fw. 109 * @fw_id_to_txq: maps a fw id of a txq to the corresponding 110 * ieee80211_txq. 111 * @used_phy_ids: a bitmap of the phy IDs used. If a bit is set, it means 112 * that the index of this bit is already used as a PHY id. 113 * @num_igtks: the number if iGTKs that were sent to the FW. 114 * @monitor: monitor related data 115 * @monitor.on: does a monitor vif exist (singleton hence bool) 116 * @monitor.ampdu_ref: the id of the A-MPDU for sniffer 117 * @monitor.ampdu_toggle: the state of the previous packet to track A-MPDU 118 * @monitor.cur_aid: current association id tracked by the sniffer 119 * @monitor.cur_bssid: current bssid tracked by the sniffer 120 * @monitor.ptp_time: set the Rx mactime using the device's PTP clock time 121 * @monitor.p80: primary channel position relative to he whole bandwidth, in 122 * steps of 80 MHz 123 * @monitor.phy: PHY data information 124 * @monitor.phy.data: PHY data (&struct iwl_rx_phy_air_sniffer_ntfy) received 125 * @monitor.phy.valid: PHY data is valid (was received) 126 * @monitor.phy.used: PHY data was used by an RX 127 * @fw_id_to_link_sta: maps a fw id of a sta to the corresponding 128 * ieee80211_link_sta. This is not cleaned up on restart since we want to 129 * preserve the fw sta ids during a restart (for SN/PN restoring). 130 * FW ids of internal stations will be mapped to ERR_PTR, and will be 131 * re-allocated during a restart, so make sure to free it in restart 132 * cleanup using iwl_mld_free_internal_sta 133 * @netdetect: indicates the FW is in suspend mode with netdetect configured 134 * @p2p_device_vif: points to the p2p device vif if exists 135 * @bt_is_active: indicates that BT is active 136 * @dev: pointer to device struct. For printing purposes 137 * @trans: pointer to the transport layer 138 * @cfg: pointer to the device configuration 139 * @fw: a pointer to the fw object 140 * @hw: pointer to the hw object. 141 * @wiphy: a pointer to the wiphy struct, for easier access to it. 142 * @ext_capab: extended capabilities that will be set to wiphy on registration. 143 * @sta_ext_capab: extended capabilities for the station interface. 144 * @nvm_data: pointer to the nvm_data that includes all our capabilities 145 * @fwrt: fw runtime data 146 * @debugfs_dir: debugfs directory 147 * @notif_wait: notification wait related data. 148 * @async_handlers_list: a list of all async RX handlers. When a notifciation 149 * with an async handler is received, it is added to this list. 150 * When &async_handlers_wk runs - it runs these handlers one by one. 151 * @async_handlers_lock: a lock for &async_handlers_list. Sync 152 * &async_handlers_wk and RX notifcation path. 153 * @async_handlers_wk: A work to run all async RX handlers from 154 * &async_handlers_list. 155 * @ct_kill_exit_wk: worker to exit thermal kill 156 * @fw_status: bitmap of fw status bits 157 * @running: true if the firmware is running 158 * @do_not_dump_once: true if firmware dump must be prevented once 159 * @in_d3: indicates FW is in suspend mode and should be resumed 160 * @resuming: indicates the driver is resuming from wowlan 161 * @in_hw_restart: indicates that we are currently in restart flow. 162 * rather than restarted. Should be unset upon restart. 163 * @radio_kill: bitmap of radio kill status 164 * @radio_kill.hw: radio is killed by hw switch 165 * @radio_kill.ct: radio is killed because the device it too hot 166 * @power_budget_mw: maximum cTDP power budget as defined for this system and 167 * device 168 * @addresses: device MAC addresses. 169 * @scan: instance of the scan object 170 * @channel_survey: channel survey information collected during scan 171 * @wowlan: WoWLAN support data. 172 * @debug_max_sleep: maximum sleep time in D3 (for debug purposes) 173 * @led: the led device 174 * @mcc_src: the source id of the MCC, comes from the firmware 175 * @bios_enable_puncturing: is puncturing enabled by bios 176 * @fw_id_to_ba: maps a fw (BA) id to a corresponding Block Ack session data. 177 * @num_rx_ba_sessions: tracks the number of active Rx Block Ack (BA) sessions. 178 * the driver ensures that new BA sessions are blocked once the maximum 179 * supported by the firmware is reached, preventing firmware asserts. 180 * @rxq_sync: manages RX queue sync state 181 * @txqs_to_add: a list of &ieee80211_txq's to allocate in &add_txqs_wk 182 * @add_txqs_wk: a worker to allocate txqs. 183 * @add_txqs_lock: to lock the &txqs_to_add list. 184 * @error_recovery_buf: pointer to the recovery buffer that will be read 185 * from firmware upon fw/hw error and sent back to the firmware in 186 * reconfig flow (after NIC reset). 187 * @mcast_filter_cmd: pointer to the multicast filter command. 188 * @mgmt_tx_ant: stores the last TX antenna index; used for setting 189 * TX rate_n_flags for non-STA mgmt frames (toggles on every TX failure). 190 * @set_tx_ant: stores the last TX antenna bitmask set by user space (if any) 191 * @set_rx_ant: stores the last RX antenna bitmask set by user space (if any) 192 * @fw_rates_ver_3: FW rates are in version 3 193 * @low_latency: low-latency manager. 194 * @tzone: thermal zone device's data 195 * @cooling_dev: cooling device's related data 196 * @ibss_manager: in IBSS mode (only one vif can be active), indicates what 197 * firmware indicated about having transmitted the last beacon, i.e. 198 * being IBSS manager for that time and needing to respond to probe 199 * requests 200 * @ptp_data: data of the PTP clock 201 * @time_sync: time sync data. 202 * @ftm_initiator: FTM initiator data 203 * @nan_device_vif: points to the NAN device vif if exists 204 */ 205 struct iwl_mld { 206 /* Add here fields that need clean up on restart */ 207 struct_group(zeroed_on_hw_restart, 208 struct ieee80211_bss_conf __rcu *fw_id_to_bss_conf[IWL_FW_MAX_LINK_ID + 1]; 209 struct ieee80211_vif __rcu *fw_id_to_vif[NUM_MAC_INDEX_DRIVER]; 210 struct ieee80211_txq __rcu *fw_id_to_txq[IWL_MAX_TVQM_QUEUES]; 211 u8 used_phy_ids: NUM_PHY_CTX; 212 u8 num_igtks; 213 struct { 214 bool on; 215 u32 ampdu_ref; 216 bool ampdu_toggle; 217 u8 p80; 218 struct { 219 struct iwl_rx_phy_air_sniffer_ntfy data; 220 u8 valid:1, used:1; 221 } phy; 222 #ifdef CONFIG_IWLWIFI_DEBUGFS 223 __le16 cur_aid; 224 u8 cur_bssid[ETH_ALEN]; 225 bool ptp_time; 226 #endif 227 } monitor; 228 #ifdef CONFIG_PM_SLEEP 229 bool netdetect; 230 #endif /* CONFIG_PM_SLEEP */ 231 struct ieee80211_vif *p2p_device_vif; 232 bool bt_is_active; 233 struct ieee80211_vif *nan_device_vif; 234 ); 235 struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX]; 236 /* And here fields that survive a fw restart */ 237 struct device *dev; 238 struct iwl_trans *trans; 239 const struct iwl_rf_cfg *cfg; 240 const struct iwl_fw *fw; 241 struct ieee80211_hw *hw; 242 struct wiphy *wiphy; 243 struct wiphy_iftype_ext_capab ext_capab[IWL_MLD_EXT_CAPA_NUM_IFTYPES]; 244 u8 sta_ext_capab[IWL_MLD_STA_EXT_CAPA_SIZE]; 245 struct iwl_nvm_data *nvm_data; 246 struct iwl_fw_runtime fwrt; 247 struct dentry *debugfs_dir; 248 struct iwl_notif_wait_data notif_wait; 249 struct list_head async_handlers_list; 250 spinlock_t async_handlers_lock; 251 struct wiphy_work async_handlers_wk; 252 struct wiphy_delayed_work ct_kill_exit_wk; 253 254 struct { 255 u32 running:1, 256 do_not_dump_once:1, 257 #ifdef CONFIG_PM_SLEEP 258 in_d3:1, 259 resuming:1, 260 #endif 261 in_hw_restart:1; 262 263 } fw_status; 264 265 struct { 266 u32 hw:1, 267 ct:1; 268 } radio_kill; 269 270 u32 power_budget_mw; 271 272 struct mac_address addresses[IWL_MLD_MAX_ADDRESSES]; 273 struct iwl_mld_scan scan; 274 struct iwl_mld_survey *channel_survey; 275 #ifdef CONFIG_PM_SLEEP 276 struct wiphy_wowlan_support wowlan; 277 u32 debug_max_sleep; 278 #endif /* CONFIG_PM_SLEEP */ 279 #ifdef CONFIG_IWLWIFI_LEDS 280 struct led_classdev led; 281 #endif 282 enum iwl_mcc_source mcc_src; 283 bool bios_enable_puncturing; 284 285 struct iwl_mld_baid_data __rcu *fw_id_to_ba[IWL_MAX_BAID]; 286 u8 num_rx_ba_sessions; 287 288 struct iwl_mld_rx_queues_sync rxq_sync; 289 290 struct list_head txqs_to_add; 291 struct wiphy_work add_txqs_wk; 292 spinlock_t add_txqs_lock; 293 294 u8 *error_recovery_buf; 295 struct iwl_mcast_filter_cmd *mcast_filter_cmd; 296 297 u8 mgmt_tx_ant; 298 299 u8 set_tx_ant; 300 u8 set_rx_ant; 301 302 bool fw_rates_ver_3; 303 304 struct iwl_mld_low_latency low_latency; 305 306 bool ibss_manager; 307 #ifdef CONFIG_THERMAL 308 struct thermal_zone_device *tzone; 309 struct iwl_mld_cooling_device cooling_dev; 310 #endif 311 312 struct ptp_data ptp_data; 313 314 struct iwl_mld_time_sync_data __rcu *time_sync; 315 316 struct ftm_initiator_data ftm_initiator; 317 }; 318 319 /* memset the part of the struct that requires cleanup on restart */ 320 #define CLEANUP_STRUCT(_ptr) \ 321 memset((void *)&(_ptr)->zeroed_on_hw_restart, 0, \ 322 sizeof((_ptr)->zeroed_on_hw_restart)) 323 324 /* Cleanup function for struct iwl_mld, will be called in restart */ 325 static inline void 326 iwl_cleanup_mld(struct iwl_mld *mld) 327 { 328 CLEANUP_STRUCT(mld); 329 CLEANUP_STRUCT(&mld->scan); 330 331 #ifdef CONFIG_PM_SLEEP 332 mld->fw_status.in_d3 = false; 333 #endif 334 335 iwl_mld_low_latency_restart_cleanup(mld); 336 } 337 338 enum iwl_power_scheme { 339 IWL_POWER_SCHEME_CAM = 1, 340 IWL_POWER_SCHEME_BPS, 341 }; 342 343 /** 344 * struct iwl_mld_mod_params - module parameters for iwlmld 345 * @power_scheme: one of enum iwl_power_scheme 346 */ 347 struct iwl_mld_mod_params { 348 int power_scheme; 349 }; 350 351 extern struct iwl_mld_mod_params iwlmld_mod_params; 352 353 /* Extract MLD priv from op_mode */ 354 #define IWL_OP_MODE_GET_MLD(_iwl_op_mode) \ 355 ((struct iwl_mld *)(_iwl_op_mode)->op_mode_specific) 356 357 #define IWL_MAC80211_GET_MLD(_hw) \ 358 IWL_OP_MODE_GET_MLD((struct iwl_op_mode *)((_hw)->priv)) 359 360 #ifdef CONFIG_IWLWIFI_DEBUGFS 361 void 362 iwl_mld_add_debugfs_files(struct iwl_mld *mld, struct dentry *debugfs_dir); 363 #else 364 static inline void 365 iwl_mld_add_debugfs_files(struct iwl_mld *mld, struct dentry *debugfs_dir) 366 {} 367 #endif 368 369 int iwl_mld_load_fw(struct iwl_mld *mld); 370 void iwl_mld_stop_fw(struct iwl_mld *mld); 371 int iwl_mld_start_fw(struct iwl_mld *mld); 372 void iwl_mld_send_recovery_cmd(struct iwl_mld *mld, u32 flags); 373 374 static inline void iwl_mld_set_ctkill(struct iwl_mld *mld, bool state) 375 { 376 mld->radio_kill.ct = state; 377 378 wiphy_rfkill_set_hw_state(mld->wiphy, 379 mld->radio_kill.hw || mld->radio_kill.ct); 380 } 381 382 static inline void iwl_mld_set_hwkill(struct iwl_mld *mld, bool state) 383 { 384 mld->radio_kill.hw = state; 385 386 wiphy_rfkill_set_hw_state(mld->wiphy, 387 mld->radio_kill.hw || mld->radio_kill.ct); 388 } 389 390 static inline u8 iwl_mld_get_valid_tx_ant(const struct iwl_mld *mld) 391 { 392 u8 tx_ant = mld->fw->valid_tx_ant; 393 394 if (mld->nvm_data && mld->nvm_data->valid_tx_ant) 395 tx_ant &= mld->nvm_data->valid_tx_ant; 396 397 if (mld->set_tx_ant) 398 tx_ant &= mld->set_tx_ant; 399 400 return tx_ant; 401 } 402 403 static inline u8 iwl_mld_get_valid_rx_ant(const struct iwl_mld *mld) 404 { 405 u8 rx_ant = mld->fw->valid_rx_ant; 406 407 if (mld->nvm_data && mld->nvm_data->valid_rx_ant) 408 rx_ant &= mld->nvm_data->valid_rx_ant; 409 410 if (mld->set_rx_ant) 411 rx_ant &= mld->set_rx_ant; 412 413 return rx_ant; 414 } 415 416 static inline u8 iwl_mld_nl80211_band_to_fw(enum nl80211_band band) 417 { 418 switch (band) { 419 case NL80211_BAND_2GHZ: 420 return PHY_BAND_24; 421 case NL80211_BAND_5GHZ: 422 return PHY_BAND_5; 423 case NL80211_BAND_6GHZ: 424 return PHY_BAND_6; 425 default: 426 WARN_ONCE(1, "Unsupported band (%u)\n", band); 427 return PHY_BAND_5; 428 } 429 } 430 431 static inline u8 iwl_mld_phy_band_to_nl80211(u8 phy_band) 432 { 433 switch (phy_band) { 434 case PHY_BAND_24: 435 return NL80211_BAND_2GHZ; 436 case PHY_BAND_5: 437 return NL80211_BAND_5GHZ; 438 case PHY_BAND_6: 439 return NL80211_BAND_6GHZ; 440 default: 441 WARN_ONCE(1, "Unsupported phy band (%u)\n", phy_band); 442 return NL80211_BAND_5GHZ; 443 } 444 } 445 446 static inline int 447 iwl_mld_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags, 448 enum nl80211_band band) 449 { 450 int format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK; 451 int rate = rate_n_flags & RATE_LEGACY_RATE_MSK; 452 bool is_lb = band == NL80211_BAND_2GHZ; 453 454 if (format == RATE_MCS_MOD_TYPE_LEGACY_OFDM) 455 return is_lb ? rate + IWL_FIRST_OFDM_RATE : rate; 456 457 /* CCK is not allowed in 5 GHz */ 458 return is_lb ? rate : -1; 459 } 460 461 extern const struct ieee80211_ops iwl_mld_hw_ops; 462 463 /** 464 * enum iwl_rx_handler_context: context for Rx handler 465 * @RX_HANDLER_SYNC: this means that it will be called in the Rx path 466 * which can't acquire the wiphy->mutex. 467 * @RX_HANDLER_ASYNC: If the handler needs to hold wiphy->mutex 468 * (and only in this case!), it should be set as ASYNC. In that case, 469 * it will be called from a worker with wiphy->mutex held. 470 */ 471 enum iwl_rx_handler_context { 472 RX_HANDLER_SYNC, 473 RX_HANDLER_ASYNC, 474 }; 475 476 /** 477 * struct iwl_rx_handler: handler for FW notification 478 * @val_fn: input validation function. 479 * @sizes: an array that mapps a version to the expected size. 480 * @fn: the function is called when notification is handled 481 * @cmd_id: command id 482 * @n_sizes: number of elements in &sizes. 483 * @context: see &iwl_rx_handler_context 484 * @obj_type: the type of the object that this handler is related to. 485 * See &iwl_mld_object_type. Use IWL_MLD_OBJECT_TYPE_NONE if not related. 486 * @cancel: function to cancel the notification. valid only if obj_type is not 487 * IWL_MLD_OBJECT_TYPE_NONE. 488 */ 489 struct iwl_rx_handler { 490 union { 491 bool (*val_fn)(struct iwl_mld *mld, struct iwl_rx_packet *pkt); 492 const struct iwl_notif_struct_size *sizes; 493 }; 494 void (*fn)(struct iwl_mld *mld, struct iwl_rx_packet *pkt); 495 u16 cmd_id; 496 u8 n_sizes; 497 u8 context; 498 enum iwl_mld_object_type obj_type; 499 bool (*cancel)(struct iwl_mld *mld, struct iwl_rx_packet *pkt, 500 u32 obj_id); 501 }; 502 503 /** 504 * struct iwl_notif_struct_size: map a notif ver to the expected size 505 * 506 * @size: the size to expect 507 * @ver: the version of the notification 508 */ 509 struct iwl_notif_struct_size { 510 u32 size:24, ver:8; 511 }; 512 513 #if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) 514 extern const struct iwl_hcmd_arr iwl_mld_groups[]; 515 extern const unsigned int global_iwl_mld_goups_size; 516 extern const struct iwl_rx_handler iwl_mld_rx_handlers[]; 517 extern const unsigned int iwl_mld_rx_handlers_num; 518 519 bool 520 iwl_mld_is_dup(struct iwl_mld *mld, struct ieee80211_sta *sta, 521 struct ieee80211_hdr *hdr, 522 const struct iwl_rx_mpdu_desc *mpdu_desc, 523 struct ieee80211_rx_status *rx_status, int queue); 524 525 void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans, 526 const struct iwl_rf_cfg *cfg, const struct iwl_fw *fw, 527 struct ieee80211_hw *hw, struct dentry *dbgfs_dir); 528 #endif 529 530 #define IWL_MLD_INVALID_FW_ID 0xff 531 532 #define IWL_MLD_ALLOC_FN(_type, _mac80211_type) \ 533 static int \ 534 iwl_mld_allocate_##_type##_fw_id(struct iwl_mld *mld, \ 535 u8 *fw_id, \ 536 struct ieee80211_##_mac80211_type *mac80211_ptr) \ 537 { \ 538 u8 rand = IWL_MLD_DIS_RANDOM_FW_ID ? 0 : get_random_u8(); \ 539 u8 arr_sz = ARRAY_SIZE(mld->fw_id_to_##_mac80211_type); \ 540 if (__builtin_types_compatible_p(typeof(*mac80211_ptr), \ 541 struct ieee80211_link_sta)) \ 542 arr_sz = mld->fw->ucode_capa.num_stations; \ 543 if (__builtin_types_compatible_p(typeof(*mac80211_ptr), \ 544 struct ieee80211_bss_conf)) \ 545 arr_sz = mld->fw->ucode_capa.num_links; \ 546 for (int i = 0; i < arr_sz; i++) { \ 547 u8 idx = (i + rand) % arr_sz; \ 548 if (rcu_access_pointer(mld->fw_id_to_##_mac80211_type[idx])) \ 549 continue; \ 550 IWL_DEBUG_INFO(mld, "Allocated at index %d / %d\n", idx, arr_sz); \ 551 *fw_id = idx; \ 552 rcu_assign_pointer(mld->fw_id_to_##_mac80211_type[idx], mac80211_ptr); \ 553 return 0; \ 554 } \ 555 return -ENOSPC; \ 556 } 557 558 static inline struct ieee80211_bss_conf * 559 iwl_mld_fw_id_to_link_conf(struct iwl_mld *mld, u8 fw_link_id) 560 { 561 if (IWL_FW_CHECK(mld, fw_link_id >= mld->fw->ucode_capa.num_links, 562 "Invalid fw_link_id: %d\n", fw_link_id)) 563 return NULL; 564 565 return wiphy_dereference(mld->wiphy, 566 mld->fw_id_to_bss_conf[fw_link_id]); 567 } 568 569 #define MSEC_TO_TU(_msec) ((_msec) * 1000 / 1024) 570 571 void iwl_mld_add_vif_debugfs(struct ieee80211_hw *hw, 572 struct ieee80211_vif *vif); 573 void iwl_mld_add_link_debugfs(struct ieee80211_hw *hw, 574 struct ieee80211_vif *vif, 575 struct ieee80211_bss_conf *link_conf, 576 struct dentry *dir); 577 void iwl_mld_add_link_sta_debugfs(struct ieee80211_hw *hw, 578 struct ieee80211_vif *vif, 579 struct ieee80211_link_sta *link_sta, 580 struct dentry *dir); 581 582 /* Utilities */ 583 584 static inline u8 iwl_mld_mac80211_ac_to_fw_tx_fifo(enum ieee80211_ac_numbers ac) 585 { 586 static const u8 mac80211_ac_to_fw_tx_fifo[] = { 587 IWL_BZ_EDCA_TX_FIFO_VO, 588 IWL_BZ_EDCA_TX_FIFO_VI, 589 IWL_BZ_EDCA_TX_FIFO_BE, 590 IWL_BZ_EDCA_TX_FIFO_BK, 591 IWL_BZ_TRIG_TX_FIFO_VO, 592 IWL_BZ_TRIG_TX_FIFO_VI, 593 IWL_BZ_TRIG_TX_FIFO_BE, 594 IWL_BZ_TRIG_TX_FIFO_BK, 595 }; 596 return mac80211_ac_to_fw_tx_fifo[ac]; 597 } 598 599 static inline u32 600 iwl_mld_get_lmac_id(struct iwl_mld *mld, enum nl80211_band band) 601 { 602 if (!fw_has_capa(&mld->fw->ucode_capa, 603 IWL_UCODE_TLV_CAPA_CDB_SUPPORT) || 604 band == NL80211_BAND_2GHZ) 605 return IWL_LMAC_24G_INDEX; 606 return IWL_LMAC_5G_INDEX; 607 } 608 609 /* Check if we had an error, but reconfig flow didn't start yet */ 610 static inline bool iwl_mld_error_before_recovery(struct iwl_mld *mld) 611 { 612 return mld->fw_status.in_hw_restart && 613 !iwl_trans_fw_running(mld->trans); 614 } 615 616 int iwl_mld_tdls_sta_count(struct iwl_mld *mld); 617 618 #endif /* __iwl_mld_h__ */ 619