Commit 2d39c7ae authored by Mario Limonciello's avatar Mario Limonciello Committed by Alex Deucher
Browse files

drm/amd: Load PSP microcode during early_init



Simplifies the code so that all PSP versions will get the firmware
name from `amdgpu_ucode_ip_version_decode` and then use this filename
to load microcode as part of the early_init process.

Any failures will cause the driver to fail to probe before the firmware
framebuffer has been removed.

Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Signed-off-by: default avatarMario Limonciello <mario.limonciello@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 93fec4f8
Loading
Loading
Loading
Loading
+46 −74
Original line number Diff line number Diff line
@@ -123,6 +123,44 @@ static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp
	}
}

static int psp_init_sriov_microcode(struct psp_context *psp)
{
	struct amdgpu_device *adev = psp->adev;
	char ucode_prefix[30];
	int ret = 0;

	amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));

	switch (adev->ip_versions[MP0_HWIP][0]) {
	case IP_VERSION(9, 0, 0):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, ucode_prefix);
		break;
	case IP_VERSION(11, 0, 9):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, ucode_prefix);
		break;
	case IP_VERSION(11, 0, 7):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, ucode_prefix);
		break;
	case IP_VERSION(13, 0, 2):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, ucode_prefix);
		ret &= psp_init_ta_microcode(psp, ucode_prefix);
		break;
	case IP_VERSION(13, 0, 0):
		adev->virt.autoload_ucode_id = 0;
		break;
	case IP_VERSION(13, 0, 10):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA;
		break;
	default:
		return -EINVAL;
	}
	return ret;
}

static int psp_early_init(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -193,7 +231,10 @@ static int psp_early_init(void *handle)

	psp_check_pmfw_centralized_cstate_management(psp);

	return 0;
	if (amdgpu_sriov_vf(adev))
		return psp_init_sriov_microcode(psp);
	else
		return psp_init_microcode(psp);
}

void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx)
@@ -351,42 +392,6 @@ static bool psp_get_runtime_db_entry(struct amdgpu_device *adev,
	return ret;
}

static int psp_init_sriov_microcode(struct psp_context *psp)
{
	struct amdgpu_device *adev = psp->adev;
	int ret = 0;

	switch (adev->ip_versions[MP0_HWIP][0]) {
	case IP_VERSION(9, 0, 0):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, "vega10");
		break;
	case IP_VERSION(11, 0, 9):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, "navi12");
		break;
	case IP_VERSION(11, 0, 7):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, "sienna_cichlid");
		break;
	case IP_VERSION(13, 0, 2):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
		ret = psp_init_cap_microcode(psp, "aldebaran");
		ret &= psp_init_ta_microcode(psp, "aldebaran");
		break;
	case IP_VERSION(13, 0, 0):
		adev->virt.autoload_ucode_id = 0;
		break;
	case IP_VERSION(13, 0, 10):
		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA;
		break;
	default:
		ret = -EINVAL;
		break;
	}
	return ret;
}

static int psp_sw_init(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -402,15 +407,6 @@ static int psp_sw_init(void *handle)
		ret = -ENOMEM;
	}

	if (amdgpu_sriov_vf(adev))
		ret = psp_init_sriov_microcode(psp);
	else
		ret = psp_init_microcode(psp);
	if (ret) {
		DRM_ERROR("Failed to load psp firmware!\n");
		return ret;
	}

	adev->psp.xgmi_context.supports_extended_data =
		!adev->gmc.xgmi.connected_to_cpu &&
			adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2);
@@ -2914,19 +2910,13 @@ int psp_ring_cmd_submit(struct psp_context *psp,
	return 0;
}

int psp_init_asd_microcode(struct psp_context *psp,
			   const char *chip_name)
int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
{
	struct amdgpu_device *adev = psp->adev;
	char fw_name[PSP_FW_NAME_LEN];
	const struct psp_firmware_header_v1_0 *asd_hdr;
	int err = 0;

	if (!chip_name) {
		dev_err(adev->dev, "invalid chip name for asd microcode\n");
		return -EINVAL;
	}

	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name);
	err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev);
	if (err)
@@ -2950,19 +2940,13 @@ int psp_init_asd_microcode(struct psp_context *psp,
	return err;
}

int psp_init_toc_microcode(struct psp_context *psp,
			   const char *chip_name)
int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name)
{
	struct amdgpu_device *adev = psp->adev;
	char fw_name[PSP_FW_NAME_LEN];
	const struct psp_firmware_header_v1_0 *toc_hdr;
	int err = 0;

	if (!chip_name) {
		dev_err(adev->dev, "invalid chip name for toc microcode\n");
		return -EINVAL;
	}

	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name);
	err = request_firmware(&adev->psp.toc_fw, fw_name, adev->dev);
	if (err)
