Commit 70d3ca86 authored by Luca Coelho's avatar Luca Coelho Committed by Kalle Valo
Browse files

iwlwifi: mvm: ring the doorbell and wait for PNVM load completion



When we receive a non-zero SKU_ID in the alive notification, we need
to ring the doorbell and wait for the FW to send us a PNVM load
complete notification before we continue the init phase.

Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20201008180656.a10e8b6bbcf9.Ib5d10b3d508a4d2d4e6b7b629af89d76f4f03d81@changeid
parent 7ef3e224
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -90,6 +90,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
	 * @TAS_CONFIG: &struct iwl_tas_config_cmd
	 */
	TAS_CONFIG = 0x3,

	/**
	 * @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
	 */
	PNVM_INIT_COMPLETE_NTFY = 0xFE,
};

/**
@@ -476,4 +481,12 @@ struct iwl_lari_config_change_cmd {
	__le32 config_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_1 */

/**
 * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
 * @status: PNVM image loading status
 */
struct iwl_pnvm_init_complete_ntfy {
	__le32 status;
} __packed; /* PNVM_INIT_COMPLETE_NTFY_S_VER_1 */

#endif /* __iwl_fw_api_nvm_reg_h__ */
+1 −0
Original line number Diff line number Diff line
@@ -460,6 +460,7 @@ enum {
#define UREG_DOORBELL_TO_ISR6_NMI_BIT	BIT(0)
#define UREG_DOORBELL_TO_ISR6_SUSPEND	BIT(18)
#define UREG_DOORBELL_TO_ISR6_RESUME	BIT(19)
#define UREG_DOORBELL_TO_ISR6_PNVM	BIT(20)

#define FSEQ_ERROR_CODE			0xA340C8
#define FSEQ_TOP_INIT_VERSION		0xA34038
+51 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@

#define MVM_UCODE_ALIVE_TIMEOUT	HZ
#define MVM_UCODE_CALIB_TIMEOUT	(2*HZ)
#define MVM_UCODE_PNVM_TIMEOUT	(HZ / 10)

#define UCODE_VALID_OK	cpu_to_le32(0x1)

@@ -305,6 +306,20 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
	return true;
}

static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
				 struct iwl_rx_packet *pkt, void *data)
{
	struct iwl_mvm *mvm =
		container_of(notif_wait, struct iwl_mvm, notif_wait);
	struct iwl_pnvm_init_complete_ntfy *pnvm_ntf = (void *)pkt->data;

	IWL_DEBUG_FW(mvm,
		     "PNVM complete notification received with status %d\n",
		     le32_to_cpu(pnvm_ntf->status));

	return true;
}

static bool iwl_wait_init_complete(struct iwl_notif_wait_data *notif_wait,
				   struct iwl_rx_packet *pkt, void *data)
{
@@ -328,6 +343,35 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
	return false;
}

static int iwl_mvm_load_pnvm(struct iwl_mvm *mvm)
{
	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 (!mvm->trans->sku_id[0] &&
	    !mvm->trans->sku_id[1] &&
	    !mvm->trans->sku_id[2])
		return 0;

	/*
	 * TODO: phase 2: load the pnvm file, find the right section,
	 * load it and set the right DMA pointer.
	 */

	iwl_init_notification_wait(&mvm->notif_wait, &pnvm_wait,
				   ntf_cmds, ARRAY_SIZE(ntf_cmds),
				   iwl_pnvm_complete_fn, NULL);

	/* kick the doorbell */
	iwl_write_umac_prph(mvm->trans, UREG_DOORBELL_TO_ISR6,
			    UREG_DOORBELL_TO_ISR6_PNVM);

	return iwl_wait_notification(&mvm->notif_wait, &pnvm_wait,
				     MVM_UCODE_PNVM_TIMEOUT);
}

static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
					 enum iwl_ucode_type ucode_type)
{
@@ -416,6 +460,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
		return -EIO;
	}

	ret = iwl_mvm_load_pnvm(mvm);
	if (ret) {
		IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
		iwl_fw_set_current_image(&mvm->fwrt, old_type);
		return ret;
	}

	iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);

	/*