File Index
Files and directories
Sign in
FILE

mld.h

File preview with syntax highlighting.

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