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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/mcc.c
Extension
.c
Size
7447 bytes
Lines
295
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

// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright (C) 2024-2026 Intel Corporation
 */

#include <net/cfg80211.h>
#include <net/mac80211.h>

#include <fw/dbg.h>
#include <iwl-nvm-parse.h>

#include "mld.h"
#include "hcmd.h"
#include "mcc.h"

/* It is the caller's responsibility to free the pointer returned here */
static struct iwl_mcc_update_resp_v8 *
iwl_mld_copy_mcc_resp(const struct iwl_rx_packet *pkt)
{
	const struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (const void *)pkt->data;
	int n_channels = __le32_to_cpu(mcc_resp_v8->n_channels);
	struct iwl_mcc_update_resp_v8 *resp_cp;
	int notif_len = struct_size(resp_cp, channels, n_channels);

	if (iwl_rx_packet_payload_len(pkt) != notif_len)
		return ERR_PTR(-EINVAL);

	resp_cp = kmemdup(mcc_resp_v8, notif_len, GFP_KERNEL);
	if (!resp_cp)
		return ERR_PTR(-ENOMEM);

	return resp_cp;
}

/* It is the caller's responsibility to free the pointer returned here */
static struct iwl_mcc_update_resp_v8 *
iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2,
		   enum iwl_mcc_source src_id)
{
	struct iwl_mcc_update_cmd mcc_update_cmd = {
		.mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]),
		.source_id = (u8)src_id,
	};
	struct iwl_mcc_update_resp_v8 *resp_cp;
	struct iwl_rx_packet *pkt;
	struct iwl_host_cmd cmd = {
		.id = MCC_UPDATE_CMD,
		.flags = CMD_WANT_SKB,
		.data = { &mcc_update_cmd },
		.len[0] = sizeof(mcc_update_cmd),
	};
	int ret;
	u16 mcc;

	IWL_DEBUG_LAR(mld, "send MCC update to FW with '%c%c' src = %d\n",
		      alpha2[0], alpha2[1], src_id);

	ret = iwl_mld_send_cmd(mld, &cmd);
	if (ret)
		return ERR_PTR(ret);

	pkt = cmd.resp_pkt;

	resp_cp = iwl_mld_copy_mcc_resp(pkt);
	if (IS_ERR(resp_cp))
		goto exit;

	mcc = le16_to_cpu(resp_cp->mcc);

	IWL_FW_CHECK(mld, !mcc, "mcc can't be 0: %d\n", mcc);

	IWL_DEBUG_LAR(mld,
		      "MCC response status: 0x%x. new MCC: 0x%x ('%c%c')\n",
		      le32_to_cpu(resp_cp->status), mcc, mcc >> 8, mcc & 0xff);

exit:
	iwl_free_resp(&cmd);
	return resp_cp;
}

/* It is the caller's responsibility to free the pointer returned here */
struct ieee80211_regdomain *
iwl_mld_get_regdomain(struct iwl_mld *mld,
		      const char *alpha2,
		      enum iwl_mcc_source src_id,
		      bool *changed)
{
	struct ieee80211_regdomain *regd = NULL;
	struct iwl_mcc_update_resp_v8 *resp;
	u8 resp_ver = iwl_fw_lookup_notif_ver(mld->fw, IWL_ALWAYS_LONG_GROUP,

Annotation

Implementation Notes