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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/tlc.c
Extension
.c
Size
27886 bytes
Lines
925
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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_tlc_sta_capa {
	u16 non_ht_rates;
	u16 max_amsdu_len;
	u8 rx_nss;
	enum ieee80211_sta_rx_bandwidth bandwidth;
	enum ieee80211_smps_mode smps_mode;
	const struct ieee80211_sta_ht_cap *ht_cap;
	const struct ieee80211_sta_vht_cap *vht_cap;
	const struct ieee80211_sta_he_cap *he_cap;
	const struct ieee80211_sta_eht_cap *eht_cap;
	const struct ieee80211_sta_uhr_cap *uhr_cap;

	const struct ieee80211_sta_he_cap *own_he_cap;
	const struct ieee80211_sta_eht_cap *own_eht_cap;
	const struct ieee80211_sta_uhr_cap *own_uhr_cap;
};

static __le16
iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld,
			  struct iwl_mld_tlc_sta_capa *capa)
{
	const struct ieee80211_sta_ht_cap *ht_cap = capa->ht_cap;
	const struct ieee80211_sta_vht_cap *vht_cap = capa->vht_cap;
	const struct ieee80211_sta_he_cap *he_cap = capa->he_cap;
	const struct ieee80211_sta_eht_cap *eht_cap = capa->eht_cap;
	const struct ieee80211_sta_uhr_cap *uhr_cap = capa->uhr_cap;
	const struct ieee80211_sta_he_cap *own_he_cap = capa->own_he_cap;
	const struct ieee80211_sta_eht_cap *own_eht_cap = capa->own_eht_cap;
	const struct ieee80211_sta_uhr_cap *own_uhr_cap = capa->own_uhr_cap;
	bool has_vht = vht_cap && vht_cap->vht_supported;
	u16 flags = 0;

	/* STBC flags */
	if (mld->cfg->ht_params.stbc &&
	    (hweight8(iwl_mld_get_valid_tx_ant(mld)) > 1)) {
		if (he_cap && he_cap->has_he &&
		    he_cap->he_cap_elem.phy_cap_info[2] &
				IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
			flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
		else if (vht_cap &&
			 vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
			flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
		else if (ht_cap && ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)
			flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
	}

	/* LDPC */
	if (mld->cfg->ht_params.ldpc &&
	    ((ht_cap && ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) ||
	     (has_vht && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
		flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;

	if (he_cap && he_cap->has_he &&
	    (he_cap->he_cap_elem.phy_cap_info[1] &
			IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
		flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;

	if (own_he_cap &&
	    !(own_he_cap->he_cap_elem.phy_cap_info[1] &
			IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
		flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;

	/* DCM */
	if (he_cap && he_cap->has_he &&
	    (he_cap->he_cap_elem.phy_cap_info[3] &
	     IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK &&
	     own_he_cap &&
	     own_he_cap->he_cap_elem.phy_cap_info[3] &
			IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK))
		flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;

	/* Extra EHT LTF */
	if (own_eht_cap &&
	    own_eht_cap->eht_cap_elem.phy_cap_info[5] &
			IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF &&
	    eht_cap && eht_cap->has_eht &&
	    eht_cap->eht_cap_elem.phy_cap_info[5] &
			IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) {
		flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK;
	}

	if (uhr_cap && uhr_cap->has_uhr && own_uhr_cap &&
	    uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX) &&
	    own_uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_TX))
		flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK |
			 IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK;

	return cpu_to_le16(flags);
}

Annotation

Implementation Notes