Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68f6f492 authored by Sara Sharon's avatar Sara Sharon Committed by Luca Coelho
Browse files

iwlwifi: trans: support loading ini TLVs from external file



Support loading and storing ini TLVs from external
file. Those TLVs are appended to the default TLVs,
so store them separately.

Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent f14cda6f
Loading
Loading
Loading
Loading
+76 −5
Original line number Diff line number Diff line
@@ -63,7 +63,8 @@
#include "iwl-trans.h"
#include "iwl-dbg-tlv.h"

void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv)
void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
			 bool ext)
{
	struct iwl_apply_point_data *data;
	struct iwl_fw_ini_header *header = (void *)&tlv->data[0];
@@ -75,6 +76,9 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv)
		      "Invalid apply point id %d\n", apply_point))
		return;

	if (ext)
		data = &trans->apply_points_ext[apply_point];
	else
		data = &trans->apply_points[apply_point];

	/*
@@ -90,7 +94,8 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv)
	data->offset += copy_size;
}

void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data)
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
		       bool ext)
{
	struct iwl_ucode_tlv *tlv;
	u32 size[IWL_FW_INI_APPLY_NUM] = {0};
@@ -137,10 +142,15 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data)
			return;
		}

		if (ext) {
			trans->apply_points_ext[i].data = mem;
			trans->apply_points_ext[i].size = size[i];
		} else {
			trans->apply_points[i].data = mem;
			trans->apply_points[i].size = size[i];
		}
	}
}

void iwl_fw_dbg_free(struct iwl_trans *trans)
{
@@ -150,5 +160,66 @@ void iwl_fw_dbg_free(struct iwl_trans *trans)
		kfree(trans->apply_points[i].data);
		trans->apply_points[i].size = 0;
		trans->apply_points[i].offset = 0;

		kfree(trans->apply_points_ext[i].data);
		trans->apply_points_ext[i].size = 0;
		trans->apply_points_ext[i].offset = 0;
	}
}

static int iwl_parse_fw_dbg_tlv(struct iwl_trans *trans, const u8 *data,
				size_t len)
{
	struct iwl_ucode_tlv *tlv;
	enum iwl_ucode_tlv_type tlv_type;
	u32 tlv_len;

	while (len >= sizeof(*tlv)) {
		len -= sizeof(*tlv);
		tlv = (void *)data;

		tlv_len = le32_to_cpu(tlv->length);
		tlv_type = le32_to_cpu(tlv->type);

		if (len < tlv_len) {
			IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
				len, tlv_len);
			return -EINVAL;
		}
		len -= ALIGN(tlv_len, 4);
		data += sizeof(*tlv) + ALIGN(tlv_len, 4);

		switch (tlv_type) {
		case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
		case IWL_UCODE_TLV_TYPE_HCMD:
		case IWL_UCODE_TLV_TYPE_REGIONS:
		case IWL_UCODE_TLV_TYPE_TRIGGERS:
		case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
			iwl_fw_dbg_copy_tlv(trans, tlv, true);
		default:
			WARN_ONCE(1, "Invalid TLV %x\n", tlv_type);
			break;
		}
	}

	return 0;
}

void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans)
{
	const struct firmware *fw;
	int res;

	if (trans->external_ini_loaded || !iwlwifi_mod_params.enable_ini)
		return;

	res = request_firmware(&fw, "iwl-dbg-tlv.ini", dev);
	if (res)
		return;

	iwl_alloc_dbg_tlv(trans, fw->size, fw->data, true);
	iwl_parse_fw_dbg_tlv(trans, fw->data, fw->size);

	trans->external_ini_loaded = true;
	release_firmware(fw);
}
+5 −2
Original line number Diff line number Diff line
@@ -77,8 +77,11 @@ struct iwl_apply_point_data {
};

struct iwl_trans;
void iwl_load_fw_dbg_tlv(struct device *dev, struct iwl_trans *trans);
void iwl_fw_dbg_free(struct iwl_trans *trans);
void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv);
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data);
void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
			 bool ext);
void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data,
		       bool ext);

#endif /* __iwl_dbg_tlv_h__*/
+5 −4
Original line number Diff line number Diff line
@@ -647,7 +647,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
	len -= sizeof(*ucode);

	if (iwlwifi_mod_params.enable_ini)
		iwl_alloc_dbg_tlv(drv->trans, len, data);
		iwl_alloc_dbg_tlv(drv->trans, len, data, false);

	while (len >= sizeof(*tlv)) {
		len -= sizeof(*tlv);
@@ -1096,7 +1096,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
		case IWL_UCODE_TLV_TYPE_TRIGGERS:
		case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
			if (iwlwifi_mod_params.enable_ini)
				iwl_fw_dbg_copy_tlv(drv->trans, tlv);
				iwl_fw_dbg_copy_tlv(drv->trans, tlv, false);
		default:
			IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
			break;
@@ -1576,7 +1576,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
	if (!drv->dbgfs_drv) {
		IWL_ERR(drv, "failed to create debugfs directory\n");
		ret = -ENOMEM;
		goto err_free_drv;
		goto err_free_tlv;
	}

	/* Create transport layer debugfs dir */
@@ -1601,7 +1601,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
#ifdef CONFIG_IWLWIFI_DEBUGFS
err_free_dbgfs:
	debugfs_remove_recursive(drv->dbgfs_drv);
err_free_drv:
err_free_tlv:
	iwl_fw_dbg_free(drv->trans);
#endif
	kfree(drv);
err:
+3 −0
Original line number Diff line number Diff line
@@ -776,6 +776,9 @@ struct iwl_trans {
#endif

	struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM];
	struct iwl_apply_point_data apply_points_ext[IWL_FW_INI_APPLY_NUM];

	bool external_ini_loaded;

	const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
	const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];