drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
Extension
.c
Size
38788 bytes
Lines
1405
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_dbg_tlv_ver_data {
	int min_ver;
	int max_ver;
};

/**
 * struct iwl_dbg_tlv_timer_node - timer node struct
 * @list: list of &struct iwl_dbg_tlv_timer_node
 * @timer: timer
 * @fwrt: &struct iwl_fw_runtime
 * @tlv: TLV attach to the timer node
 */
struct iwl_dbg_tlv_timer_node {
	struct list_head list;
	struct timer_list timer;
	struct iwl_fw_runtime *fwrt;
	struct iwl_ucode_tlv *tlv;
};

static const struct iwl_dbg_tlv_ver_data
dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
	[IWL_DBG_TLV_TYPE_DEBUG_INFO]	= {.min_ver = 1, .max_ver = 1,},
	[IWL_DBG_TLV_TYPE_BUF_ALLOC]	= {.min_ver = 1, .max_ver = 1,},
	[IWL_DBG_TLV_TYPE_HCMD]		= {.min_ver = 1, .max_ver = 1,},
	[IWL_DBG_TLV_TYPE_REGION]	= {.min_ver = 1, .max_ver = 3,},
	[IWL_DBG_TLV_TYPE_TRIGGER]	= {.min_ver = 1, .max_ver = 1,},
	[IWL_DBG_TLV_TYPE_CONF_SET]	= {.min_ver = 1, .max_ver = 1,},
};

/* add a new TLV node, returning it so it can be modified */
static struct iwl_ucode_tlv *iwl_dbg_tlv_add(const struct iwl_ucode_tlv *tlv,
					     struct list_head *list)
{
	u32 len = le32_to_cpu(tlv->length);
	struct iwl_dbg_tlv_node *node;

	node = kzalloc_flex(*node, tlv.data, len);
	if (!node)
		return NULL;

	memcpy(&node->tlv, tlv, sizeof(node->tlv));
	memcpy(node->tlv.data, tlv->data, len);
	list_add_tail(&node->list, list);

	return &node->tlv;
}

static bool iwl_dbg_tlv_ver_support(const struct iwl_ucode_tlv *tlv)
{
	const struct iwl_fw_ini_header *hdr = (const void *)&tlv->data[0];
	u32 type = le32_to_cpu(tlv->type);
	u32 tlv_idx = type - IWL_UCODE_TLV_DEBUG_BASE;
	u32 ver = le32_to_cpu(hdr->version);

	if (ver < dbg_ver_table[tlv_idx].min_ver ||
	    ver > dbg_ver_table[tlv_idx].max_ver)
		return false;

	return true;
}

static int iwl_dbg_tlv_alloc_debug_info(struct iwl_trans *trans,
					const struct iwl_ucode_tlv *tlv)
{
	const struct iwl_fw_ini_debug_info_tlv *debug_info = (const void *)tlv->data;

	if (le32_to_cpu(tlv->length) != sizeof(*debug_info))
		return -EINVAL;

	/* we use this as a string, ensure input was NUL terminated */
	if (strnlen(debug_info->debug_cfg_name,
		    sizeof(debug_info->debug_cfg_name)) ==
			sizeof(debug_info->debug_cfg_name))
		return -EINVAL;

	IWL_DEBUG_FW(trans, "WRT: Loading debug cfg: %s\n",
		     debug_info->debug_cfg_name);

	if (!iwl_dbg_tlv_add(tlv, &trans->dbg.debug_info_tlv_list))
		return -ENOMEM;
	return 0;
}

static int iwl_dbg_tlv_alloc_buf_alloc(struct iwl_trans *trans,
				       const struct iwl_ucode_tlv *tlv)
{
	const struct iwl_fw_ini_allocation_tlv *alloc = (const void *)tlv->data;
	u32 buf_location;
	u32 alloc_id;

Annotation

Implementation Notes