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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
Extension
.c
Size
84817 bytes
Lines
2983
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_mc_iter_data {
	struct iwl_mld *mld;
	int port_id;
};

static void iwl_mld_mc_iface_iterator(void *data, u8 *mac,
				      struct ieee80211_vif *vif)
{
	struct iwl_mld_mc_iter_data *mc_data = data;
	struct iwl_mld *mld = mc_data->mld;
	struct iwl_mcast_filter_cmd *cmd = mld->mcast_filter_cmd;
	struct iwl_host_cmd hcmd = {
		.id = MCAST_FILTER_CMD,
		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
	};
	int ret, len;

	/* If we don't have free ports, mcast frames will be dropped */
	if (WARN_ON_ONCE(mc_data->port_id >= MAX_PORT_ID_NUM))
		return;

	if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
		return;

	cmd->port_id = mc_data->port_id++;
	ether_addr_copy(cmd->bssid, vif->bss_conf.bssid);
	len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);

	hcmd.len[0] = len;
	hcmd.data[0] = cmd;

	ret = iwl_mld_send_cmd(mld, &hcmd);
	if (ret)
		IWL_ERR(mld, "mcast filter cmd error. ret=%d\n", ret);
}

void iwl_mld_recalc_multicast_filter(struct iwl_mld *mld)
{
	struct iwl_mld_mc_iter_data iter_data = {
		.mld = mld,
	};

	if (WARN_ON_ONCE(!mld->mcast_filter_cmd))
		return;

	ieee80211_iterate_active_interfaces(mld->hw,
					    IEEE80211_IFACE_ITER_NORMAL,
					    iwl_mld_mc_iface_iterator,
					    &iter_data);
}

static u64
iwl_mld_mac80211_prepare_multicast(struct ieee80211_hw *hw,
				   struct netdev_hw_addr_list *mc_list)
{
	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
	struct iwl_mcast_filter_cmd *cmd;
	struct netdev_hw_addr *addr;
	int addr_count = netdev_hw_addr_list_count(mc_list);
	bool pass_all = addr_count > MAX_MCAST_FILTERING_ADDRESSES;
	int len;

	if (pass_all)
		addr_count = 0;

	/* len must be a multiple of 4 */
	len = roundup(sizeof(*cmd) + addr_count * ETH_ALEN, 4);
	cmd = kzalloc(len, GFP_ATOMIC);
	if (!cmd)
		return 0;

	if (pass_all) {
		cmd->pass_all = 1;
		goto out;
	}

	netdev_hw_addr_list_for_each(addr, mc_list) {
		IWL_DEBUG_MAC80211(mld, "mcast addr (%d): %pM\n",
				   cmd->count, addr->addr);
		ether_addr_copy(&cmd->addr_list[cmd->count * ETH_ALEN],
				addr->addr);
		cmd->count++;
	}

out:
	return (u64)(unsigned long)cmd;
}

static
void iwl_mld_mac80211_configure_filter(struct ieee80211_hw *hw,

Annotation

Implementation Notes