Commit ea3571f4 authored by Alon Giladi's avatar Alon Giladi Committed by Johannes Berg
Browse files

wifi: iwlwifi: Use iwl_pnvm_image in reduce power tables flow



Generalize the parsing, loading, and setting of the power-reduce
tables, in order to support allocation of several DRAM payloads
in the future.

Signed-off-by: default avatarAlon Giladi <alon.giladi@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230606103519.564f1eead99b.Iaba653b21dc09aafc72b9bbb3928abddce0db50a@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c738fb61
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -320,8 +320,9 @@ int iwl_pnvm_load(struct iwl_trans *trans,
reduce_tables:
	/* now try to get the reduce power table, if not loaded yet */
	if (!trans->reduce_power_loaded) {
		data = iwl_uefi_get_reduced_power(trans, &length);
		if (IS_ERR_OR_NULL(data)) {
		memset(&pnvm_data, 0, sizeof(pnvm_data));
		ret = iwl_uefi_get_reduced_power(trans, &pnvm_data);
		if (ret) {
			/*
			 * Pretend we've loaded it - at least we've tried and
			 * couldn't load it at all, so there's no point in
@@ -329,7 +330,7 @@ int iwl_pnvm_load(struct iwl_trans *trans,
			 */
			trans->reduce_power_loaded = true;
		} else {
			ret = iwl_trans_load_reduce_power(trans, data, length);
			ret = iwl_trans_load_reduce_power(trans, &pnvm_data);
			if (ret) {
				IWL_DEBUG_FW(trans,
					     "Failed to load reduce power table %d\n",
+37 −53
Original line number Diff line number Diff line
@@ -55,14 +55,14 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
	return data;
}

static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
					   const u8 *data, size_t len)
static int iwl_uefi_reduce_power_section(struct iwl_trans *trans,
					 const u8 *data, size_t len,
					 struct iwl_pnvm_image *pnvm_data)
{
	const struct iwl_ucode_tlv *tlv;
	u8 *reduce_power_data = NULL, *tmp;
	u32 size = 0;

	IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n");
	memset(pnvm_data, 0, sizeof(*pnvm_data));

	while (len >= sizeof(*tlv)) {
		u32 tlv_len, tlv_type;
@@ -76,9 +76,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
		if (len < tlv_len) {
			IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
				len, tlv_len);
			kfree(reduce_power_data);
			reduce_power_data = ERR_PTR(-EINVAL);
			goto out;
			return -EINVAL;
		}

		data += sizeof(*tlv);
@@ -89,23 +87,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
				     "Got IWL_UCODE_TLV_MEM_DESC len %d\n",
				     tlv_len);

			IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);

			tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL);
			if (!tmp) {
			if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) {
				IWL_DEBUG_FW(trans,
					     "Couldn't allocate (more) reduce_power_data\n");

				kfree(reduce_power_data);
				reduce_power_data = ERR_PTR(-ENOMEM);
				goto out;
				"too many payloads to allocate in DRAM.\n");
				return -EINVAL;
			}

			reduce_power_data = tmp;

			memcpy(reduce_power_data + size, data, tlv_len);
			IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len);

			size += tlv_len;
			pnvm_data->chunks[pnvm_data->n_chunks].data = data;
			pnvm_data->chunks[pnvm_data->n_chunks].len = tlv_len;
			pnvm_data->n_chunks++;

			break;
		}
@@ -124,27 +116,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
	}

done:
	if (!size) {
	if (!pnvm_data->n_chunks) {
		IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n");
		/* Better safe than sorry, but 'reduce_power_data' should
		 * always be NULL if !size.
		 */
		kfree(reduce_power_data);
		reduce_power_data = ERR_PTR(-ENOENT);
		goto out;
		return -ENOENT;
	}

	IWL_INFO(trans, "loaded REDUCE_POWER\n");

out:
	return reduce_power_data;
	return 0;
}

static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
					 const u8 *data, size_t len)
static int iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
				       const u8 *data, size_t len,
				       struct iwl_pnvm_image *pnvm_data)
{
	const struct iwl_ucode_tlv *tlv;
	void *sec_data;

	IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n");

@@ -160,7 +143,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
		if (len < tlv_len) {
			IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
				len, tlv_len);
			return ERR_PTR(-EINVAL);
			return -EINVAL;
		}

		if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) {
@@ -181,11 +164,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
			if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) &&
			    trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) &&
			    trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) {
				sec_data = iwl_uefi_reduce_power_section(trans,
									 data,
									 len);
				if (!IS_ERR(sec_data))
					return sec_data;
				int ret = iwl_uefi_reduce_power_section(trans,
								    data, len,
								    pnvm_data);
				if (!ret)
					return 0;
			} else {
				IWL_DEBUG_FW(trans, "SKU ID didn't match!\n");
			}
@@ -195,20 +178,20 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans,
		}
	}

	return ERR_PTR(-ENOENT);
	return -ENOENT;
}

void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
			       struct iwl_pnvm_image *pnvm_data)
{
	struct pnvm_sku_package *package;
	void *data = NULL;
	unsigned long package_size;
	efi_status_t status;

	*len = 0;
	int ret;
	size_t len = 0;

	if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
		return ERR_PTR(-ENODEV);
		return -ENODEV;

	/*
	 * TODO: we hardcode a maximum length here, because reading
@@ -219,7 +202,7 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)

	package = kmalloc(package_size, GFP_KERNEL);
	if (!package)
		return ERR_PTR(-ENOMEM);
		return -ENOMEM;

	status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID,
				  NULL, &package_size, package);
@@ -228,22 +211,23 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
			     "Reduced Power UEFI variable not found 0x%lx (len %lu)\n",
			     status, package_size);
		kfree(package);
		return ERR_PTR(-ENOENT);
		return -ENOENT;
	}

	IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n",
		     package_size);
	*len = package_size;
	len = package_size;

	IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n",
		     package->rev, package->total_size, package->n_skus);

	data = iwl_uefi_reduce_power_parse(trans, package->data,
					   *len - sizeof(*package));
	ret = iwl_uefi_reduce_power_parse(trans, package->data,
					  len - sizeof(*package),
					  pnvm_data);

	kfree(package);

	return data;
	return ret;
}

static int iwl_uefi_step_parse(struct uefi_cnv_common_step_data *common_step_data,
+5 −3
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@ struct uefi_cnv_common_step_data {
 */
#ifdef CONFIG_EFI
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
			       struct iwl_pnvm_image *pnvm_data);
void iwl_uefi_get_step_table(struct iwl_trans *trans);
#else /* CONFIG_EFI */
static inline
@@ -60,9 +61,10 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
}

static inline
void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
int iwl_uefi_get_reduced_power(struct iwl_trans *trans,
			       struct iwl_pnvm_image *pnvm_data)
{
	return ERR_PTR(-EOPNOTSUPP);
	return -EOPNOTSUPP;
}

static inline
+3 −2
Original line number Diff line number Diff line
@@ -292,8 +292,9 @@ int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans,
					   const struct iwl_ucode_capabilities *capa);
void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans,
					   const struct iwl_ucode_capabilities *capa);
int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans,
						   const void *data, u32 len);
int iwl_trans_pcie_ctx_info_gen3_load_reduce_power
				(struct iwl_trans *trans,
				 const struct iwl_pnvm_image *payloads);
void iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans);
int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans,
					  u32 mbx_addr_0_step, u32 mbx_addr_1_step);
+5 −6
Original line number Diff line number Diff line
@@ -641,8 +641,7 @@ struct iwl_trans_ops {
	void (*set_pnvm)(struct iwl_trans *trans,
			 const struct iwl_ucode_capabilities *capa);
	int (*load_reduce_power)(struct iwl_trans *trans,
				 const void *data,
				 u32 len);
				 const struct iwl_pnvm_image *payloads);
	void (*set_reduce_power)(struct iwl_trans *trans);

	void (*interrupts)(struct iwl_trans *trans, bool enable);
@@ -1559,11 +1558,11 @@ static inline void iwl_trans_set_pnvm(struct iwl_trans *trans,
		trans->ops->set_pnvm(trans, capa);
}

static inline int iwl_trans_load_reduce_power(struct iwl_trans *trans,
					      const void *data,
					      u32 len)
static inline int iwl_trans_load_reduce_power
				(struct iwl_trans *trans,
				 const struct iwl_pnvm_image *payloads)
{
	return trans->ops->load_reduce_power(trans, data, len);
	return trans->ops->load_reduce_power(trans, payloads);
}

static inline void iwl_trans_set_reduce_power(struct iwl_trans *trans)
Loading