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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/link.c
Extension
.c
Size
40638 bytes
Lines
1355
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_link_chan_load_threshold {
	u8 high_lim;
	u8 low_lim;
};

static const struct iwl_mld_link_chan_load_threshold
link_chan_load_thresh_tbl[] = {
	[LINK_CHAN_LOAD_LVL1] = { .high_lim = 45, .low_lim = 40 },
	[LINK_CHAN_LOAD_LVL2] = { .high_lim = 70, .low_lim = 65 },
	[LINK_CHAN_LOAD_LVL3] = { .high_lim = 85, .low_lim = 80 },
};

int iwl_mld_send_link_cmd(struct iwl_mld *mld,
			  struct iwl_link_config_cmd *cmd,
			  enum iwl_ctxt_action action)
{
	int ret;

	lockdep_assert_wiphy(mld->wiphy);

	if (WARN_ON_ONCE(cmd->link_id == cpu_to_le32(FW_CTXT_ID_INVALID)))
		return -EINVAL;

	cmd->action = cpu_to_le32(action);
	ret = iwl_mld_send_cmd_pdu(mld,
				   WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD),
				   cmd);
	if (ret)
		IWL_ERR(mld, "Failed to send LINK_CONFIG_CMD (action:%d): %d\n",
			action, ret);
	return ret;
}

static int iwl_mld_add_link_to_fw(struct iwl_mld *mld,
				  struct ieee80211_bss_conf *link_conf)
{
	struct ieee80211_vif *vif = link_conf->vif;
	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
	struct iwl_mld_link *link = iwl_mld_link_from_mac80211(link_conf);
	struct iwl_link_config_cmd cmd = {};

	lockdep_assert_wiphy(mld->wiphy);

	if (WARN_ON(!link))
		return -EINVAL;

	cmd.link_id = cpu_to_le32(link->fw_id);
	cmd.mac_id = cpu_to_le32(mld_vif->fw_id);
	cmd.spec_link_id = link_conf->link_id;
	cmd.phy_id = cpu_to_le32(FW_CTXT_ID_INVALID);

	ether_addr_copy(cmd.local_link_addr, link_conf->addr);

	if (vif->type == NL80211_IFTYPE_ADHOC && link_conf->bssid)
		ether_addr_copy(cmd.ibss_bssid_addr, link_conf->bssid);

	return iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_ADD);
}

/* Get the basic rates of the used band and add the mandatory ones */
static void iwl_mld_fill_rates(struct iwl_mld *mld,
			       struct ieee80211_bss_conf *link,
			       struct ieee80211_chanctx_conf *chan_ctx,
			       __le32 *cck_rates, __le32 *ofdm_rates)
{
	struct cfg80211_chan_def *chandef =
		iwl_mld_get_chandef_from_chanctx(mld, chan_ctx);
	struct ieee80211_supported_band *sband =
		mld->hw->wiphy->bands[chandef->chan->band];
	unsigned long basic = link->basic_rates;
	int lowest_present_ofdm = 100;
	int lowest_present_cck = 100;
	u32 cck = 0;
	u32 ofdm = 0;
	int i;

	for_each_set_bit(i, &basic, BITS_PER_LONG) {
		int hw = sband->bitrates[i].hw_value;

		if (hw >= IWL_FIRST_OFDM_RATE) {
			ofdm |= BIT(hw - IWL_FIRST_OFDM_RATE);
			if (lowest_present_ofdm > hw)
				lowest_present_ofdm = hw;
		} else {
			BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);

			cck |= BIT(hw);
			if (lowest_present_cck > hw)
				lowest_present_cck = hw;
		}

Annotation

Implementation Notes