drivers/net/wireless/intel/iwlwifi/mld/mlo.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/mld/mlo.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/mlo.c
Extension
.c
Size
35831 bytes
Lines
1257
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct iwl_mld_update_emlsr_block_data {
	bool block;
	enum iwl_mld_emlsr_blocked reason;
	int result;
};

static void
iwl_mld_vif_iter_update_emlsr_block(void *_data, u8 *mac,
				    struct ieee80211_vif *vif)
{
	struct iwl_mld_update_emlsr_block_data *data = _data;
	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
	int ret;

	if (!iwl_mld_vif_has_emlsr_cap(vif))
		return;

	if (data->block) {
		ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif,
					       data->reason,
					       iwl_mld_get_primary_link(vif));
		if (ret)
			data->result = ret;
	} else {
		iwl_mld_unblock_emlsr(mld_vif->mld, vif,
				      data->reason);
	}
}

int iwl_mld_update_emlsr_block(struct iwl_mld *mld, bool block,
			       enum iwl_mld_emlsr_blocked reason)
{
	struct iwl_mld_update_emlsr_block_data block_data = {
		.block = block,
		.reason = reason,
	};

	ieee80211_iterate_active_interfaces_mtx(mld->hw,
						IEEE80211_IFACE_ITER_NORMAL,
						iwl_mld_vif_iter_update_emlsr_block,
						&block_data);

	return block_data.result;
}

int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld,
				      int pending_link_changes)
{
	/* An active link of a non-station vif blocks EMLSR. Upon activation
	 * block EMLSR on the bss vif. Upon deactivation, check if this link
	 * was the last non-station link active, and if so unblock the bss vif
	 */
	int count = pending_link_changes;

	/* No need to count if we are activating a non-BSS link */
	if (count <= 0)
		ieee80211_iterate_active_interfaces_mtx(mld->hw,
							IEEE80211_IFACE_ITER_NORMAL,
							iwl_mld_count_non_bss_links,
							&count);

	/*
	 * We could skip updating it if the block change did not change (and
	 * pending_link_changes is non-zero).
	 */
	return iwl_mld_update_emlsr_block(mld, !!count,
					  IWL_MLD_EMLSR_BLOCKED_NON_BSS);
}

#define EMLSR_SEC_LINK_MIN_PERC 10
#define EMLSR_MIN_TX 3000
#define EMLSR_MIN_RX 400

void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
{
	struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif,
						   emlsr.check_tpt_wk.work);
	struct ieee80211_vif *vif =
		container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
	struct iwl_mld *mld = mld_vif->mld;
	struct iwl_mld_sta *mld_sta;
	struct iwl_mld_link *sec_link;
	unsigned long total_tx = 0, total_rx = 0;
	unsigned long sec_link_tx = 0, sec_link_rx = 0;
	u8 sec_link_tx_perc, sec_link_rx_perc;
	s8 sec_link_id;

	if (!iwl_mld_vif_has_emlsr_cap(vif) || !mld_vif->ap_sta)
		return;

Annotation

Implementation Notes