@@ -3113,8 +3097,7 @@ static int psp_init_sos_base_fw(struct amdgpu_device *adev)
	return 0;
}

int psp_init_sos_microcode(struct psp_context *psp,
			   const char *chip_name)
int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
{
	struct amdgpu_device *adev = psp->adev;
	char fw_name[PSP_FW_NAME_LEN];
@@ -3127,11 +3110,6 @@ int psp_init_sos_microcode(struct psp_context *psp,
	uint8_t *ucode_array_start_addr;
	int fw_index = 0;

	if (!chip_name) {
		dev_err(adev->dev, "invalid chip name for sos microcode\n");
		return -EINVAL;
	}

	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name);
	err = request_firmware(&adev->psp.sos_fw, fw_name, adev->dev);
	if (err)
@@ -3398,8 +3376,7 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
	return err;
}

int psp_init_cap_microcode(struct psp_context *psp,
			  const char *chip_name)
int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
{
	struct amdgpu_device *adev = psp->adev;
	char fw_name[PSP_FW_NAME_LEN];
@@ -3407,11 +3384,6 @@ int psp_init_cap_microcode(struct psp_context *psp,
	struct amdgpu_firmware_info *info = NULL;
	int err = 0;

	if (!chip_name) {
		dev_err(adev->dev, "invalid chip name for cap microcode\n");
		return -EINVAL;
	}

	if (!amdgpu_sriov_vf(adev)) {
		dev_err(adev->dev, "cap microcode should only be loaded under SRIOV\n");
		return -EINVAL;
+0 −12
Original line number Diff line number Diff line
@@ -47,22 +47,10 @@ MODULE_FIRMWARE("amdgpu/raven_ta.bin");
static int psp_v10_0_init_microcode(struct psp_context *psp)
{
	struct amdgpu_device *adev = psp->adev;
	const char *chip_name;
	char ucode_prefix[30];
	int err = 0;
	DRM_DEBUG("\n");

	switch (adev->asic_type) {
	case CHIP_RAVEN:
		if (adev->apu_flags & AMD_APU_IS_RAVEN2)
			chip_name = "raven2";
		else if (adev->apu_flags & AMD_APU_IS_PICASSO)
			chip_name = "picasso";
		else
			chip_name = "raven";
		break;
	default: BUG();
	}
	amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));

	err = psp_init_asd_microcode(psp, ucode_prefix);
+8 −43
Original line number Diff line number Diff line
@@ -88,55 +88,20 @@ MODULE_FIRMWARE("amdgpu/beige_goby_ta.bin");
static int psp_v11_0_init_microcode(struct psp_context *psp)
{
	struct amdgpu_device *adev = psp->adev;
	const char *chip_name;
	char ucode_prefix[30];
	int err = 0;

	DRM_DEBUG("\n");

	switch (adev->ip_versions[MP0_HWIP][0]) {
	case IP_VERSION(11, 0, 2):
		chip_name = "vega20";
		break;
	case IP_VERSION(11, 0, 0):
		chip_name = "navi10";
		break;
	case IP_VERSION(11, 0, 5):
		chip_name = "navi14";
		break;
	case IP_VERSION(11, 0, 9):
		chip_name = "navi12";
		break;
	case IP_VERSION(11, 0, 4):
		chip_name = "arcturus";
		break;
	case IP_VERSION(11, 0, 7):
		chip_name = "sienna_cichlid";
		break;
	case IP_VERSION(11, 0, 11):
		chip_name = "navy_flounder";
		break;
	case IP_VERSION(11, 5, 0):
		chip_name = "vangogh";
		break;
	case IP_VERSION(11, 0, 12):
		chip_name = "dimgrey_cavefish";
		break;
	case IP_VERSION(11, 0, 13):
		chip_name = "beige_goby";
		break;
	default:
		BUG();
	}
	amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));

	switch (adev->ip_versions[MP0_HWIP][0]) {
	case IP_VERSION(11, 0, 2):
	case IP_VERSION(11, 0, 4):
		err = psp_init_sos_microcode(psp, chip_name);
		err = psp_init_sos_microcode(psp, ucode_prefix);
		if (err)
			return err;
		err = psp_init_asd_microcode(psp, chip_name);
		err = psp_init_asd_microcode(psp, ucode_prefix);
		if (err)
			return err;
		err = psp_init_ta_microcode(psp, ucode_prefix);
@@ -145,10 +110,10 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
	case IP_VERSION(11, 0, 0):
	case IP_VERSION(11, 0, 5):
	case IP_VERSION(11, 0, 9):
		err = psp_init_sos_microcode(psp, chip_name);
		err = psp_init_sos_microcode(psp, ucode_prefix);
		if (err)
			return err;
		err = psp_init_asd_microcode(psp, chip_name);
		err = psp_init_asd_microcode(psp, ucode_prefix);
		if (err)
			return err;
		err = psp_init_ta_microcode(psp, ucode_prefix);
@@ -158,16 +123,16 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
	case IP_VERSION(11, 0, 11):
	case IP_VERSION(11, 0, 12):
	case IP_VERSION(11, 0, 13):
		err = psp_init_sos_microcode(psp, chip_name);
		err = psp_init_sos_microcode(psp, ucode_prefix);
		if (err)
			return err;
		err = psp_init_ta_microcode(psp, chip_name);
		err = psp_init_ta_microcode(psp, ucode_prefix);
		break;
	case IP_VERSION(11, 5, 0):
		err = psp_init_asd_microcode(psp, chip_name);
		err = psp_init_asd_microcode(psp, ucode_prefix);
		if (err)
			return err;
		err = psp_init_toc_microcode(psp, chip_name);
		err = psp_init_toc_microcode(psp, ucode_prefix);
		break;
	default:
		BUG();
+1 −12
Original line number Diff line number Diff line
@@ -48,24 +48,13 @@ MODULE_FIRMWARE("amdgpu/green_sardine_ta.bin");
static int psp_v12_0_init_microcode(struct psp_context *psp)
{
	struct amdgpu_device *adev = psp->adev;
	const char *chip_name;
	char ucode_prefix[30];
	int err = 0;
	DRM_DEBUG("\n");

	switch (adev->asic_type) {
	case CHIP_RENOIR:
		if (adev->apu_flags & AMD_APU_IS_RENOIR)
			chip_name = "renoir";
		else
			chip_name = "green_sardine";
		break;
	default:
		BUG();
	}
	amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));

	err = psp_init_asd_microcode(psp, chip_name);
	err = psp_init_asd_microcode(psp, ucode_prefix);
	if (err)
		return err;

+7 −20
Original line number Diff line number Diff line
@@ -70,32 +70,19 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_11_ta.bin");
static int psp_v13_0_init_microcode(struct psp_context *psp)
{
	struct amdgpu_device *adev = psp->adev;
	const char *chip_name;
	char ucode_prefix[30];
	int err = 0;

	switch (adev->ip_versions[MP0_HWIP][0]) {
	case IP_VERSION(13, 0, 2):
		chip_name = "aldebaran";
		break;
	case IP_VERSION(13, 0, 1):
	case IP_VERSION(13, 0, 3):
		chip_name = "yellow_carp";
		break;
	default:
	amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
		chip_name = ucode_prefix;
		break;
	}

	switch (adev->ip_versions[MP0_HWIP][0]) {
	case IP_VERSION(13, 0, 2):
		err = psp_init_sos_microcode(psp, chip_name);
		err = psp_init_sos_microcode(psp, ucode_prefix);
		if (err)
			return err;
		/* It's not necessary to load ras ta on Guest side */
		if (!amdgpu_sriov_vf(adev)) {
			err = psp_init_ta_microcode(&adev->psp, chip_name);
			err = psp_init_ta_microcode(psp, ucode_prefix);
			if (err)
				return err;
		}
@@ -105,21 +92,21 @@ static int psp_v13_0_init_microcode(struct psp_context *psp)
	case IP_VERSION(13, 0, 5):
	case IP_VERSION(13, 0, 8):
	case IP_VERSION(13, 0, 11):
		err = psp_init_toc_microcode(psp, chip_name);
		err = psp_init_toc_microcode(psp, ucode_prefix);
		if (err)
			return err;
		err = psp_init_ta_microcode(psp, chip_name);
		err = psp_init_ta_microcode(psp, ucode_prefix);
		if (err)
			return err;
		break;
	case IP_VERSION(13, 0, 0):
	case IP_VERSION(13, 0, 7):
	case IP_VERSION(13, 0, 10):
		err = psp_init_sos_microcode(psp, chip_name);
		err = psp_init_sos_microcode(psp, ucode_prefix);
		if (err)
			return err;
		/* It's not necessary to load ras ta on Guest side */
		err = psp_init_ta_microcode(psp, chip_name);
		err = psp_init_ta_microcode(psp, ucode_prefix);
		if (err)
			return err;
		break;
Loading