Commit 875d035f authored by Johannes Berg's avatar Johannes Berg
Browse files

wifi: iwlwifi: fw: clean up PNVM loading code



This code is a bit of a maze of gotos etc. Clean up the
code a bit to make the intent clearer.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230606103519.51fb5ee63f21.I20f270b2d47612e84643dc235c2940b8d9ed9930@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 380bf72d
Loading
Loading
Loading
Loading
+89 −66
Original line number Diff line number Diff line
@@ -270,88 +270,111 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
	return image;
}

int iwl_pnvm_load(struct iwl_trans *trans,
		  struct iwl_notif_wait_data *notif_wait,
static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans,
					const struct iwl_ucode_capabilities *capa)
{
	u8 *data;
	struct iwl_pnvm_image *pnvm_data = NULL;
	u8 *data = NULL;
	size_t length;
	struct iwl_notification_wait pnvm_wait;
	static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
						PNVM_INIT_COMPLETE_NTFY) };
	struct iwl_pnvm_image pnvm_data;
	int ret;

	/* if the SKU_ID is empty, there's nothing to do */
	if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
		return 0;

	/* failed to get/parse the image in the past, no use to try again */
	/* failed to get/parse the image in the past, no use trying again */
	if (trans->fail_to_parse_pnvm_image)
		goto reduce_tables;
		return;

	if (trans->pnvm_loaded)
		goto set;

	/* get the image, parse and load it, if not loaded yet */
	if (!trans->pnvm_loaded) {
	data = iwl_get_pnvm_image(trans, &length);
	if (!data) {
		trans->fail_to_parse_pnvm_image = true;
			goto reduce_tables;
		return;
	}
		ret = iwl_pnvm_parse(trans, data, length, &pnvm_data);

	pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL);
	if (!pnvm_data)
		goto free;

	ret = iwl_pnvm_parse(trans, data, length, pnvm_data);
	if (ret) {
		trans->fail_to_parse_pnvm_image = true;
			kfree(data);
			goto reduce_tables;
		goto free;
	}

		ret = iwl_trans_load_pnvm(trans, &pnvm_data, capa);
		/* can only free data after pvnm_data use, but
		 * pnvm_data.version used below is not a pointer
		 */
		kfree(data);
	ret = iwl_trans_load_pnvm(trans, pnvm_data, capa);
	if (ret)
			goto reduce_tables;
		IWL_INFO(trans, "loaded PNVM version %08x\n",
			 pnvm_data.version);
	}
		goto free;
	IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version);

set:
	iwl_trans_set_pnvm(trans, capa);
free:
	kfree(data);
	kfree(pnvm_data);
}

static void
iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans,
				    const struct iwl_ucode_capabilities *capa)
{
	struct iwl_pnvm_image *pnvm_data = NULL;
	u8 *data = NULL;
	size_t length;
	int ret;

reduce_tables:
	/* now try to get the reduce power table, if not loaded yet */
	if (trans->failed_to_load_reduce_power_image)
		goto notification;
		return;

	if (trans->reduce_power_loaded)
		goto set;

	if (!trans->reduce_power_loaded) {
		memset(&pnvm_data, 0, sizeof(pnvm_data));
	data = iwl_uefi_get_reduced_power(trans, &length);
	if (IS_ERR(data)) {
			ret = PTR_ERR(data);
		trans->failed_to_load_reduce_power_image = true;
			goto notification;
		return;
	}

		ret = iwl_uefi_reduce_power_parse(trans, data, length,
						  &pnvm_data);
	pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL);
	if (!pnvm_data)
		goto free;

	ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data);
	if (ret) {
		trans->failed_to_load_reduce_power_image = true;
			kfree(data);
			goto notification;
		goto free;
	}

		ret = iwl_trans_load_reduce_power(trans, &pnvm_data, capa);
		kfree(data);
	ret = iwl_trans_load_reduce_power(trans, pnvm_data, capa);
	if (ret) {
		IWL_DEBUG_FW(trans,
			     "Failed to load reduce power table %d\n",
			     ret);
		trans->failed_to_load_reduce_power_image = true;
			goto notification;
		}
		goto free;
	}

set:
	iwl_trans_set_reduce_power(trans, capa);
free:
	kfree(data);
	kfree(pnvm_data);
}

int iwl_pnvm_load(struct iwl_trans *trans,
		  struct iwl_notif_wait_data *notif_wait,
		  const struct iwl_ucode_capabilities *capa)
{
	struct iwl_notification_wait pnvm_wait;
	static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
						PNVM_INIT_COMPLETE_NTFY) };

	/* if the SKU_ID is empty, there's nothing to do */
	if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2])
		return 0;

	iwl_pnvm_load_pnvm_to_trans(trans, capa);
	iwl_pnvm_load_reduce_power_to_trans(trans, capa);

notification:
	iwl_init_notification_wait(notif_wait, &pnvm_wait,
				   ntf_cmds, ARRAY_SIZE(ntf_cmds),
				   iwl_pnvm_complete_fn, trans);