2023-01-05 17:09:50

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 00/45] Recover from failure to probe GPU

One of the first thing that KMS drivers do during initialization is
destroy the system firmware framebuffer by means of
`drm_aperture_remove_conflicting_pci_framebuffers`

This means that if for any reason the GPU failed to probe the user
will be stuck with at best a screen frozen at the last thing that
was shown before the KMS driver continued it's probe.

The problem is most pronounced when new GPU support is introduced
because users will need to have a recent linux-firmware snapshot
on their system when they boot a kernel with matching support.

However the problem is further exaggerated in the case of amdgpu because
it has migrated to "IP discovery" where amdgpu will attempt to load
on "ALL" AMD GPUs even if the driver is missing support for IP blocks
contained in that GPU.

IP discovery requires some probing and isn't run until after the
framebuffer has been destroyed.

This means a situation can occur where a user purchases a new GPU not
yet supported by a distribution and when booting the installer it will
"freeze" even if the distribution doesn't have the matching kernel support
for those IP blocks.

The perfect example of this is Ubuntu 22.10 and the new dGPUs just
launched by AMD. The installation media ships with kernel 5.19 (which
has IP discovery) but the amdgpu support for those IP blocks landed in
kernel 6.0. The matching linux-firmware was released after 22.10's launch.
The screen will freeze without nomodeset. Even if a user manages to install
and then upgrades to kernel 6.0 after install they'll still have the
problem of missing firmware, and the same experience.

This is quite jarring for users, particularly if they don't know
that they have to use "nomodeset" to install.

To help the situation make changes to GPU discovery:
1) Delay releasing the firmware framebuffer until after early_init
completed. This will help the situation of an older kernel that doesn't
yet support the IP blocks probing a new GPU. IP discovery will have failed.
2) Request loading all PSP, VCN, SDMA, SMU, DMCUB, MES and GC microcode
into memory during early_init. This will help the situation of new enough
kernel for the IP discovery phase to otherwise pass but missing microcode
from linux-firmware.git.

v6->v7:
* Pick up tags
* Fix PSP TAv1 handling to match previous behavior (securedisplay_context
only is set on PSPv10 and PSPv12/Renoir)
v5->v6:
* Fix arguments for amdgpu_ucode_release to allow clearing pointer
* Fix whitespace mistake in VCN
* Pick up tags
v4->v5:
* Rename amdgpu_ucode_load to amdgpu_ucode_request
* Add and utilize amdgpu_ucode_release throughout existing patches
* Update all amdgpu code to stop using request_firmware and
release_firmware for microcode
* Drop export of amdgpu_ucode_validate outside of amdgpu_ucode.c
* Pick up relevant tags for some patches
v3->v4:
* Rework to delay framebuffer release until early_init is done
* Make IP load microcode during early init phase
* Add SMU and DMCUB checks for early_init loading
* Add some new helper code for wrapping request_firmware calls (needed for
early_init to return something besides -ENOENT)
v2->v3:
* Pick up tags for patches 1-10
* Rework patch 11 to not validate during discovery
* Fix bugs with GFX9 due to gfx.num_gfx_rings not being set during
discovery
* Fix naming scheme for SDMA on dGPUs
v1->v2:
* Take the suggestion from v1 thread to delay the framebuffer release
until ip discovery is done. This patch is CC to stable to that older
stable kernels with IP discovery won't try to probe unknown IP.
* Drop changes to drm aperature.
* Fetch SDMA, VCN, MES, GC and PSP microcode during IP discovery.

Mario Limonciello (27):
drm/amd: Delay removal of the firmware framebuffer
drm/amd: Add a legacy mapping to "amdgpu_ucode_ip_version_decode"
drm/amd: Convert SMUv11 microcode to use
`amdgpu_ucode_ip_version_decode`
drm/amd: Convert SMUv13 microcode to use
`amdgpu_ucode_ip_version_decode`
drm/amd: Add a new helper for loading/validating microcode
drm/amd: Use `amdgpu_ucode_request` helper for SDMA
drm/amd: Convert SDMA to use `amdgpu_ucode_ip_version_decode`
drm/amd: Make SDMA firmware load failures less noisy.
drm/amd: Use `amdgpu_ucode_*` helpers for VCN
drm/amd: Load VCN microcode during early_init
drm/amd: Load MES microcode during early_init
drm/amd: Use `amdgpu_ucode_*` helpers for MES
drm/amd: Remove superfluous assignment for `adev->mes.adev`
drm/amd: Use `amdgpu_ucode_*` helpers for GFX9
drm/amd: Load GFX9 microcode during early_init
drm/amd: Use `amdgpu_ucode_*` helpers for GFX10
drm/amd: Load GFX10 microcode during early_init
drm/amd: Use `amdgpu_ucode_*` helpers for GFX11
drm/amd: Load GFX11 microcode during early_init
drm/amd: Parse both v1 and v2 TA microcode headers using same function
drm/amd: Avoid BUG() for case of SRIOV missing IP version
drm/amd: Load PSP microcode during early_init
drm/amd: Use `amdgpu_ucode_*` helpers for PSP
drm/amd/display: Load DMUB microcode during early_init
drm/amd: Use `amdgpu_ucode_release` helper for DMUB
drm/amd: Use `amdgpu_ucode_*` helpers for SMU
drm/amd: Load SMU microcode during early_init
drm/amd: Optimize SRIOV switch/case for PSP microcode load
drm/amd: Use `amdgpu_ucode_*` helpers for GFX6
drm/amd: Use `amdgpu_ucode_*` helpers for GFX7
drm/amd: Use `amdgpu_ucode_*` helpers for GFX8
drm/amd: Use `amdgpu_ucode_*` helpers for GMC6
drm/amd: Use `amdgpu_ucode_*` helpers for GMC7
drm/amd: Use `amdgpu_ucode_*` helpers for GMC8
drm/amd: Use `amdgpu_ucode_*` helpers for SDMA2.4
drm/amd: Use `amdgpu_ucode_*` helpers for SDMA3.0
drm/amd: Use `amdgpu_ucode_*` helpers for SDMA on CIK
drm/amd: Use `amdgpu_ucode_*` helpers for UVD
drm/amd: Use `amdgpu_ucode_*` helpers for VCE
drm/amd: Use `amdgpu_ucode_*` helpers for CGS
drm/amd: Use `amdgpu_ucode_*` helpers for GPU info bin
drm/amd: Use `amdgpu_ucode_*` helpers for DMCU
drm/amd: Use `amdgpu_ucode_release` helper for powerplay
drm/amd: Use `amdgpu_ucode_release` helper for si
drm/amd: make amdgpu_ucode_validate static

drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 11 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 22 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 6 -
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 59 ++++
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 299 +++++++++---------
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 25 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 259 ++++++++++++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 14 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 14 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 65 +---
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 1 +
drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 16 +-
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 155 +++------
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 124 +++-----
drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 30 +-
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 68 +---
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 94 ++----
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 140 ++------
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 14 +-
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 13 +-
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 13 +-
drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 7 +-
drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 108 ++-----
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 99 ++----
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 80 +----
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 131 +-------
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 79 +----
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 27 +-
drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c | 14 +-
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 16 +-
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 18 +-
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 18 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 47 +--
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 30 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 55 +---
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 25 +-
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 5 +-
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 5 +-
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 5 +-
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 5 +-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 5 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 110 ++++---
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 11 +-
.../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 3 +-
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 +-
.../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 51 +--
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 28 +-
50 files changed, 900 insertions(+), 1545 deletions(-)

--
2.34.1


2023-01-05 17:10:40

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 30/45] drm/amd: Use `amdgpu_ucode_*` helpers for GFX7

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 68 +++++++--------------------
1 file changed, 17 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 0f2976507e48..646999ad4f04 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -887,6 +887,16 @@ static void gfx_v7_0_get_csb_buffer(struct amdgpu_device *adev, volatile u32 *bu
static void gfx_v7_0_init_pg(struct amdgpu_device *adev);
static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev);

+static void gfx_v7_0_free_microcode(struct amdgpu_device *adev)
+{
+ amdgpu_ucode_release(&adev->gfx.pfp_fw);
+ amdgpu_ucode_release(&adev->gfx.me_fw);
+ amdgpu_ucode_release(&adev->gfx.ce_fw);
+ amdgpu_ucode_release(&adev->gfx.mec_fw);
+ amdgpu_ucode_release(&adev->gfx.mec2_fw);
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
+}
+
/*
* Core functions
*/
@@ -927,88 +937,44 @@ static int gfx_v7_0_init_microcode(struct amdgpu_device *adev)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.pfp_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
if (err)
goto out;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.me_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
if (err)
goto out;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.ce_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
if (err)
goto out;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
- err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.mec_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
if (err)
goto out;

if (adev->asic_type == CHIP_KAVERI) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
if (err)
goto out;
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
if (err)
goto out;
- err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
-
out:
if (err) {
pr_err("gfx7: Failed to load firmware \"%s\"\n", fw_name);
- release_firmware(adev->gfx.pfp_fw);
- adev->gfx.pfp_fw = NULL;
- release_firmware(adev->gfx.me_fw);
- adev->gfx.me_fw = NULL;
- release_firmware(adev->gfx.ce_fw);
- adev->gfx.ce_fw = NULL;
- release_firmware(adev->gfx.mec_fw);
- adev->gfx.mec_fw = NULL;
- release_firmware(adev->gfx.mec2_fw);
- adev->gfx.mec2_fw = NULL;
- release_firmware(adev->gfx.rlc_fw);
- adev->gfx.rlc_fw = NULL;
+ gfx_v7_0_free_microcode(adev);
}
return err;
}

-static void gfx_v7_0_free_microcode(struct amdgpu_device *adev)
-{
- release_firmware(adev->gfx.pfp_fw);
- adev->gfx.pfp_fw = NULL;
- release_firmware(adev->gfx.me_fw);
- adev->gfx.me_fw = NULL;
- release_firmware(adev->gfx.ce_fw);
- adev->gfx.ce_fw = NULL;
- release_firmware(adev->gfx.mec_fw);
- adev->gfx.mec_fw = NULL;
- release_firmware(adev->gfx.mec2_fw);
- adev->gfx.mec2_fw = NULL;
- release_firmware(adev->gfx.rlc_fw);
- adev->gfx.rlc_fw = NULL;
-}
-
/**
* gfx_v7_0_tiling_mode_table_init - init the hw tiling table
*
--
2.34.1

2023-01-05 17:11:19

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 19/45] drm/amd: Load GFX11 microcode during early_init

If GFX11 microcode is required but not available during early init, the
firmware framebuffer will have already been released and the screen will
freeze.

Move the request for GFX11 microcode into the early_init phase
so that if it's not available, driver init will fail.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Rebase on earlier changes
---
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 26 +++++++-------------------
1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index d4f67624d05b..5cc329cf66c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -439,14 +439,12 @@ static void gfx_v11_0_free_microcode(struct amdgpu_device *adev)
kfree(adev->gfx.rlc.register_list_format);
}

-static int gfx_v11_0_init_toc_microcode(struct amdgpu_device *adev)
+static int gfx_v11_0_init_toc_microcode(struct amdgpu_device *adev, const char *ucode_prefix)
{
const struct psp_firmware_header_v1_0 *toc_hdr;
int err = 0;
char fw_name[40];
- char ucode_prefix[30];

- amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix);
err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
if (err)
@@ -534,6 +532,9 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);
}

+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO)
+ err = gfx_v11_0_init_toc_microcode(adev, ucode_prefix);
+
/* only one MEC for gfx 11.0.0. */
adev->gfx.mec2_fw = NULL;

@@ -684,19 +685,11 @@ static void gfx_v11_0_mec_fini(struct amdgpu_device *adev)
amdgpu_bo_free_kernel(&adev->gfx.mec.mec_fw_data_obj, NULL, NULL);
}

-static int gfx_v11_0_me_init(struct amdgpu_device *adev)
+static void gfx_v11_0_me_init(struct amdgpu_device *adev)
{
- int r;
-
bitmap_zero(adev->gfx.me.queue_bitmap, AMDGPU_MAX_GFX_QUEUES);

amdgpu_gfx_graphics_queue_acquire(adev);
-
- r = gfx_v11_0_init_microcode(adev);
- if (r)
- DRM_ERROR("Failed to load gfx firmware!\n");
-
- return r;
}

static int gfx_v11_0_mec_init(struct amdgpu_device *adev)
@@ -1309,9 +1302,7 @@ static int gfx_v11_0_sw_init(void *handle)
}
}

- r = gfx_v11_0_me_init(adev);
- if (r)
- return r;
+ gfx_v11_0_me_init(adev);

r = gfx_v11_0_rlc_init(adev);
if (r) {
@@ -1379,9 +1370,6 @@ static int gfx_v11_0_sw_init(void *handle)

/* allocate visible FB for rlc auto-loading fw */
if (adev->firmware.load_type == AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO) {
- r = gfx_v11_0_init_toc_microcode(adev);
- if (r)
- dev_err(adev->dev, "Failed to load toc firmware!\n");
r = gfx_v11_0_rlc_autoload_buffer_init(adev);
if (r)
return r;
@@ -4650,7 +4638,7 @@ static int gfx_v11_0_early_init(void *handle)

gfx_v11_0_init_rlcg_reg_access_ctrl(adev);

- return 0;
+ return gfx_v11_0_init_microcode(adev);
}

static int gfx_v11_0_ras_late_init(void *handle)
--
2.34.1

2023-01-05 17:11:32

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 15/45] drm/amd: Load GFX9 microcode during early_init

If GFX9 microcode is required but not available during early init, the
firmware framebuffer will have already been released and the screen will
freeze.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 58 +++++----------------------
1 file changed, 9 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index ef2dbebbc90c..0dba690cf7dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -1245,7 +1245,7 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
}

static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
- const char *chip_name)
+ char *chip_name)
{
char fw_name[30];
int err;
@@ -1278,7 +1278,7 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
}

static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
- const char *chip_name)
+ char *chip_name)
{
char fw_name[30];
int err;
@@ -1333,7 +1333,7 @@ static bool gfx_v9_0_load_mec2_fw_bin_support(struct amdgpu_device *adev)
}

static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
- const char *chip_name)
+ char *chip_name)
{
char fw_name[30];
int err;
@@ -1379,58 +1379,24 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,

static int gfx_v9_0_init_microcode(struct amdgpu_device *adev)
{
- const char *chip_name;
+ char ucode_prefix[30];
int r;

DRM_DEBUG("\n");
-
- switch (adev->ip_versions[GC_HWIP][0]) {
- case IP_VERSION(9, 0, 1):
- chip_name = "vega10";
- break;
- case IP_VERSION(9, 2, 1):
- chip_name = "vega12";
- break;
- case IP_VERSION(9, 4, 0):
- chip_name = "vega20";
- break;
- case IP_VERSION(9, 2, 2):
- case IP_VERSION(9, 1, 0):
- 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;
- case IP_VERSION(9, 4, 1):
- chip_name = "arcturus";
- break;
- case IP_VERSION(9, 3, 0):
- if (adev->apu_flags & AMD_APU_IS_RENOIR)
- chip_name = "renoir";
- else
- chip_name = "green_sardine";
- break;
- case IP_VERSION(9, 4, 2):
- chip_name = "aldebaran";
- break;
- default:
- BUG();
- }
+ amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));

/* No CPG in Arcturus */
if (adev->gfx.num_gfx_rings) {
- r = gfx_v9_0_init_cp_gfx_microcode(adev, chip_name);
+ r = gfx_v9_0_init_cp_gfx_microcode(adev, ucode_prefix);
if (r)
return r;
}

- r = gfx_v9_0_init_rlc_microcode(adev, chip_name);
+ r = gfx_v9_0_init_rlc_microcode(adev, ucode_prefix);
if (r)
return r;

- r = gfx_v9_0_init_cp_compute_microcode(adev, chip_name);
+ r = gfx_v9_0_init_cp_compute_microcode(adev, ucode_prefix);
if (r)
return r;

@@ -2118,12 +2084,6 @@ static int gfx_v9_0_sw_init(void *handle)

adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;

- r = gfx_v9_0_init_microcode(adev);
- if (r) {
- DRM_ERROR("Failed to load gfx firmware!\n");
- return r;
- }
-
if (adev->gfx.rlc.funcs) {
if (adev->gfx.rlc.funcs->init) {
r = adev->gfx.rlc.funcs->init(adev);
@@ -4565,7 +4525,7 @@ static int gfx_v9_0_early_init(void *handle)
/* init rlcg reg access ctrl */
gfx_v9_0_init_rlcg_reg_access_ctrl(adev);

- return 0;
+ return gfx_v9_0_init_microcode(adev);
}

static int gfx_v9_0_ecc_late_init(void *handle)
--
2.34.1

2023-01-05 17:16:53

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 24/45] drm/amd/display: Load DMUB microcode during early_init

If DMUB is required for an ASIC, ensure that the microcode is available
and validates during early_init.

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

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Harry Wentland <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 89 ++++++++++++-------
1 file changed, 58 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 4829b5431e4c..c8c5d37c8b3a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1945,7 +1945,6 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
struct dmub_srv_fb_info *fb_info;
struct dmub_srv *dmub_srv;
const struct dmcub_firmware_header_v1_0 *hdr;
- const char *fw_name_dmub;
enum dmub_asic dmub_asic;
enum dmub_status status;
int r;
@@ -1953,73 +1952,46 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(2, 1, 0):
dmub_asic = DMUB_ASIC_DCN21;
- fw_name_dmub = FIRMWARE_RENOIR_DMUB;
- if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
- fw_name_dmub = FIRMWARE_GREEN_SARDINE_DMUB;
break;
case IP_VERSION(3, 0, 0):
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0)) {
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
dmub_asic = DMUB_ASIC_DCN30;
- fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB;
- } else {
+ else
dmub_asic = DMUB_ASIC_DCN30;
- fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB;
- }
break;
case IP_VERSION(3, 0, 1):
dmub_asic = DMUB_ASIC_DCN301;
- fw_name_dmub = FIRMWARE_VANGOGH_DMUB;
break;
case IP_VERSION(3, 0, 2):
dmub_asic = DMUB_ASIC_DCN302;
- fw_name_dmub = FIRMWARE_DIMGREY_CAVEFISH_DMUB;
break;
case IP_VERSION(3, 0, 3):
dmub_asic = DMUB_ASIC_DCN303;
- fw_name_dmub = FIRMWARE_BEIGE_GOBY_DMUB;
break;
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
dmub_asic = (adev->external_rev_id == YELLOW_CARP_B0) ? DMUB_ASIC_DCN31B : DMUB_ASIC_DCN31;
- fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB;
break;
case IP_VERSION(3, 1, 4):
dmub_asic = DMUB_ASIC_DCN314;
- fw_name_dmub = FIRMWARE_DCN_314_DMUB;
break;
case IP_VERSION(3, 1, 5):
dmub_asic = DMUB_ASIC_DCN315;
- fw_name_dmub = FIRMWARE_DCN_315_DMUB;
break;
case IP_VERSION(3, 1, 6):
dmub_asic = DMUB_ASIC_DCN316;
- fw_name_dmub = FIRMWARE_DCN316_DMUB;
break;
case IP_VERSION(3, 2, 0):
dmub_asic = DMUB_ASIC_DCN32;
- fw_name_dmub = FIRMWARE_DCN_V3_2_0_DMCUB;
break;
case IP_VERSION(3, 2, 1):
dmub_asic = DMUB_ASIC_DCN321;
- fw_name_dmub = FIRMWARE_DCN_V3_2_1_DMCUB;
break;
default:
/* ASIC doesn't support DMUB. */
return 0;
}

- r = request_firmware_direct(&adev->dm.dmub_fw, fw_name_dmub, adev->dev);
- if (r) {
- DRM_ERROR("DMUB firmware loading failed: %d\n", r);
- return 0;
- }
-
- r = amdgpu_ucode_validate(adev->dm.dmub_fw);
- if (r) {
- DRM_ERROR("Couldn't validate DMUB firmware: %d\n", r);
- return 0;
- }
-
hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data;
adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);

@@ -4513,6 +4485,61 @@ DEVICE_ATTR_WO(s3_debug);

#endif

+static int dm_init_microcode(struct amdgpu_device *adev)
+{
+ char *fw_name_dmub;
+ int r;
+
+ switch (adev->ip_versions[DCE_HWIP][0]) {
+ case IP_VERSION(2, 1, 0):
+ fw_name_dmub = FIRMWARE_RENOIR_DMUB;
+ if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
+ fw_name_dmub = FIRMWARE_GREEN_SARDINE_DMUB;
+ break;
+ case IP_VERSION(3, 0, 0):
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
+ fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB;
+ else
+ fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB;
+ break;
+ case IP_VERSION(3, 0, 1):
+ fw_name_dmub = FIRMWARE_VANGOGH_DMUB;
+ break;
+ case IP_VERSION(3, 0, 2):
+ fw_name_dmub = FIRMWARE_DIMGREY_CAVEFISH_DMUB;
+ break;
+ case IP_VERSION(3, 0, 3):
+ fw_name_dmub = FIRMWARE_BEIGE_GOBY_DMUB;
+ break;
+ case IP_VERSION(3, 1, 2):
+ case IP_VERSION(3, 1, 3):
+ fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB;
+ break;
+ case IP_VERSION(3, 1, 4):
+ fw_name_dmub = FIRMWARE_DCN_314_DMUB;
+ break;
+ case IP_VERSION(3, 1, 5):
+ fw_name_dmub = FIRMWARE_DCN_315_DMUB;
+ break;
+ case IP_VERSION(3, 1, 6):
+ fw_name_dmub = FIRMWARE_DCN316_DMUB;
+ break;
+ case IP_VERSION(3, 2, 0):
+ fw_name_dmub = FIRMWARE_DCN_V3_2_0_DMCUB;
+ break;
+ case IP_VERSION(3, 2, 1):
+ fw_name_dmub = FIRMWARE_DCN_V3_2_1_DMCUB;
+ break;
+ default:
+ /* ASIC doesn't support DMUB. */
+ return 0;
+ }
+ r = amdgpu_ucode_request(adev, &adev->dm.dmub_fw, fw_name_dmub);
+ if (r)
+ DRM_ERROR("DMUB firmware loading failed: %d\n", r);
+ return r;
+}
+
static int dm_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -4645,7 +4672,7 @@ static int dm_early_init(void *handle)
#endif
adev->dc_enabled = true;

- return 0;
+ return dm_init_microcode(adev);
}

static bool modereset_required(struct drm_crtc_state *crtc_state)
--
2.34.1

2023-01-05 17:17:40

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 35/45] drm/amd: Use `amdgpu_ucode_*` helpers for SDMA2.4

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index c52d246a1d96..fd2a7b66ac56 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -113,10 +113,9 @@ static void sdma_v2_4_init_golden_registers(struct amdgpu_device *adev)
static void sdma_v2_4_free_microcode(struct amdgpu_device *adev)
{
int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- release_firmware(adev->sdma.instance[i].fw);
- adev->sdma.instance[i].fw = NULL;
- }
+
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}

/**
@@ -151,10 +150,7 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
if (err)
goto out;
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
@@ -176,10 +172,8 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
pr_err("sdma_v2_4: Failed to load firmware \"%s\"\n", fw_name);
- for (i = 0; i < adev->sdma.num_instances; i++) {
- release_firmware(adev->sdma.instance[i].fw);
- adev->sdma.instance[i].fw = NULL;
- }
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}
return err;
}
--
2.34.1

2023-01-05 17:18:20

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 37/45] drm/amd: Use `amdgpu_ucode_*` helpers for SDMA on CIK

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index cbca9866645c..67d16236b216 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -73,10 +73,9 @@ u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev);
static void cik_sdma_free_microcode(struct amdgpu_device *adev)
{
int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- release_firmware(adev->sdma.instance[i].fw);
- adev->sdma.instance[i].fw = NULL;
- }
+
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}

/*
@@ -137,18 +136,15 @@ static int cik_sdma_init_microcode(struct amdgpu_device *adev)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
if (err)
goto out;
- err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
}
out:
if (err) {
pr_err("cik_sdma: Failed to load firmware \"%s\"\n", fw_name);
- for (i = 0; i < adev->sdma.num_instances; i++) {
- release_firmware(adev->sdma.instance[i].fw);
- adev->sdma.instance[i].fw = NULL;
- }
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}
return err;
}
--
2.34.1

2023-01-05 17:19:31

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 40/45] drm/amd: Use `amdgpu_ucode_*` helpers for CGS

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
index f1a050379190..456e385333b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
@@ -411,17 +411,10 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
return -EINVAL;
}

- err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
- if (err) {
- DRM_ERROR("Failed to request firmware\n");
- return err;
- }
-
- err = amdgpu_ucode_validate(adev->pm.fw);
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
if (err) {
DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
+ amdgpu_ucode_release(&adev->pm.fw);
return err;
}

--
2.34.1

2023-01-05 17:19:34

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 01/45] drm/amd: Delay removal of the firmware framebuffer

Removing the firmware framebuffer from the driver means that even
if the driver doesn't support the IP blocks in a GPU it will no
longer be functional after the driver fails to initialize.

This change will ensure that unsupported IP blocks at least cause
the driver to work with the EFI framebuffer.

Cc: [email protected]
Suggested-by: Alex Deucher <[email protected]>
Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 6 ------
2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 9a1a5c2864a0..cdb681398a99 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -37,6 +37,7 @@
#include <linux/pci-p2pdma.h>

#include <drm/drm_atomic_helper.h>
+#include <drm/drm_aperture.h>
#include <drm/drm_probe_helper.h>
#include <drm/amdgpu_drm.h>
#include <linux/vgaarb.h>
@@ -89,6 +90,8 @@ MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
#define AMDGPU_MAX_RETRY_LIMIT 2
#define AMDGPU_RETRY_SRIOV_RESET(r) ((r) == -EBUSY || (r) == -ETIMEDOUT || (r) == -EINVAL)

+static const struct drm_driver amdgpu_kms_driver;
+
const char *amdgpu_asic_name[] = {
"TAHITI",
"PITCAIRN",
@@ -3685,6 +3688,11 @@ int amdgpu_device_init(struct amdgpu_device *adev,
if (r)
return r;

+ /* Get rid of things like offb */
+ r = drm_aperture_remove_conflicting_pci_framebuffers(adev->pdev, &amdgpu_kms_driver);
+ if (r)
+ return r;
+
/* Enable TMZ based on IP_VERSION */
amdgpu_gmc_tmz_set(adev);

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index db7e34eacc35..b9f14ec9edb2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -23,7 +23,6 @@
*/

#include <drm/amdgpu_drm.h>
-#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
#include <drm/drm_gem.h>
#include <drm/drm_vblank.h>
@@ -2096,11 +2095,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
}
#endif

- /* Get rid of things like offb */
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver);
- if (ret)
- return ret;
-
adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev);
if (IS_ERR(adev))
return PTR_ERR(adev);
--
2.34.1

2023-01-05 17:19:58

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 31/45] drm/amd: Use `amdgpu_ucode_*` helpers for GFX8

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 94 ++++++++++-----------------
1 file changed, 33 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index d47135606e3e..04577e5234ae 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -924,20 +924,14 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)

static void gfx_v8_0_free_microcode(struct amdgpu_device *adev)
{
- release_firmware(adev->gfx.pfp_fw);
- adev->gfx.pfp_fw = NULL;
- release_firmware(adev->gfx.me_fw);
- adev->gfx.me_fw = NULL;
- release_firmware(adev->gfx.ce_fw);
- adev->gfx.ce_fw = NULL;
- release_firmware(adev->gfx.rlc_fw);
- adev->gfx.rlc_fw = NULL;
- release_firmware(adev->gfx.mec_fw);
- adev->gfx.mec_fw = NULL;
+ amdgpu_ucode_release(&adev->gfx.pfp_fw);
+ amdgpu_ucode_release(&adev->gfx.me_fw);
+ amdgpu_ucode_release(&adev->gfx.ce_fw);
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
+ amdgpu_ucode_release(&adev->gfx.mec_fw);
if ((adev->asic_type != CHIP_STONEY) &&
(adev->asic_type != CHIP_TOPAZ))
- release_firmware(adev->gfx.mec2_fw);
- adev->gfx.mec2_fw = NULL;
+ amdgpu_ucode_release(&adev->gfx.mec2_fw);

kfree(adev->gfx.rlc.register_list_format);
}
@@ -989,18 +983,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)

if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp_2.bin", chip_name);
- err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev);
- if (err == -ENOENT) {
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
+ if (err == -ENODEV) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
}
} else {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
}
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.pfp_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
@@ -1009,18 +1000,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)

if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me_2.bin", chip_name);
- err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
- if (err == -ENOENT) {
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
+ if (err == -ENODEV) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
}
} else {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
}
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.me_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
@@ -1030,18 +1018,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)

if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce_2.bin", chip_name);
- err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
- if (err == -ENOENT) {
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
+ if (err == -ENODEV) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
}
} else {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
}
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.ce_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
@@ -1060,10 +1045,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
adev->virt.chained_ib_support = false;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
if (err)
goto out;
- err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
@@ -1110,18 +1094,15 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)

if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec_2.bin", chip_name);
- err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev);
- if (err == -ENOENT) {
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
+ if (err == -ENODEV) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
- err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
}
} else {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
- err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
}
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.mec_fw);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
@@ -1132,19 +1113,16 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
(adev->asic_type != CHIP_TOPAZ)) {
if (adev->asic_type >= CHIP_POLARIS10 && adev->asic_type <= CHIP_POLARIS12) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2_2.bin", chip_name);
- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
- if (err == -ENOENT) {
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
+ if (err == -ENODEV) {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
}
} else {
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
}
if (!err) {
- err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
- if (err)
- goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)
adev->gfx.mec2_fw->data;
adev->gfx.mec2_fw_version =
@@ -1219,18 +1197,12 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
dev_err(adev->dev,
"gfx8: Failed to load firmware \"%s\"\n",
fw_name);
- release_firmware(adev->gfx.pfp_fw);
- adev->gfx.pfp_fw = NULL;
- release_firmware(adev->gfx.me_fw);
- adev->gfx.me_fw = NULL;
- release_firmware(adev->gfx.ce_fw);
- adev->gfx.ce_fw = NULL;
- release_firmware(adev->gfx.rlc_fw);
- adev->gfx.rlc_fw = NULL;
- release_firmware(adev->gfx.mec_fw);
- adev->gfx.mec_fw = NULL;
- release_firmware(adev->gfx.mec2_fw);
- adev->gfx.mec2_fw = NULL;
+ amdgpu_ucode_release(&adev->gfx.pfp_fw);
+ amdgpu_ucode_release(&adev->gfx.me_fw);
+ amdgpu_ucode_release(&adev->gfx.ce_fw);
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
+ amdgpu_ucode_release(&adev->gfx.mec_fw);
+ amdgpu_ucode_release(&adev->gfx.mec2_fw);
}
return err;
}
--
2.34.1

2023-01-05 17:20:21

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 04/45] drm/amd: Convert SMUv13 microcode to use `amdgpu_ucode_ip_version_decode`

The special case for the one dGPU has been moved into
`amdgpu_ucode_ip_version_decode`, so simplify this code.

Signed-off-by: Mario Limonciello <[email protected]>
Acked-by: Christian König <[email protected]>
Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index 0ac9cac805f9..506a49a4b425 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -88,7 +88,6 @@ static const int link_speed[] = {25, 50, 80, 160};
int smu_v13_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- const char *chip_name;
char fw_name[30];
char ucode_prefix[30];
int err = 0;
@@ -100,16 +99,9 @@ int smu_v13_0_init_microcode(struct smu_context *smu)
if (amdgpu_sriov_vf(adev))
return 0;

- switch (adev->ip_versions[MP1_HWIP][0]) {
- case IP_VERSION(13, 0, 2):
- chip_name = "aldebaran_smc";
- break;
- default:
- amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));
- chip_name = ucode_prefix;
- }
+ amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);

err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
if (err)
--
2.34.1

2023-01-05 17:20:21

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 33/45] drm/amd: Use `amdgpu_ucode_*` helpers for GMC7

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 979da6f510e8..4412e8c65726 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -156,16 +156,10 @@ static int gmc_v7_0_init_microcode(struct amdgpu_device *adev)

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);

- err = request_firmware(&adev->gmc.fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gmc.fw);
-
-out:
+ err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
if (err) {
pr_err("cik_mc: Failed to load firmware \"%s\"\n", fw_name);
- release_firmware(adev->gmc.fw);
- adev->gmc.fw = NULL;
+ amdgpu_ucode_release(&adev->gmc.fw);
}
return err;
}
@@ -1081,8 +1075,7 @@ static int gmc_v7_0_sw_fini(void *handle)
kfree(adev->gmc.vm_fault_info);
amdgpu_gart_table_vram_free(adev);
amdgpu_bo_fini(adev);
- release_firmware(adev->gmc.fw);
- adev->gmc.fw = NULL;
+ amdgpu_ucode_release(&adev->gmc.fw);

return 0;
}
--
2.34.1

2023-01-05 17:20:37

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 08/45] drm/amd: Make SDMA firmware load failures less noisy.

When firmware is missing we get failures at every step.
```
[ 3.855086] amdgpu 0000:04:00.0: Direct firmware load for amdgpu/green_sardine_sdma.bin failed with error -2
[ 3.855087] [drm:amdgpu_sdma_init_microcode [amdgpu]] *ERROR* SDMA: Failed to init firmware "amdgpu/green_sardine_sdma.bin"
[ 3.855398] [drm:sdma_v4_0_early_init [amdgpu]] *ERROR* Failed to load sdma firmware!
```
Realistically we don't need all of these, a user can tell from the first one
that request_firmware emitted what happened. Drop the others.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 95e9450f3348..0e1e2521fe25 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -280,10 +280,8 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
}

out:
- if (err) {
- DRM_ERROR("SDMA: Failed to init firmware \"%s\"\n", fw_name);
+ if (err)
amdgpu_sdma_destroy_inst_ctx(adev, duplicate);
- }
return err;
}

--
2.34.1

2023-01-05 17:21:17

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 09/45] drm/amd: Use `amdgpu_ucode_*` helpers for VCN

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 16 +++-------------
1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index a23e26b272b4..b37400107a37 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -206,19 +206,9 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
return -EINVAL;
}

- r = request_firmware(&adev->vcn.fw, fw_name, adev->dev);
+ r = amdgpu_ucode_request(adev, &adev->vcn.fw, fw_name);
if (r) {
- dev_err(adev->dev, "amdgpu_vcn: Can't load firmware \"%s\"\n",
- fw_name);
- return r;
- }
-
- r = amdgpu_ucode_validate(adev->vcn.fw);
- if (r) {
- dev_err(adev->dev, "amdgpu_vcn: Can't validate firmware \"%s\"\n",
- fw_name);
- release_firmware(adev->vcn.fw);
- adev->vcn.fw = NULL;
+ amdgpu_ucode_release(&adev->vcn.fw);
return r;
}

@@ -333,7 +323,7 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
}

- release_firmware(adev->vcn.fw);
+ amdgpu_ucode_release(&adev->vcn.fw);
mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
mutex_destroy(&adev->vcn.vcn_pg_lock);

--
2.34.1

2023-01-05 17:21:30

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 05/45] drm/amd: Add a new helper for loading/validating microcode

All microcode runs a basic validation after it's been loaded. Each
IP block as part of init will run both.

Introduce a wrapper for request_firmware and amdgpu_ucode_validate.
This wrapper will also remap any error codes from request_firmware
to -ENODEV. This is so that early_init will fail if firmware couldn't
be loaded instead of the IP block being disabled.

Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Fix argument to be ** not *
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 36 +++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 3 ++
2 files changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index eafcddce58d3..8ebfec12da87 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -1312,3 +1312,39 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type,

snprintf(ucode_prefix, len, "%s_%d_%d_%d", ip_name, maj, min, rev);
}
+
+/*
+ * amdgpu_ucode_request - Fetch and validate amdgpu microcode
+ *
+ * @adev: amdgpu device
+ * @fw: pointer to load firmware to
+ * @fw_name: firmware to load
+ *
+ * This is a helper that will use request_firmware and amdgpu_ucode_validate
+ * to load and run basic validation on firmware. If the load fails, remap
+ * the error code to -ENODEV, so that early_init functions will fail to load.
+ */
+int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
+ const char *fw_name)
+{
+ int err = request_firmware(fw, fw_name, adev->dev);
+
+ if (err)
+ return -ENODEV;
+ err = amdgpu_ucode_validate(*fw);
+ if (err)
+ dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name);
+
+ return err;
+}
+
+/*
+ * amdgpu_ucode_release - Release firmware microcode
+ *
+ * @fw: pointer to firmware to release
+ */
+void amdgpu_ucode_release(const struct firmware **fw)
+{
+ release_firmware(*fw);
+ *fw = NULL;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 552e06929229..848579d4988b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -544,6 +544,9 @@ void amdgpu_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
int amdgpu_ucode_validate(const struct firmware *fw);
+int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
+ const char *fw_name);
+void amdgpu_ucode_release(const struct firmware **fw);
bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
uint16_t hdr_major, uint16_t hdr_minor);

--
2.34.1

2023-01-05 17:21:50

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 42/45] drm/amd: Use `amdgpu_ucode_*` helpers for DMCU

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 61c192ead62f..79c4652e8e40 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1881,20 +1881,13 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
return 0;
}

- r = request_firmware_direct(&adev->dm.fw_dmcu, fw_name_dmcu, adev->dev);
- if (r == -ENOENT) {
+ r = amdgpu_ucode_request(adev, &adev->dm.fw_dmcu, fw_name_dmcu);
+ if (r == -ENODEV) {
/* DMCU firmware is not necessary, so don't raise a fuss if it's missing */
DRM_DEBUG_KMS("dm: DMCU firmware not found\n");
adev->dm.fw_dmcu = NULL;
return 0;
}
- if (r) {
- dev_err(adev->dev, "amdgpu_dm: Can't load firmware \"%s\"\n",
- fw_name_dmcu);
- return r;
- }
-
- r = amdgpu_ucode_validate(adev->dm.fw_dmcu);
if (r) {
dev_err(adev->dev, "amdgpu_dm: Can't validate firmware \"%s\"\n",
fw_name_dmcu);
--
2.34.1

2023-01-05 17:22:45

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 02/45] drm/amd: Add a legacy mapping to "amdgpu_ucode_ip_version_decode"

This will allow other parts of the driver that currently special
case firmware file names to before IP version style naming to just
have a single call to `amdgpu_ucode_ip_version_decode`.

Signed-off-by: Mario Limonciello <[email protected]>
Acked-by: Christian König <[email protected]>
Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 221 ++++++++++++++++++++++
1 file changed, 221 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 5cb62e6249c2..eafcddce58d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -1059,12 +1059,233 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
return 0;
}

+static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int block_type)
+{
+ if (block_type == MP0_HWIP) {
+ switch (adev->ip_versions[MP0_HWIP][0]) {
+ case IP_VERSION(9, 0, 0):
+ switch (adev->asic_type) {
+ case CHIP_VEGA10:
+ return "vega10";
+ case CHIP_VEGA12:
+ return "vega12";
+ default:
+ return NULL;
+ }
+ break;
+ case IP_VERSION(10, 0, 0):
+ case IP_VERSION(10, 0, 1):
+ if (adev->asic_type == CHIP_RAVEN) {
+ if (adev->apu_flags & AMD_APU_IS_RAVEN2)
+ return "raven2";
+ else if (adev->apu_flags & AMD_APU_IS_PICASSO)
+ return "picasso";
+ return "raven";
+ }
+ break;
+ case IP_VERSION(11, 0, 0):
+ return "navi10";
+ case IP_VERSION(11, 0, 2):
+ return "vega20";
+ case IP_VERSION(11, 0, 4):
+ return "arcturus";
+ case IP_VERSION(11, 0, 5):
+ return "navi14";
+ case IP_VERSION(11, 0, 7):
+ return "sienna_cichlid";
+ case IP_VERSION(11, 0, 9):
+ return "navi12";
+ case IP_VERSION(11, 0, 11):
+ return "navy_flounder";
+ case IP_VERSION(11, 0, 12):
+ return "dimgrey_cavefish";
+ case IP_VERSION(11, 0, 13):
+ return "beige_goby";
+ case IP_VERSION(11, 5, 0):
+ return "vangogh";
+ case IP_VERSION(12, 0, 1):
+ if (adev->asic_type == CHIP_RENOIR) {
+ if (adev->apu_flags & AMD_APU_IS_RENOIR)
+ return "renoir";
+ return "green_sardine";
+ }
+ break;
+ case IP_VERSION(13, 0, 2):
+ return "aldebaran";
+ case IP_VERSION(13, 0, 1):
+ case IP_VERSION(13, 0, 3):
+ return "yellow_carp";
+ }
+ } else if (block_type == MP1_HWIP) {
+ switch (adev->ip_versions[MP1_HWIP][0]) {
+ case IP_VERSION(9, 0, 0):
+ case IP_VERSION(10, 0, 0):
+ case IP_VERSION(10, 0, 1):
+ case IP_VERSION(11, 0, 2):
+ if (adev->asic_type == CHIP_ARCTURUS)
+ return "arcturus_smc";
+ return NULL;
+ case IP_VERSION(11, 0, 0):
+ return "navi10_smc";
+ case IP_VERSION(11, 0, 5):
+ return "navi14_smc";
+ case IP_VERSION(11, 0, 9):
+ return "navi12_smc";
+ case IP_VERSION(11, 0, 7):
+ return "sienna_cichlid_smc";
+ case IP_VERSION(11, 0, 11):
+ return "navy_flounder_smc";
+ case IP_VERSION(11, 0, 12):
+ return "dimgrey_cavefish_smc";
+ case IP_VERSION(11, 0, 13):
+ return "beige_goby_smc";
+ case IP_VERSION(13, 0, 2):
+ return "aldebaran_smc";
+ }
+ } else if (block_type == SDMA0_HWIP) {
+ switch (adev->ip_versions[SDMA0_HWIP][0]) {
+ case IP_VERSION(4, 0, 0):
+ return "vega10_sdma";
+ case IP_VERSION(4, 0, 1):
+ return "vega12_sdma";
+ case IP_VERSION(4, 1, 0):
+ case IP_VERSION(4, 1, 1):
+ if (adev->apu_flags & AMD_APU_IS_RAVEN2)
+ return "raven2_sdma";
+ else if (adev->apu_flags & AMD_APU_IS_PICASSO)
+ return "picasso_sdma";
+ return "raven_sdma";
+ case IP_VERSION(4, 1, 2):
+ if (adev->apu_flags & AMD_APU_IS_RENOIR)
+ return "renoir_sdma";
+ return "green_sardine_sdma";
+ case IP_VERSION(4, 2, 0):
+ return "vega20_sdma";
+ case IP_VERSION(4, 2, 2):
+ return "arcturus_sdma";
+ case IP_VERSION(4, 4, 0):
+ return "aldebaran_sdma";
+ case IP_VERSION(5, 0, 0):
+ return "navi10_sdma";
+ case IP_VERSION(5, 0, 1):
+ return "cyan_skillfish2_sdma";
+ case IP_VERSION(5, 0, 2):
+ return "navi14_sdma";
+ case IP_VERSION(5, 0, 5):
+ return "navi12_sdma";
+ case IP_VERSION(5, 2, 0):
+ return "sienna_cichlid_sdma";
+ case IP_VERSION(5, 2, 2):
+ return "navy_flounder_sdma";
+ case IP_VERSION(5, 2, 4):
+ return "dimgrey_cavefish_sdma";
+ case IP_VERSION(5, 2, 5):
+ return "beige_goby_sdma";
+ case IP_VERSION(5, 2, 3):
+ return "yellow_carp_sdma";
+ case IP_VERSION(5, 2, 1):
+ return "vangogh_sdma";
+ }
+ } else if (block_type == UVD_HWIP) {
+ switch (adev->ip_versions[UVD_HWIP][0]) {
+ case IP_VERSION(1, 0, 0):
+ case IP_VERSION(1, 0, 1):
+ if (adev->apu_flags & AMD_APU_IS_RAVEN2)
+ return "raven2_vcn";
+ else if (adev->apu_flags & AMD_APU_IS_PICASSO)
+ return "picasso_vcn";
+ return "raven_vcn";
+ case IP_VERSION(2, 5, 0):
+ return "arcturus_vcn";
+ case IP_VERSION(2, 2, 0):
+ if (adev->apu_flags & AMD_APU_IS_RENOIR)
+ return "renoir_vcn";
+ return "green_sardine_vcn";
+ case IP_VERSION(2, 6, 0):
+ return "aldebaran_vcn";
+ case IP_VERSION(2, 0, 0):
+ return "navi10_vcn";
+ case IP_VERSION(2, 0, 2):
+ if (adev->asic_type == CHIP_NAVI12)
+ return "navi12_vcn";
+ return "navi14_vcn";
+ case IP_VERSION(3, 0, 0):
+ case IP_VERSION(3, 0, 64):
+ case IP_VERSION(3, 0, 192):
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
+ return "sienna_cichlid_vcn";
+ return "navy_flounder_vcn";
+ case IP_VERSION(3, 0, 2):
+ return "vangogh_vcn";
+ case IP_VERSION(3, 0, 16):
+ return "dimgrey_cavefish_vcn";
+ case IP_VERSION(3, 0, 33):
+ return "beige_goby_vcn";
+ case IP_VERSION(3, 1, 1):
+ return "yellow_carp_vcn";
+ }
+ } else if (block_type == GC_HWIP) {
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(9, 0, 1):
+ return "vega10";
+ case IP_VERSION(9, 2, 1):
+ return "vega12";
+ case IP_VERSION(9, 4, 0):
+ return "vega20";
+ case IP_VERSION(9, 2, 2):
+ case IP_VERSION(9, 1, 0):
+ if (adev->apu_flags & AMD_APU_IS_RAVEN2)
+ return "raven2";
+ else if (adev->apu_flags & AMD_APU_IS_PICASSO)
+ return "picasso";
+ return "raven";
+ case IP_VERSION(9, 4, 1):
+ return "arcturus";
+ case IP_VERSION(9, 3, 0):
+ if (adev->apu_flags & AMD_APU_IS_RENOIR)
+ return "renoir";
+ return "green_sardine";
+ case IP_VERSION(9, 4, 2):
+ return "aldebaran";
+ case IP_VERSION(10, 1, 10):
+ return "navi10";
+ case IP_VERSION(10, 1, 1):
+ return "navi14";
+ case IP_VERSION(10, 1, 2):
+ return "navi12";
+ case IP_VERSION(10, 3, 0):
+ return "sienna_cichlid";
+ case IP_VERSION(10, 3, 2):
+ return "navy_flounder";
+ case IP_VERSION(10, 3, 1):
+ return "vangogh";
+ case IP_VERSION(10, 3, 4):
+ return "dimgrey_cavefish";
+ case IP_VERSION(10, 3, 5):
+ return "beige_goby";
+ case IP_VERSION(10, 3, 3):
+ return "yellow_carp";
+ case IP_VERSION(10, 1, 3):
+ case IP_VERSION(10, 1, 4):
+ return "cyan_skillfish2";
+ }
+ }
+ return NULL;
+}
+
void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, char *ucode_prefix, int len)
{
int maj, min, rev;
char *ip_name;
+ const char *legacy;
uint32_t version = adev->ip_versions[block_type][0];

+ legacy = amdgpu_ucode_legacy_naming(adev, block_type);
+ if (legacy) {
+ snprintf(ucode_prefix, len, "%s", legacy);
+ return;
+ }
+
switch (block_type) {
case GC_HWIP:
ip_name = "gc";
--
2.34.1

2023-01-05 17:22:52

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 34/45] drm/amd: Use `amdgpu_ucode_*` helpers for GMC8

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 382dde1ce74c..561daac2e6f7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -264,16 +264,10 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
- err = request_firmware(&adev->gmc.fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gmc.fw);
-
-out:
+ err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
if (err) {
pr_err("mc: Failed to load firmware \"%s\"\n", fw_name);
- release_firmware(adev->gmc.fw);
- adev->gmc.fw = NULL;
+ amdgpu_ucode_release(&adev->gmc.fw);
}
return err;
}
@@ -1203,8 +1197,7 @@ static int gmc_v8_0_sw_fini(void *handle)
kfree(adev->gmc.vm_fault_info);
amdgpu_gart_table_vram_free(adev);
amdgpu_bo_fini(adev);
- release_firmware(adev->gmc.fw);
- adev->gmc.fw = NULL;
+ amdgpu_ucode_release(&adev->gmc.fw);

return 0;
}
--
2.34.1

2023-01-05 17:23:00

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 11/45] drm/amd: Load MES microcode during early_init

Add an early_init phase to MES for fetching and validating microcode
from the filesystem.

If MES microcode is required but not available during early init, the
firmware framebuffer will have already been released and the screen will
freeze.

Move the request for MES microcode into the early_init phase
so that if it's not available, early_init will fail.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 65 +++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 1 +
drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 97 +++++--------------------
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 88 +++++-----------------
4 files changed, 100 insertions(+), 151 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
index 0c546245793b..dd8f35234507 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
@@ -21,6 +21,8 @@
*
*/

+#include <linux/firmware.h>
+
#include "amdgpu_mes.h"
#include "amdgpu.h"
#include "soc15_common.h"
@@ -1423,3 +1425,66 @@ int amdgpu_mes_self_test(struct amdgpu_device *adev)
kfree(vm);
return 0;
}
+
+int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
+{
+ const struct mes_firmware_header_v1_0 *mes_hdr;
+ struct amdgpu_firmware_info *info;
+ char ucode_prefix[30];
+ char fw_name[40];
+ int r;
+
+ amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes%s.bin",
+ ucode_prefix,
+ pipe == AMDGPU_MES_SCHED_PIPE ? "" : "1");
+ r = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev);
+ if (r)
+ goto out;
+
+ r = amdgpu_ucode_validate(adev->mes.fw[pipe]);
+ if (r)
+ goto out;
+
+ mes_hdr = (const struct mes_firmware_header_v1_0 *)
+ adev->mes.fw[pipe]->data;
+ adev->mes.uc_start_addr[pipe] =
+ le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
+ ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
+ adev->mes.data_start_addr[pipe] =
+ le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
+ ((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
+
+ if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+ int ucode, ucode_data;
+
+ if (pipe == AMDGPU_MES_SCHED_PIPE) {
+ ucode = AMDGPU_UCODE_ID_CP_MES;
+ ucode_data = AMDGPU_UCODE_ID_CP_MES_DATA;
+ } else {
+ ucode = AMDGPU_UCODE_ID_CP_MES1;
+ ucode_data = AMDGPU_UCODE_ID_CP_MES1_DATA;
+ }
+
+ info = &adev->firmware.ucode[ucode];
+ info->ucode_id = ucode;
+ info->fw = adev->mes.fw[pipe];
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(mes_hdr->mes_ucode_size_bytes),
+ PAGE_SIZE);
+
+ info = &adev->firmware.ucode[ucode_data];
+ info->ucode_id = ucode_data;
+ info->fw = adev->mes.fw[pipe];
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes),
+ PAGE_SIZE);
+ }
+
+ return 0;
+
+out:
+ release_firmware(adev->mes.fw[pipe]);
+ adev->mes.fw[pipe] = NULL;
+ return r;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
index 97c05d08a551..547ec35691fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
@@ -306,6 +306,7 @@ struct amdgpu_mes_funcs {

int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs);

+int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe);
int amdgpu_mes_init(struct amdgpu_device *adev);
void amdgpu_mes_fini(struct amdgpu_device *adev);

diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
index 614394118a53..9c5ff8b7c202 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -379,82 +379,6 @@ static const struct amdgpu_mes_funcs mes_v10_1_funcs = {
.resume_gang = mes_v10_1_resume_gang,
};

-static int mes_v10_1_init_microcode(struct amdgpu_device *adev,
- enum admgpu_mes_pipe pipe)
-{
- const char *chip_name;
- char fw_name[30];
- int err;
- const struct mes_firmware_header_v1_0 *mes_hdr;
- struct amdgpu_firmware_info *info;
-
- switch (adev->ip_versions[GC_HWIP][0]) {
- case IP_VERSION(10, 1, 10):
- chip_name = "navi10";
- break;
- case IP_VERSION(10, 3, 0):
- chip_name = "sienna_cichlid";
- break;
- default:
- BUG();
- }
-
- if (pipe == AMDGPU_MES_SCHED_PIPE)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin",
- chip_name);
- else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes1.bin",
- chip_name);
-
- err = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev);
- if (err)
- return err;
-
- err = amdgpu_ucode_validate(adev->mes.fw[pipe]);
- if (err) {
- release_firmware(adev->mes.fw[pipe]);
- adev->mes.fw[pipe] = NULL;
- return err;
- }
-
- mes_hdr = (const struct mes_firmware_header_v1_0 *)
- adev->mes.fw[pipe]->data;
- adev->mes.uc_start_addr[pipe] =
- le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
- ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
- adev->mes.data_start_addr[pipe] =
- le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
- ((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
-
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
- int ucode, ucode_data;
-
- if (pipe == AMDGPU_MES_SCHED_PIPE) {
- ucode = AMDGPU_UCODE_ID_CP_MES;
- ucode_data = AMDGPU_UCODE_ID_CP_MES_DATA;
- } else {
- ucode = AMDGPU_UCODE_ID_CP_MES1;
- ucode_data = AMDGPU_UCODE_ID_CP_MES1_DATA;
- }
-
- info = &adev->firmware.ucode[ucode];
- info->ucode_id = ucode;
- info->fw = adev->mes.fw[pipe];
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(mes_hdr->mes_ucode_size_bytes),
- PAGE_SIZE);
-
- info = &adev->firmware.ucode[ucode_data];
- info->ucode_id = ucode_data;
- info->fw = adev->mes.fw[pipe];
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes),
- PAGE_SIZE);
- }
-
- return 0;
-}
-
static void mes_v10_1_free_microcode(struct amdgpu_device *adev,
enum admgpu_mes_pipe pipe)
{
@@ -1019,10 +943,6 @@ static int mes_v10_1_sw_init(void *handle)
if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
continue;

- r = mes_v10_1_init_microcode(adev, pipe);
- if (r)
- return r;
-
r = mes_v10_1_allocate_eop_buf(adev, pipe);
if (r)
return r;
@@ -1229,6 +1149,22 @@ static int mes_v10_1_resume(void *handle)
return amdgpu_mes_resume(adev);
}

+static int mes_v10_0_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int pipe, r;
+
+ for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) {
+ if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
+ continue;
+ r = amdgpu_mes_init_microcode(adev, pipe);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
static int mes_v10_0_late_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1241,6 +1177,7 @@ static int mes_v10_0_late_init(void *handle)

static const struct amd_ip_funcs mes_v10_1_ip_funcs = {
.name = "mes_v10_1",
+ .early_init = mes_v10_0_early_init,
.late_init = mes_v10_0_late_init,
.sw_init = mes_v10_1_sw_init,
.sw_fini = mes_v10_1_sw_fini,
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 970b066b37bb..3af77a32baac 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -459,73 +459,6 @@ static const struct amdgpu_mes_funcs mes_v11_0_funcs = {
.misc_op = mes_v11_0_misc_op,
};

-static int mes_v11_0_init_microcode(struct amdgpu_device *adev,
- enum admgpu_mes_pipe pipe)
-{
- char fw_name[30];
- char ucode_prefix[30];
- int err;
- const struct mes_firmware_header_v1_0 *mes_hdr;
- struct amdgpu_firmware_info *info;
-
- amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- if (pipe == AMDGPU_MES_SCHED_PIPE)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin",
- ucode_prefix);
- else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes1.bin",
- ucode_prefix);
-
- err = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev);
- if (err)
- return err;
-
- err = amdgpu_ucode_validate(adev->mes.fw[pipe]);
- if (err) {
- release_firmware(adev->mes.fw[pipe]);
- adev->mes.fw[pipe] = NULL;
- return err;
- }
-
- mes_hdr = (const struct mes_firmware_header_v1_0 *)
- adev->mes.fw[pipe]->data;
- adev->mes.uc_start_addr[pipe] =
- le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
- ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
- adev->mes.data_start_addr[pipe] =
- le32_to_cpu(mes_hdr->mes_data_start_addr_lo) |
- ((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32);
-
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
- int ucode, ucode_data;
-
- if (pipe == AMDGPU_MES_SCHED_PIPE) {
- ucode = AMDGPU_UCODE_ID_CP_MES;
- ucode_data = AMDGPU_UCODE_ID_CP_MES_DATA;
- } else {
- ucode = AMDGPU_UCODE_ID_CP_MES1;
- ucode_data = AMDGPU_UCODE_ID_CP_MES1_DATA;
- }
-
- info = &adev->firmware.ucode[ucode];
- info->ucode_id = ucode;
- info->fw = adev->mes.fw[pipe];
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(mes_hdr->mes_ucode_size_bytes),
- PAGE_SIZE);
-
- info = &adev->firmware.ucode[ucode_data];
- info->ucode_id = ucode_data;
- info->fw = adev->mes.fw[pipe];
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes),
- PAGE_SIZE);
- }
-
- return 0;
-}
-
static void mes_v11_0_free_microcode(struct amdgpu_device *adev,
enum admgpu_mes_pipe pipe)
{
@@ -1100,10 +1033,6 @@ static int mes_v11_0_sw_init(void *handle)
if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
continue;

- r = mes_v11_0_init_microcode(adev, pipe);
- if (r)
- return r;
-
r = mes_v11_0_allocate_eop_buf(adev, pipe);
if (r)
return r;
@@ -1338,6 +1267,22 @@ static int mes_v11_0_resume(void *handle)
return amdgpu_mes_resume(adev);
}

+static int mes_v11_0_early_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ int pipe, r;
+
+ for (pipe = 0; pipe < AMDGPU_MAX_MES_PIPES; pipe++) {
+ if (!adev->enable_mes_kiq && pipe == AMDGPU_MES_KIQ_PIPE)
+ continue;
+ r = amdgpu_mes_init_microcode(adev, pipe);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
static int mes_v11_0_late_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1352,6 +1297,7 @@ static int mes_v11_0_late_init(void *handle)

static const struct amd_ip_funcs mes_v11_0_ip_funcs = {
.name = "mes_v11_0",
+ .early_init = mes_v11_0_early_init,
.late_init = mes_v11_0_late_init,
.sw_init = mes_v11_0_sw_init,
.sw_fini = mes_v11_0_sw_fini,
--
2.34.1

2023-01-05 17:23:15

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 17/45] drm/amd: Load GFX10 microcode during early_init

Simplifies the code so that GFX10 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: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 84 ++++++--------------------
1 file changed, 18 insertions(+), 66 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 140bb18ff768..6983acc456b2 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -3968,9 +3968,9 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev)

static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
{
- const char *chip_name;
char fw_name[40];
- char *wks = "";
+ char ucode_prefix[30];
+ const char *wks = "";
int err;
const struct rlc_firmware_header_v2_0 *rlc_hdr;
uint16_t version_major;
@@ -3978,71 +3978,31 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)

DRM_DEBUG("\n");

- switch (adev->ip_versions[GC_HWIP][0]) {
- case IP_VERSION(10, 1, 10):
- chip_name = "navi10";
- break;
- case IP_VERSION(10, 1, 1):
- chip_name = "navi14";
- if (!(adev->pdev->device == 0x7340 &&
- adev->pdev->revision != 0x00))
- wks = "_wks";
- break;
- case IP_VERSION(10, 1, 2):
- chip_name = "navi12";
- break;
- case IP_VERSION(10, 3, 0):
- chip_name = "sienna_cichlid";
- break;
- case IP_VERSION(10, 3, 2):
- chip_name = "navy_flounder";
- break;
- case IP_VERSION(10, 3, 1):
- chip_name = "vangogh";
- break;
- case IP_VERSION(10, 3, 4):
- chip_name = "dimgrey_cavefish";
- break;
- case IP_VERSION(10, 3, 5):
- chip_name = "beige_goby";
- break;
- case IP_VERSION(10, 3, 3):
- chip_name = "yellow_carp";
- break;
- case IP_VERSION(10, 3, 6):
- chip_name = "gc_10_3_6";
- break;
- case IP_VERSION(10, 1, 3):
- case IP_VERSION(10, 1, 4):
- chip_name = "cyan_skillfish2";
- break;
- case IP_VERSION(10, 3, 7):
- chip_name = "gc_10_3_7";
- break;
- default:
- BUG();
- }
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 1) &&
+ (!(adev->pdev->device == 0x7340 && adev->pdev->revision != 0x00)))
+ wks = "_wks";
+ amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp%s.bin", chip_name, wks);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp%s.bin", ucode_prefix, wks);
err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me%s.bin", chip_name, wks);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me%s.bin", ucode_prefix, wks);
err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce%s.bin", chip_name, wks);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce%s.bin", ucode_prefix, wks);
err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);

if (!amdgpu_sriov_vf(adev)) {
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", ucode_prefix);
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
/* don't check this. There are apparently firmwares in the wild with
* incorrect size in the header
@@ -4051,7 +4011,7 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
goto out;
if (err)
dev_dbg(adev->dev,
- "gfx10: amdgpu_ucode_validate() failed \"%s\"\n",
+ "gfx10: amdgpu_ucode_request() failed \"%s\"\n",
fw_name);
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
version_major = le16_to_cpu(rlc_hdr->header.header_version_major);
@@ -4061,14 +4021,14 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
goto out;
}

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec%s.bin", chip_name, wks);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec%s.bin", ucode_prefix, wks);
err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2%s.bin", chip_name, wks);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2%s.bin", ucode_prefix, wks);
err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
if (!err) {
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
@@ -4077,6 +4037,8 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
err = 0;
adev->gfx.mec2_fw = NULL;
}
+ amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
+ amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);

gfx_v10_0_check_fw_write_wait(adev);
out:
@@ -4239,19 +4201,11 @@ static void gfx_v10_0_mec_fini(struct amdgpu_device *adev)
amdgpu_bo_free_kernel(&adev->gfx.mec.mec_fw_obj, NULL, NULL);
}

-static int gfx_v10_0_me_init(struct amdgpu_device *adev)
+static void gfx_v10_0_me_init(struct amdgpu_device *adev)
{
- int r;
-
bitmap_zero(adev->gfx.me.queue_bitmap, AMDGPU_MAX_GFX_QUEUES);

amdgpu_gfx_graphics_queue_acquire(adev);
-
- r = gfx_v10_0_init_microcode(adev);
- if (r)
- DRM_ERROR("Failed to load gfx firmware!\n");
-
- return r;
}

static int gfx_v10_0_mec_init(struct amdgpu_device *adev)
@@ -4619,9 +4573,7 @@ static int gfx_v10_0_sw_init(void *handle)

adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;

- r = gfx_v10_0_me_init(adev);
- if (r)
- return r;
+ gfx_v10_0_me_init(adev);

if (adev->gfx.rlc.funcs) {
if (adev->gfx.rlc.funcs->init) {
@@ -7599,7 +7551,7 @@ static int gfx_v10_0_early_init(void *handle)
/* init rlcg reg access ctrl */
gfx_v10_0_init_rlcg_reg_access_ctrl(adev);

- return 0;
+ return gfx_v10_0_init_microcode(adev);
}

static int gfx_v10_0_late_init(void *handle)
--
2.34.1

2023-01-05 17:23:30

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 10/45] drm/amd: Load VCN microcode during early_init

Simplifies the code so that all VCN 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.

Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Fix whitespace problem in firmware file names
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 53 +++++++------------------
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 1 +
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 5 ++-
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 5 ++-
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 5 ++-
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 5 ++-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 5 ++-
7 files changed, 31 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index b37400107a37..0fb9a6d23065 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -80,10 +80,24 @@ MODULE_FIRMWARE(FIRMWARE_VCN4_0_4);

static void amdgpu_vcn_idle_work_handler(struct work_struct *work);

+int amdgpu_vcn_early_init(struct amdgpu_device *adev)
+{
+ char ucode_prefix[30];
+ char fw_name[40];
+ int r;
+
+ amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
+ r = amdgpu_ucode_request(adev, &adev->vcn.fw, fw_name);
+ if (r)
+ amdgpu_ucode_release(&adev->vcn.fw);
+
+ return r;
+}
+
int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
{
unsigned long bo_size;
- const char *fw_name;
const struct common_firmware_header *hdr;
unsigned char fw_check;
unsigned int fw_shared_size, log_offset;
@@ -99,46 +113,27 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
switch (adev->ip_versions[UVD_HWIP][0]) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
- if (adev->apu_flags & AMD_APU_IS_RAVEN2)
- fw_name = FIRMWARE_RAVEN2;
- else if (adev->apu_flags & AMD_APU_IS_PICASSO)
- fw_name = FIRMWARE_PICASSO;
- else
- fw_name = FIRMWARE_RAVEN;
- break;
case IP_VERSION(2, 5, 0):
- fw_name = FIRMWARE_ARCTURUS;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(2, 2, 0):
- if (adev->apu_flags & AMD_APU_IS_RENOIR)
- fw_name = FIRMWARE_RENOIR;
- else
- fw_name = FIRMWARE_GREEN_SARDINE;
-
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(2, 6, 0):
- fw_name = FIRMWARE_ALDEBARAN;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(2, 0, 0):
- fw_name = FIRMWARE_NAVI10;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(2, 0, 2):
- if (adev->asic_type == CHIP_NAVI12)
- fw_name = FIRMWARE_NAVI12;
- else
- fw_name = FIRMWARE_NAVI14;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
@@ -146,58 +141,46 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 64):
case IP_VERSION(3, 0, 192):
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0))
- fw_name = FIRMWARE_SIENNA_CICHLID;
- else
- fw_name = FIRMWARE_NAVY_FLOUNDER;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(3, 0, 2):
- fw_name = FIRMWARE_VANGOGH;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(3, 0, 16):
- fw_name = FIRMWARE_DIMGREY_CAVEFISH;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(3, 0, 33):
- fw_name = FIRMWARE_BEIGE_GOBY;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(3, 1, 1):
- fw_name = FIRMWARE_YELLOW_CARP;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(3, 1, 2):
- fw_name = FIRMWARE_VCN_3_1_2;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(4, 0, 0):
- fw_name = FIRMWARE_VCN4_0_0;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(4, 0, 2):
- fw_name = FIRMWARE_VCN4_0_2;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break;
case IP_VERSION(4, 0, 4):
- fw_name = FIRMWARE_VCN4_0_4;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
@@ -206,12 +189,6 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
return -EINVAL;
}

- r = amdgpu_ucode_request(adev, &adev->vcn.fw, fw_name);
- if (r) {
- amdgpu_ucode_release(&adev->vcn.fw);
- return r;
- }
-
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index dbb8d68a30c6..d3e2af902907 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -369,6 +369,7 @@ enum vcn_ring_type {
VCN_UNIFIED_RING,
};

+int amdgpu_vcn_early_init(struct amdgpu_device *adev);
int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
int amdgpu_vcn_sw_fini(struct amdgpu_device *adev);
int amdgpu_vcn_suspend(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index f0fbcda76f5e..c305b2cb8490 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -57,11 +57,12 @@ static void vcn_v1_0_idle_work_handler(struct work_struct *work);
static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);

/**
- * vcn_v1_0_early_init - set function pointers
+ * vcn_v1_0_early_init - set function pointers and load microcode
*
* @handle: amdgpu_device pointer
*
* Set ring and irq function pointers
+ * Load microcode from filesystem
*/
static int vcn_v1_0_early_init(void *handle)
{
@@ -75,7 +76,7 @@ static int vcn_v1_0_early_init(void *handle)

jpeg_v1_0_early_init(handle);

- return 0;
+ return amdgpu_vcn_early_init(adev);
}

/**
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index 08871bad9994..4b4cd88414e0 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -62,11 +62,12 @@ static int vcn_v2_0_pause_dpg_mode(struct amdgpu_device *adev,
int inst_idx, struct dpg_pause_state *new_state);
static int vcn_v2_0_start_sriov(struct amdgpu_device *adev);
/**
- * vcn_v2_0_early_init - set function pointers
+ * vcn_v2_0_early_init - set function pointers and load microcode
*
* @handle: amdgpu_device pointer
*
* Set ring and irq function pointers
+ * Load microcode from filesystem
*/
static int vcn_v2_0_early_init(void *handle)
{
@@ -81,7 +82,7 @@ static int vcn_v2_0_early_init(void *handle)
vcn_v2_0_set_enc_ring_funcs(adev);
vcn_v2_0_set_irq_funcs(adev);

- return 0;
+ return amdgpu_vcn_early_init(adev);
}

/**
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index ec87b00f2e05..b0b0e69c6a94 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -71,11 +71,12 @@ static int amdgpu_ih_clientid_vcns[] = {
};

/**
- * vcn_v2_5_early_init - set function pointers
+ * vcn_v2_5_early_init - set function pointers and load microcode
*
* @handle: amdgpu_device pointer
*
* Set ring and irq function pointers
+ * Load microcode from filesystem
*/
static int vcn_v2_5_early_init(void *handle)
{
@@ -107,7 +108,7 @@ static int vcn_v2_5_early_init(void *handle)
vcn_v2_5_set_irq_funcs(adev);
vcn_v2_5_set_ras_funcs(adev);

- return 0;
+ return amdgpu_vcn_early_init(adev);
}

/**
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 9c8b5fd99037..bd228512424a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -78,11 +78,12 @@ static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring);
static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);

/**
- * vcn_v3_0_early_init - set function pointers
+ * vcn_v3_0_early_init - set function pointers and load microcode
*
* @handle: amdgpu_device pointer
*
* Set ring and irq function pointers
+ * Load microcode from filesystem
*/
static int vcn_v3_0_early_init(void *handle)
{
@@ -109,7 +110,7 @@ static int vcn_v3_0_early_init(void *handle)
vcn_v3_0_set_enc_ring_funcs(adev);
vcn_v3_0_set_irq_funcs(adev);

- return 0;
+ return amdgpu_vcn_early_init(adev);
}

/**
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 1e2b22299975..a79b6088374b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -68,11 +68,12 @@ static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev);

/**
- * vcn_v4_0_early_init - set function pointers
+ * vcn_v4_0_early_init - set function pointers and load microcode
*
* @handle: amdgpu_device pointer
*
* Set ring and irq function pointers
+ * Load microcode from filesystem
*/
static int vcn_v4_0_early_init(void *handle)
{
@@ -88,7 +89,7 @@ static int vcn_v4_0_early_init(void *handle)
vcn_v4_0_set_irq_funcs(adev);
vcn_v4_0_set_ras_funcs(adev);

- return 0;
+ return amdgpu_vcn_early_init(adev);
}

/**
--
2.34.1

2023-01-05 17:23:46

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 14/45] drm/amd: Use `amdgpu_ucode_*` helpers for GFX9

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper will provide symmetry on unload.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 82 +++++++--------------------
1 file changed, 21 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index f202b45c413c..ef2dbebbc90c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -1078,18 +1078,12 @@ static int gfx_v9_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)

static void gfx_v9_0_free_microcode(struct amdgpu_device *adev)
{
- release_firmware(adev->gfx.pfp_fw);
- adev->gfx.pfp_fw = NULL;
- release_firmware(adev->gfx.me_fw);
- adev->gfx.me_fw = NULL;
- release_firmware(adev->gfx.ce_fw);
- adev->gfx.ce_fw = NULL;
- release_firmware(adev->gfx.rlc_fw);
- adev->gfx.rlc_fw = NULL;
- release_firmware(adev->gfx.mec_fw);
- adev->gfx.mec_fw = NULL;
- release_firmware(adev->gfx.mec2_fw);
- adev->gfx.mec2_fw = NULL;
+ amdgpu_ucode_release(&adev->gfx.pfp_fw);
+ amdgpu_ucode_release(&adev->gfx.me_fw);
+ amdgpu_ucode_release(&adev->gfx.ce_fw);
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
+ amdgpu_ucode_release(&adev->gfx.mec_fw);
+ amdgpu_ucode_release(&adev->gfx.mec2_fw);

kfree(adev->gfx.rlc.register_list_format);
}
@@ -1257,43 +1251,28 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev,
int err;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.pfp_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP);

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.me_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME);

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.ce_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE);

out:
if (err) {
- dev_err(adev->dev,
- "gfx9: Failed to init firmware \"%s\"\n",
- fw_name);
- release_firmware(adev->gfx.pfp_fw);
- adev->gfx.pfp_fw = NULL;
- release_firmware(adev->gfx.me_fw);
- adev->gfx.me_fw = NULL;
- release_firmware(adev->gfx.ce_fw);
- adev->gfx.ce_fw = NULL;
+ amdgpu_ucode_release(&adev->gfx.pfp_fw);
+ amdgpu_ucode_release(&adev->gfx.me_fw);
+ amdgpu_ucode_release(&adev->gfx.ce_fw);
}
return err;
}
@@ -1328,10 +1307,7 @@ static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_kicker_rlc.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
if (err)
goto out;
rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
@@ -1340,13 +1316,9 @@ static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
version_minor = le16_to_cpu(rlc_hdr->header.header_version_minor);
err = amdgpu_gfx_rlc_init_microcode(adev, version_major, version_minor);
out:
- if (err) {
- dev_err(adev->dev,
- "gfx9: Failed to init firmware \"%s\"\n",
- fw_name);
- release_firmware(adev->gfx.rlc_fw);
- adev->gfx.rlc_fw = NULL;
- }
+ if (err)
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
+
return err;
}

@@ -1371,12 +1343,9 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);

- err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw, fw_name);
if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.mec_fw);
- if (err)
- goto out;
+ return err;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT);

@@ -1386,11 +1355,8 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);

- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec2_fw, fw_name);
if (!err) {
- err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
- if (err)
- goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT);
} else {
@@ -1402,17 +1368,11 @@ static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev,
adev->gfx.mec2_feature_version = adev->gfx.mec_feature_version;
}

-out:
gfx_v9_0_check_if_need_gfxoff(adev);
gfx_v9_0_check_fw_write_wait(adev);
if (err) {
- dev_err(adev->dev,
- "gfx9: Failed to init firmware \"%s\"\n",
- fw_name);
- release_firmware(adev->gfx.mec_fw);
- adev->gfx.mec_fw = NULL;
- release_firmware(adev->gfx.mec2_fw);
- adev->gfx.mec2_fw = NULL;
+ amdgpu_ucode_release(&adev->gfx.mec_fw);
+ amdgpu_ucode_release(&adev->gfx.mec2_fw);
}
return err;
}
--
2.34.1

2023-01-05 17:23:56

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 25/45] drm/amd: Use `amdgpu_ucode_release` helper for DMUB

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c8c5d37c8b3a..61c192ead62f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1898,8 +1898,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
if (r) {
dev_err(adev->dev, "amdgpu_dm: Can't validate firmware \"%s\"\n",
fw_name_dmcu);
- release_firmware(adev->dm.fw_dmcu);
- adev->dm.fw_dmcu = NULL;
+ amdgpu_ucode_release(&adev->dm.fw_dmcu);
return r;
}

@@ -2113,11 +2112,8 @@ static int dm_sw_fini(void *handle)
adev->dm.dmub_srv = NULL;
}

- release_firmware(adev->dm.dmub_fw);
- adev->dm.dmub_fw = NULL;
-
- release_firmware(adev->dm.fw_dmcu);
- adev->dm.fw_dmcu = NULL;
+ amdgpu_ucode_release(&adev->dm.dmub_fw);
+ amdgpu_ucode_release(&adev->dm.fw_dmcu);

return 0;
}
--
2.34.1

2023-01-05 17:32:12

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 07/45] drm/amd: Convert SDMA to use `amdgpu_ucode_ip_version_decode`

Simplifies the code so that all SDMA versions will get the firmware
name from `amdgpu_ucode_ip_version_decode`.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 12 ++++--
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 47 +-------------------
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 30 +------------
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 55 +-----------------------
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 25 +----------
6 files changed, 17 insertions(+), 156 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index a6a491569022..95e9450f3348 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -200,15 +200,21 @@ void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
}

int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
- char *fw_name, u32 instance,
- bool duplicate)
+ u32 instance, bool duplicate)
{
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
int err = 0, i;
const struct sdma_firmware_header_v2_0 *sdma_hdr;
uint16_t version_major;
-
+ char ucode_prefix[30];
+ char fw_name[40];
+
+ amdgpu_ucode_ip_version_decode(adev, SDMA0_HWIP, ucode_prefix, sizeof(ucode_prefix));
+ if (instance == 0)
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
+ else
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s%d.bin", ucode_prefix, i);
err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw, fw_name);
if (err)
goto out;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
index 7d99205c2e01..2d16e6d36728 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
@@ -124,8 +124,8 @@ int amdgpu_sdma_process_ras_data_cb(struct amdgpu_device *adev,
int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
-int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
- char *fw_name, u32 instance, bool duplicate);
+int amdgpu_sdma_init_microcode(struct amdgpu_device *adev, u32 instance,
+ bool duplicate);
void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
bool duplicate);
void amdgpu_sdma_unset_buffer_funcs_helper(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index 4d780e4430e7..017ae298558e 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -575,60 +575,17 @@ static void sdma_v4_0_setup_ulv(struct amdgpu_device *adev)
// vega10 real chip need to use PSP to load firmware
static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
{
- const char *chip_name;
- char fw_name[30];
int ret, i;

- DRM_DEBUG("\n");
-
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
- case IP_VERSION(4, 0, 0):
- chip_name = "vega10";
- break;
- case IP_VERSION(4, 0, 1):
- chip_name = "vega12";
- break;
- case IP_VERSION(4, 2, 0):
- chip_name = "vega20";
- break;
- case IP_VERSION(4, 1, 0):
- case IP_VERSION(4, 1, 1):
- 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;
- case IP_VERSION(4, 2, 2):
- chip_name = "arcturus";
- break;
- case IP_VERSION(4, 1, 2):
- if (adev->apu_flags & AMD_APU_IS_RENOIR)
- chip_name = "renoir";
- else
- chip_name = "green_sardine";
- break;
- case IP_VERSION(4, 4, 0):
- chip_name = "aldebaran";
- break;
- default:
- BUG();
- }
-
for (i = 0; i < adev->sdma.num_instances; i++) {
- if (i == 0)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
- else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma%d.bin", chip_name, i);
if (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 2, 2) ||
adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(4, 4, 0)) {
/* Acturus & Aldebaran will leverage the same FW memory
for every SDMA instance */
- ret = amdgpu_sdma_init_microcode(adev, fw_name, 0, true);
+ ret = amdgpu_sdma_init_microcode(adev, 0, true);
break;
} else {
- ret = amdgpu_sdma_init_microcode(adev, fw_name, i, false);
+ ret = amdgpu_sdma_init_microcode(adev, i, false);
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index d4d9f196db83..1941b3b7c5d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -237,39 +237,13 @@ static void sdma_v5_0_init_golden_registers(struct amdgpu_device *adev)
// emulation only, won't work on real chip
// navi10 real chip need to use PSP to load firmware
static int sdma_v5_0_init_microcode(struct amdgpu_device *adev)
-{
- const char *chip_name;
- char fw_name[40];
- int ret, i;
+{ int ret, i;

if (amdgpu_sriov_vf(adev) && (adev->ip_versions[SDMA0_HWIP][0] == IP_VERSION(5, 0, 5)))
return 0;

- DRM_DEBUG("\n");
-
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
- case IP_VERSION(5, 0, 0):
- chip_name = "navi10";
- break;
- case IP_VERSION(5, 0, 2):
- chip_name = "navi14";
- break;
- case IP_VERSION(5, 0, 5):
- chip_name = "navi12";
- break;
- case IP_VERSION(5, 0, 1):
- chip_name = "cyan_skillfish2";
- break;
- default:
- BUG();
- }
-
for (i = 0; i < adev->sdma.num_instances; i++) {
- if (i == 0)
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
- else
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- ret = amdgpu_sdma_init_microcode(adev, fw_name, i, false);
+ ret = amdgpu_sdma_init_microcode(adev, i, false);
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index 65e7a710298d..8e445eb9dd49 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -89,59 +89,6 @@ static u32 sdma_v5_2_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3
return base + internal_offset;
}

-/**
- * sdma_v5_2_init_microcode - load ucode images from disk
- *
- * @adev: amdgpu_device pointer
- *
- * Use the firmware interface to load the ucode images into
- * the driver (not loaded into hw).
- * Returns 0 on success, error on failure.
- */
-
-// emulation only, won't work on real chip
-// navi10 real chip need to use PSP to load firmware
-static int sdma_v5_2_init_microcode(struct amdgpu_device *adev)
-{
- const char *chip_name;
- char fw_name[40];
-
- DRM_DEBUG("\n");
-
- switch (adev->ip_versions[SDMA0_HWIP][0]) {
- case IP_VERSION(5, 2, 0):
- chip_name = "sienna_cichlid_sdma";
- break;
- case IP_VERSION(5, 2, 2):
- chip_name = "navy_flounder_sdma";
- break;
- case IP_VERSION(5, 2, 1):
- chip_name = "vangogh_sdma";
- break;
- case IP_VERSION(5, 2, 4):
- chip_name = "dimgrey_cavefish_sdma";
- break;
- case IP_VERSION(5, 2, 5):
- chip_name = "beige_goby_sdma";
- break;
- case IP_VERSION(5, 2, 3):
- chip_name = "yellow_carp_sdma";
- break;
- case IP_VERSION(5, 2, 6):
- chip_name = "sdma_5_2_6";
- break;
- case IP_VERSION(5, 2, 7):
- chip_name = "sdma_5_2_7";
- break;
- default:
- BUG();
- }
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", chip_name);
-
- return amdgpu_sdma_init_microcode(adev, fw_name, 0, true);
-}
-
static unsigned sdma_v5_2_ring_init_cond_exec(struct amdgpu_ring *ring)
{
unsigned ret;
@@ -1288,7 +1235,7 @@ static int sdma_v5_2_sw_init(void *handle)
return r;
}

- r = sdma_v5_2_init_microcode(adev);
+ r = amdgpu_sdma_init_microcode(adev, 0, true);
if (r) {
DRM_ERROR("Failed to load sdma firmware!\n");
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 049c26a45d85..bf1fa5e8d2f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -78,29 +78,6 @@ static u32 sdma_v6_0_get_reg_offset(struct amdgpu_device *adev, u32 instance, u3
return base + internal_offset;
}

-/**
- * sdma_v6_0_init_microcode - load ucode images from disk
- *
- * @adev: amdgpu_device pointer
- *
- * Use the firmware interface to load the ucode images into
- * the driver (not loaded into hw).
- * Returns 0 on success, error on failure.
- */
-static int sdma_v6_0_init_microcode(struct amdgpu_device *adev)
-{
- char fw_name[30];
- char ucode_prefix[30];
-
- DRM_DEBUG("\n");
-
- amdgpu_ucode_ip_version_decode(adev, SDMA0_HWIP, ucode_prefix, sizeof(ucode_prefix));
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);
-
- return amdgpu_sdma_init_microcode(adev, fw_name, 0, true);
-}
-
static unsigned sdma_v6_0_ring_init_cond_exec(struct amdgpu_ring *ring)
{
unsigned ret;
@@ -1260,7 +1237,7 @@ static int sdma_v6_0_sw_init(void *handle)
if (r)
return r;

- r = sdma_v6_0_init_microcode(adev);
+ r = amdgpu_sdma_init_microcode(adev, 0, true);
if (r) {
DRM_ERROR("Failed to load sdma firmware!\n");
return r;
--
2.34.1

2023-01-05 17:36:36

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 12/45] drm/amd: Use `amdgpu_ucode_*` helpers for MES

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper provides symmetry for releasing firmware.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 10 ++--------
drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 10 +---------
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 10 +---------
3 files changed, 4 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
index dd8f35234507..82e27bd4f038 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
@@ -1438,11 +1438,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes%s.bin",
ucode_prefix,
pipe == AMDGPU_MES_SCHED_PIPE ? "" : "1");
- r = request_firmware(&adev->mes.fw[pipe], fw_name, adev->dev);
- if (r)
- goto out;
-
- r = amdgpu_ucode_validate(adev->mes.fw[pipe]);
+ r = amdgpu_ucode_request(adev, &adev->mes.fw[pipe], fw_name);
if (r)
goto out;

@@ -1482,9 +1478,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe)
}

return 0;
-
out:
- release_firmware(adev->mes.fw[pipe]);
- adev->mes.fw[pipe] = NULL;
+ amdgpu_ucode_release(&adev->mes.fw[pipe]);
return r;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
index 9c5ff8b7c202..7848b9de79ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -379,13 +379,6 @@ static const struct amdgpu_mes_funcs mes_v10_1_funcs = {
.resume_gang = mes_v10_1_resume_gang,
};

-static void mes_v10_1_free_microcode(struct amdgpu_device *adev,
- enum admgpu_mes_pipe pipe)
-{
- release_firmware(adev->mes.fw[pipe]);
- adev->mes.fw[pipe] = NULL;
-}
-
static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev,
enum admgpu_mes_pipe pipe)
{
@@ -979,8 +972,7 @@ static int mes_v10_1_sw_fini(void *handle)
amdgpu_bo_free_kernel(&adev->mes.eop_gpu_obj[pipe],
&adev->mes.eop_gpu_addr[pipe],
NULL);
-
- mes_v10_1_free_microcode(adev, pipe);
+ amdgpu_ucode_release(&adev->mes.fw[pipe]);
}

amdgpu_bo_free_kernel(&adev->gfx.kiq.ring.mqd_obj,
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 3af77a32baac..a0125e103007 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -459,13 +459,6 @@ static const struct amdgpu_mes_funcs mes_v11_0_funcs = {
.misc_op = mes_v11_0_misc_op,
};

-static void mes_v11_0_free_microcode(struct amdgpu_device *adev,
- enum admgpu_mes_pipe pipe)
-{
- release_firmware(adev->mes.fw[pipe]);
- adev->mes.fw[pipe] = NULL;
-}
-
static int mes_v11_0_allocate_ucode_buffer(struct amdgpu_device *adev,
enum admgpu_mes_pipe pipe)
{
@@ -1069,8 +1062,7 @@ static int mes_v11_0_sw_fini(void *handle)
amdgpu_bo_free_kernel(&adev->mes.eop_gpu_obj[pipe],
&adev->mes.eop_gpu_addr[pipe],
NULL);
-
- mes_v11_0_free_microcode(adev, pipe);
+ amdgpu_ucode_release(&adev->mes.fw[pipe]);
}

amdgpu_bo_free_kernel(&adev->gfx.kiq.ring.mqd_obj,
--
2.34.1

2023-01-05 17:36:53

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 43/45] drm/amd: Use `amdgpu_ucode_release` helper for powerplay

The `amdgpu_ucode_release` helper is replacing all calls to
release_firmware.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
index 8f2cc6310340..11b7b4cffaae 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
@@ -111,8 +111,7 @@ static int pp_sw_fini(void *handle)

hwmgr_sw_fini(hwmgr);

- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
+ amdgpu_ucode_release(&adev->pm.fw);

return 0;
}
--
2.34.1

2023-01-05 17:37:38

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 27/45] drm/amd: Load SMU microcode during early_init

This will ensure that the microcode is available before the firmware
framebuffer has been destroyed.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 2fa79f892a92..ec52830dde24 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -623,6 +623,7 @@ static int smu_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct smu_context *smu;
+ int r;

smu = kzalloc(sizeof(struct smu_context), GFP_KERNEL);
if (!smu)
@@ -640,7 +641,10 @@ static int smu_early_init(void *handle)
adev->powerplay.pp_handle = smu;
adev->powerplay.pp_funcs = &swsmu_pm_funcs;

- return smu_set_funcs(adev);
+ r = smu_set_funcs(adev);
+ if (r)
+ return r;
+ return smu_init_microcode(smu);
}

static int smu_set_default_dpm_table(struct smu_context *smu)
@@ -1067,12 +1071,6 @@ static int smu_sw_init(void *handle)
smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;

- ret = smu_init_microcode(smu);
- if (ret) {
- dev_err(adev->dev, "Failed to load smu firmware!\n");
- return ret;
- }
-
ret = smu_smc_table_sw_init(smu);
if (ret) {
dev_err(adev->dev, "Failed to sw init smc table!\n");
--
2.34.1

2023-01-05 17:40:24

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 39/45] drm/amd: Use `amdgpu_ucode_*` helpers for VCE

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 02cb3a12dd76..ea78b7513182 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -158,19 +158,11 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
return -EINVAL;
}

- r = request_firmware(&adev->vce.fw, fw_name, adev->dev);
- if (r) {
- dev_err(adev->dev, "amdgpu_vce: Can't load firmware \"%s\"\n",
- fw_name);
- return r;
- }
-
- r = amdgpu_ucode_validate(adev->vce.fw);
+ r = amdgpu_ucode_request(adev, &adev->vce.fw, fw_name);
if (r) {
dev_err(adev->dev, "amdgpu_vce: Can't validate firmware \"%s\"\n",
fw_name);
- release_firmware(adev->vce.fw);
- adev->vce.fw = NULL;
+ amdgpu_ucode_release(&adev->vce.fw);
return r;
}

@@ -226,7 +218,7 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
for (i = 0; i < adev->vce.num_rings; i++)
amdgpu_ring_fini(&adev->vce.ring[i]);

- release_firmware(adev->vce.fw);
+ amdgpu_ucode_release(&adev->vce.fw);
mutex_destroy(&adev->vce.idle_mutex);

return 0;
--
2.34.1

2023-01-05 17:40:43

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 29/45] drm/amd: Use `amdgpu_ucode_*` helpers for GFX6

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 30 +++++++--------------------
1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
index 204b246f0e3f..438eab348fc8 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
@@ -338,10 +338,7 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name);
- err = request_firmware(&adev->gfx.pfp_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.pfp_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.pfp_fw, fw_name);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
@@ -349,10 +346,7 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
- err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.me_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, fw_name);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
@@ -360,10 +354,7 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
- err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.ce_fw);
+ err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, fw_name);
if (err)
goto out;
cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
@@ -371,10 +362,9 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
- err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, fw_name);
if (err)
goto out;
- err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
rlc_hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
@@ -382,14 +372,10 @@ static int gfx_v6_0_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
pr_err("gfx6: Failed to load firmware \"%s\"\n", fw_name);
- release_firmware(adev->gfx.pfp_fw);
- adev->gfx.pfp_fw = NULL;
- release_firmware(adev->gfx.me_fw);
- adev->gfx.me_fw = NULL;
- release_firmware(adev->gfx.ce_fw);
- adev->gfx.ce_fw = NULL;
- release_firmware(adev->gfx.rlc_fw);
- adev->gfx.rlc_fw = NULL;
+ amdgpu_ucode_release(&adev->gfx.pfp_fw);
+ amdgpu_ucode_release(&adev->gfx.me_fw);
+ amdgpu_ucode_release(&adev->gfx.ce_fw);
+ amdgpu_ucode_release(&adev->gfx.rlc_fw);
}
return err;
}
--
2.34.1

2023-01-05 17:41:32

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 06/45] drm/amd: Use `amdgpu_ucode_request` helper for SDMA

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index ea5278f094c0..a6a491569022 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -154,16 +154,11 @@ int amdgpu_sdma_process_ecc_irq(struct amdgpu_device *adev,

static int amdgpu_sdma_init_inst_ctx(struct amdgpu_sdma_instance *sdma_inst)
{
- int err = 0;
uint16_t version_major;
const struct common_firmware_header *header = NULL;
const struct sdma_firmware_header_v1_0 *hdr;
const struct sdma_firmware_header_v2_0 *hdr_v2;

- err = amdgpu_ucode_validate(sdma_inst->fw);
- if (err)
- return err;
-
header = (const struct common_firmware_header *)
sdma_inst->fw->data;
version_major = le16_to_cpu(header->header_version_major);
@@ -195,7 +190,7 @@ void amdgpu_sdma_destroy_inst_ctx(struct amdgpu_device *adev,
int i;

for (i = 0; i < adev->sdma.num_instances; i++) {
- release_firmware(adev->sdma.instance[i].fw);
+ amdgpu_ucode_release(&adev->sdma.instance[i].fw);
if (duplicate)
break;
}
@@ -214,7 +209,7 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev,
const struct sdma_firmware_header_v2_0 *sdma_hdr;
uint16_t version_major;

- err = request_firmware(&adev->sdma.instance[instance].fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[instance].fw, fw_name);
if (err)
goto out;

--
2.34.1

2023-01-05 17:42:41

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 45/45] drm/amd: make amdgpu_ucode_validate static

No consumers outside of amdgpu_ucode.c use amdgpu_ucode_validate
anymore, so make the function static.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 8ebfec12da87..47549d659d9b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -504,7 +504,7 @@ void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr)
}
}

-int amdgpu_ucode_validate(const struct firmware *fw)
+static int amdgpu_ucode_validate(const struct firmware *fw)
{
const struct common_firmware_header *hdr =
(const struct common_firmware_header *)fw->data;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 848579d4988b..bee93ab4298f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -543,7 +543,6 @@ void amdgpu_ucode_print_rlc_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_sdma_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr);
void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
-int amdgpu_ucode_validate(const struct firmware *fw);
int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
const char *fw_name);
void amdgpu_ucode_release(const struct firmware **fw);
--
2.34.1

2023-01-05 17:57:48

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 28/45] drm/amd: Optimize SRIOV switch/case for PSP microcode load

Now that IP version decoding is used, a number of case statements
can be combined.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Christian König <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index aae76acc38e5..706cce2edfaa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -132,14 +132,8 @@ static int psp_init_sriov_microcode(struct psp_context *psp)

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):
+ 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;
--
2.34.1

2023-01-05 18:04:15

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 20/45] drm/amd: Parse both v1 and v2 TA microcode headers using same function

Several IP versions duplicate code and can't use the common helpers.
Move this code into a single function so that the helpers can be used.

Signed-off-by: Mario Limonciello <[email protected]>
---
v6->v7:
* Drop tags
* Only set adev->psp.securedisplay_context.context on PSPv12 Renoir and
PSP v10 which matches previous behavior. If it should match for Cezanne
and PSPv11 too we can undo this part of the check.
v5->v6:
* Rebase on earlier patches
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 123 ++++++++++++++++++------
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 64 +-----------
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 80 ++-------------
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 66 ++-----------
4 files changed, 115 insertions(+), 218 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 7a2fc920739b..bdc2bf87a286 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -3272,41 +3272,76 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
return 0;
}

-int psp_init_ta_microcode(struct psp_context *psp,
- const char *chip_name)
+static int parse_ta_v1_microcode(struct psp_context *psp)
{
+ const struct ta_firmware_header_v1_0 *ta_hdr;
struct amdgpu_device *adev = psp->adev;
- char fw_name[PSP_FW_NAME_LEN];
- const struct ta_firmware_header_v2_0 *ta_hdr;
- int err = 0;
- int ta_index = 0;

- if (!chip_name) {
- dev_err(adev->dev, "invalid chip name for ta microcode\n");
+ ta_hdr = (const struct ta_firmware_header_v1_0 *) adev->psp.ta_fw->data;
+
+ if (le16_to_cpu(ta_hdr->header.header_version_major) != 1)
return -EINVAL;
- }

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
- err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
- if (err)
- goto out;
+ adev->psp.xgmi_context.context.bin_desc.fw_version =
+ le32_to_cpu(ta_hdr->xgmi.fw_version);
+ adev->psp.xgmi_context.context.bin_desc.size_bytes =
+ le32_to_cpu(ta_hdr->xgmi.size_bytes);
+ adev->psp.xgmi_context.context.bin_desc.start_addr =
+ (uint8_t *)ta_hdr +
+ le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+
+ adev->psp.ras_context.context.bin_desc.fw_version =
+ le32_to_cpu(ta_hdr->ras.fw_version);
+ adev->psp.ras_context.context.bin_desc.size_bytes =
+ le32_to_cpu(ta_hdr->ras.size_bytes);
+ adev->psp.ras_context.context.bin_desc.start_addr =
+ (uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr +
+ le32_to_cpu(ta_hdr->ras.offset_bytes);
+
+ adev->psp.hdcp_context.context.bin_desc.fw_version =
+ le32_to_cpu(ta_hdr->hdcp.fw_version);
+ adev->psp.hdcp_context.context.bin_desc.size_bytes =
+ le32_to_cpu(ta_hdr->hdcp.size_bytes);
+ adev->psp.hdcp_context.context.bin_desc.start_addr =
+ (uint8_t *)ta_hdr +
+ le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+
+ adev->psp.dtm_context.context.bin_desc.fw_version =
+ le32_to_cpu(ta_hdr->dtm.fw_version);
+ adev->psp.dtm_context.context.bin_desc.size_bytes =
+ le32_to_cpu(ta_hdr->dtm.size_bytes);
+ adev->psp.dtm_context.context.bin_desc.start_addr =
+ (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
+ le32_to_cpu(ta_hdr->dtm.offset_bytes);
+
+ adev->psp.securedisplay_context.context.bin_desc.fw_version =
+ le32_to_cpu(ta_hdr->securedisplay.fw_version);
+ adev->psp.securedisplay_context.context.bin_desc.size_bytes =
+ le32_to_cpu(ta_hdr->securedisplay.size_bytes);
+ adev->psp.securedisplay_context.context.bin_desc.start_addr =
+ (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
+ le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
+
+ adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);

- err = amdgpu_ucode_validate(adev->psp.ta_fw);
- if (err)
- goto out;
+ return 0;
+}
+
+static int parse_ta_v2_microcode(struct psp_context *psp)
+{
+ const struct ta_firmware_header_v2_0 *ta_hdr;
+ struct amdgpu_device *adev = psp->adev;
+ int err = 0;
+ int ta_index = 0;

ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data;

- if (le16_to_cpu(ta_hdr->header.header_version_major) != 2) {
- dev_err(adev->dev, "unsupported TA header version\n");
- err = -EINVAL;
- goto out;
- }
+ if (le16_to_cpu(ta_hdr->header.header_version_major) != 2)
+ return -EINVAL;

if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
- err = -EINVAL;
- goto out;
+ return -EINVAL;
}

for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) {
@@ -3314,14 +3349,46 @@ int psp_init_ta_microcode(struct psp_context *psp,
&ta_hdr->ta_fw_bin[ta_index],
ta_hdr);
if (err)
- goto out;
+ return err;
}

return 0;
-out:
- dev_err(adev->dev, "fail to initialize ta microcode\n");
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
+}
+
+int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
+{
+ const struct common_firmware_header *hdr;
+ struct amdgpu_device *adev = psp->adev;
+ char fw_name[PSP_FW_NAME_LEN];
+ int err;
+
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
+ err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
+ if (err)
+ return err;
+ err = amdgpu_ucode_validate(adev->psp.ta_fw);
+ if (err)
+ return err;
+
+ hdr = (const struct common_firmware_header *)adev->psp.ta_fw->data;
+ switch (le16_to_cpu(hdr->header_version_major)) {
+ case 1:
+ err = parse_ta_v1_microcode(psp);
+ break;
+ case 2:
+ err = parse_ta_v2_microcode(psp);
+ break;
+ default:
+ dev_err(adev->dev, "unsupported TA header version\n");
+ err = -EINVAL;
+ }
+
+ if (err) {
+ dev_err(adev->dev, "fail to initialize ta microcode\n");
+ release_firmware(adev->psp.ta_fw);
+ adev->psp.ta_fw = NULL;
+ }
+
return err;
}

diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 9de46fa8f46c..f14fcfb9c425 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -48,9 +48,8 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
const char *chip_name;
- char fw_name[30];
+ char ucode_prefix[30];
int err = 0;
- const struct ta_firmware_header_v1_0 *ta_hdr;
DRM_DEBUG("\n");

switch (adev->asic_type) {
@@ -64,66 +63,13 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
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)
- goto out;
-
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
- err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
- if (err) {
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
- dev_info(adev->dev,
- "psp v10.0: Failed to load firmware \"%s\"\n",
- fw_name);
- } else {
- err = amdgpu_ucode_validate(adev->psp.ta_fw);
- if (err)
- goto out2;
-
- ta_hdr = (const struct ta_firmware_header_v1_0 *)
- adev->psp.ta_fw->data;
- adev->psp.hdcp_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->hdcp.fw_version);
- adev->psp.hdcp_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->hdcp.size_bytes);
- adev->psp.hdcp_context.context.bin_desc.start_addr =
- (uint8_t *)ta_hdr +
- le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
-
- adev->psp.dtm_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->dtm.fw_version);
- adev->psp.dtm_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->dtm.size_bytes);
- adev->psp.dtm_context.context.bin_desc.start_addr =
- (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
- le32_to_cpu(ta_hdr->dtm.offset_bytes);
-
- adev->psp.securedisplay_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->securedisplay.fw_version);
- adev->psp.securedisplay_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->securedisplay.size_bytes);
- adev->psp.securedisplay_context.context.bin_desc.start_addr =
- (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
- le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
-
- adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
- }
-
- return 0;
-
-out2:
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
-out:
- if (err) {
- dev_err(adev->dev,
- "psp v10.0: Failed to load firmware \"%s\"\n",
- fw_name);
- }
+ return err;

- return err;
+ return psp_init_ta_microcode(psp, ucode_prefix);
}

static int psp_v10_0_ring_create(struct psp_context *psp,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index bd3e3e23a939..41e29b777666 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -89,9 +89,8 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
const char *chip_name;
- char fw_name[PSP_FW_NAME_LEN];
+ char ucode_prefix[30];
int err = 0;
- const struct ta_firmware_header_v1_0 *ta_hdr;

DRM_DEBUG("\n");

@@ -129,7 +128,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
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):
@@ -140,35 +139,8 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
err = psp_init_asd_microcode(psp, chip_name);
if (err)
return err;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
- err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
- if (err) {
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
- dev_info(adev->dev,
- "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
- } else {
- err = amdgpu_ucode_validate(adev->psp.ta_fw);
- if (err)
- goto out2;
-
- ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
- adev->psp.xgmi_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->xgmi.fw_version);
- adev->psp.xgmi_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->xgmi.size_bytes);
- adev->psp.xgmi_context.context.bin_desc.start_addr =
- (uint8_t *)ta_hdr +
- le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
- adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
- adev->psp.ras_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->ras.fw_version);
- adev->psp.ras_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->ras.size_bytes);
- adev->psp.ras_context.context.bin_desc.start_addr =
- (uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr +
- le32_to_cpu(ta_hdr->ras.offset_bytes);
- }
+ err = psp_init_ta_microcode(psp, ucode_prefix);
+ adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
break;
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 5):
@@ -179,39 +151,8 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
err = psp_init_asd_microcode(psp, chip_name);
if (err)
return err;
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
- err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
- if (err) {
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
- dev_info(adev->dev,
- "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
- } else {
- err = amdgpu_ucode_validate(adev->psp.ta_fw);
- if (err)
- goto out2;
-
- ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
- adev->psp.hdcp_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->hdcp.fw_version);
- adev->psp.hdcp_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->hdcp.size_bytes);
- adev->psp.hdcp_context.context.bin_desc.start_addr =
- (uint8_t *)ta_hdr +
- le32_to_cpu(
- ta_hdr->header.ucode_array_offset_bytes);
-
- adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
-
- adev->psp.dtm_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->dtm.fw_version);
- adev->psp.dtm_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->dtm.size_bytes);
- adev->psp.dtm_context.context.bin_desc.start_addr =
- (uint8_t *)adev->psp.hdcp_context.context
- .bin_desc.start_addr +
- le32_to_cpu(ta_hdr->dtm.offset_bytes);
- }
+ err = psp_init_ta_microcode(psp, ucode_prefix);
+ adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
break;
case IP_VERSION(11, 0, 7):
case IP_VERSION(11, 0, 11):
@@ -221,26 +162,17 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
if (err)
return err;
err = psp_init_ta_microcode(psp, chip_name);
- if (err)
- return err;
break;
case IP_VERSION(11, 5, 0):
err = psp_init_asd_microcode(psp, chip_name);
if (err)
return err;
err = psp_init_toc_microcode(psp, chip_name);
- if (err)
- return err;
break;
default:
BUG();
}

- return 0;
-
-out2:
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
return err;
}

diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
index 8ed2281b6557..67118e699219 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
@@ -49,9 +49,8 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
const char *chip_name;
- char fw_name[30];
+ char ucode_prefix[30];
int err = 0;
- const struct ta_firmware_header_v1_0 *ta_hdr;
DRM_DEBUG("\n");

switch (adev->asic_type) {
@@ -64,67 +63,20 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
default:
BUG();
}
+ amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));

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

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
- err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
- if (err) {
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
- dev_info(adev->dev,
- "psp v12.0: Failed to load firmware \"%s\"\n",
- fw_name);
- } else {
- err = amdgpu_ucode_validate(adev->psp.ta_fw);
- if (err)
- goto out;
-
- ta_hdr = (const struct ta_firmware_header_v1_0 *)
- adev->psp.ta_fw->data;
- adev->psp.hdcp_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->hdcp.fw_version);
- adev->psp.hdcp_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->hdcp.size_bytes);
- adev->psp.hdcp_context.context.bin_desc.start_addr =
- (uint8_t *)ta_hdr +
- le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
-
- adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
-
- adev->psp.dtm_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->dtm.fw_version);
- adev->psp.dtm_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->dtm.size_bytes);
- adev->psp.dtm_context.context.bin_desc.start_addr =
- (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
- le32_to_cpu(ta_hdr->dtm.offset_bytes);
-
- if (adev->apu_flags & AMD_APU_IS_RENOIR) {
- adev->psp.securedisplay_context.context.bin_desc.fw_version =
- le32_to_cpu(ta_hdr->securedisplay.fw_version);
- adev->psp.securedisplay_context.context.bin_desc.size_bytes =
- le32_to_cpu(ta_hdr->securedisplay.size_bytes);
- adev->psp.securedisplay_context.context.bin_desc.start_addr =
- (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
- le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
- }
- }
-
- return 0;
-
-out:
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
- if (err) {
- dev_err(adev->dev,
- "psp v12.0: Failed to load firmware \"%s\"\n",
- fw_name);
- }
+ /* only supported on renoir */
+ if (!(adev->apu_flags & AMD_APU_IS_RENOIR))
+ adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;

- return err;
+ return psp_init_ta_microcode(psp, ucode_prefix);
}

static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)
--
2.34.1

2023-01-05 18:04:24

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 44/45] drm/amd: Use `amdgpu_ucode_release` helper for si

The `amdgpu_ucode_release` helper is replacing all calls
to release_firmware.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
index 49c398ec0aaf..d6d9e3b1b2c0 100644
--- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
+++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c
@@ -7714,20 +7714,13 @@ static int si_dpm_init_microcode(struct amdgpu_device *adev)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
- err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->pm.fw);
-
-out:
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
if (err) {
DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s\"\n",
err, fw_name);
- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
+ amdgpu_ucode_release(&adev->pm.fw);
}
return err;
-
}

static int si_dpm_sw_init(void *handle)
--
2.34.1

2023-01-05 18:04:26

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 21/45] drm/amd: Avoid BUG() for case of SRIOV missing IP version

No need to crash the kernel. AMDGPU will now fail to probe.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index bdc2bf87a286..8b2f1783f93b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -380,7 +380,7 @@ static int psp_init_sriov_microcode(struct psp_context *psp)
adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA;
break;
default:
- BUG();
+ ret = -EINVAL;
break;
}
return ret;
--
2.34.1

2023-01-05 18:04:27

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 26/45] drm/amd: Use `amdgpu_ucode_*` helpers for SMU

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 16 ++++------------
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 16 ++++------------
2 files changed, 8 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index d4756bd30830..6492d69e2e60 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -109,10 +109,7 @@ int smu_v11_0_init_microcode(struct smu_context *smu)

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);

- err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->pm.fw);
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
if (err)
goto out;

@@ -130,12 +127,8 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
}

out:
- if (err) {
- DRM_ERROR("smu_v11_0: Failed to load firmware \"%s\"\n",
- fw_name);
- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
- }
+ if (err)
+ amdgpu_ucode_release(&adev->pm.fw);
return err;
}

@@ -143,8 +136,7 @@ void smu_v11_0_fini_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;

- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
+ amdgpu_ucode_release(&adev->pm.fw);
adev->pm.fw_version = 0;
}

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index 506a49a4b425..59d00fefc558 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -103,10 +103,7 @@ int smu_v13_0_init_microcode(struct smu_context *smu)

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);

- err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->pm.fw);
+ err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
if (err)
goto out;

@@ -124,12 +121,8 @@ int smu_v13_0_init_microcode(struct smu_context *smu)
}

out:
- if (err) {
- DRM_ERROR("smu_v13_0: Failed to load firmware \"%s\"\n",
- fw_name);
- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
- }
+ if (err)
+ amdgpu_ucode_release(&adev->pm.fw);
return err;
}

@@ -137,8 +130,7 @@ void smu_v13_0_fini_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;

- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
+ amdgpu_ucode_release(&adev->pm.fw);
adev->pm.fw_version = 0;
}

--
2.34.1

2023-01-05 18:04:27

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 36/45] drm/amd: Use `amdgpu_ucode_*` helpers for SDMA3.0

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 486d9b5c1b9e..e572389089d2 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -250,10 +250,9 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
static void sdma_v3_0_free_microcode(struct amdgpu_device *adev)
{
int i;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- release_firmware(adev->sdma.instance[i].fw);
- adev->sdma.instance[i].fw = NULL;
- }
+
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}

/**
@@ -309,10 +308,7 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma.bin", chip_name);
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sdma1.bin", chip_name);
- err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
+ err = amdgpu_ucode_request(adev, &adev->sdma.instance[i].fw, fw_name);
if (err)
goto out;
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
@@ -332,10 +328,8 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
out:
if (err) {
pr_err("sdma_v3_0: Failed to load firmware \"%s\"\n", fw_name);
- for (i = 0; i < adev->sdma.num_instances; i++) {
- release_firmware(adev->sdma.instance[i].fw);
- adev->sdma.instance[i].fw = NULL;
- }
+ for (i = 0; i < adev->sdma.num_instances; i++)
+ amdgpu_ucode_release(&adev->sdma.instance[i].fw);
}
return err;
}
--
2.34.1

2023-01-05 18:04:37

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 22/45] 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: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v6->v7:
* rebase on earlier patches
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 120 +++++++++--------------
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 12 ---
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 51 ++--------
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 13 +--
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 27 ++---
drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c | 14 +--
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 16 +--
7 files changed, 69 insertions(+), 184 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 8b2f1783f93b..73d67a4d0f5b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -122,6 +122,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;
@@ -192,7 +230,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)
@@ -350,42 +391,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;
@@ -401,15 +406,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);
@@ -2908,19 +2904,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)
@@ -2944,19 +2934,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)
@@ -3107,8 +3091,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];
@@ -3121,11 +3104,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)
@@ -3392,8 +3370,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];
@@ -3401,11 +3378,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;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index f14fcfb9c425..e1b7fca09666 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -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);
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index 41e29b777666..8f84fe40abbb 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -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();
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
index 67118e699219..8979e4b697cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
@@ -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;
err = psp_init_ta_microcode(psp, ucode_prefix);
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index e6a26a7e5e5e..d62fcc77af95 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -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;
- }
+ amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));

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;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
index 9d4e24e518e8..d5ba58eba3e2 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
@@ -35,25 +35,17 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_4_ta.bin");
static int psp_v13_0_4_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, 4):
- amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
- chip_name = ucode_prefix;
- 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(13, 0, 4):
- 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;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
index 157147c6c94e..f6b75e3e47ff 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
@@ -57,26 +57,18 @@ static int psp_v3_1_ring_stop(struct psp_context *psp,
static int psp_v3_1_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_VEGA10:
- chip_name = "vega10";
- break;
- case CHIP_VEGA12:
- chip_name = "vega12";
- break;
- default: BUG();
- }
+ amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));

- 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;

--
2.34.1

2023-01-05 18:04:51

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 32/45] drm/amd: Use `amdgpu_ucode_*` helpers for GMC6

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index ec291d28edff..d154ab48f507 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -131,19 +131,12 @@ static int gmc_v6_0_init_microcode(struct amdgpu_device *adev)
snprintf(fw_name, sizeof(fw_name), "amdgpu/si58_mc.bin");
else
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mc.bin", chip_name);
- err = request_firmware(&adev->gmc.fw, fw_name, adev->dev);
- if (err)
- goto out;
-
- err = amdgpu_ucode_validate(adev->gmc.fw);
-
-out:
+ err = amdgpu_ucode_request(adev, &adev->gmc.fw, fw_name);
if (err) {
dev_err(adev->dev,
"si_mc: Failed to load firmware \"%s\"\n",
fw_name);
- release_firmware(adev->gmc.fw);
- adev->gmc.fw = NULL;
+ amdgpu_ucode_release(&adev->gmc.fw);
}
return err;
}
@@ -894,8 +887,7 @@ static int gmc_v6_0_sw_fini(void *handle)
amdgpu_vm_manager_fini(adev);
amdgpu_gart_table_vram_free(adev);
amdgpu_bo_fini(adev);
- release_firmware(adev->gmc.fw);
- adev->gmc.fw = NULL;
+ amdgpu_ucode_release(&adev->gmc.fw);

return 0;
}
--
2.34.1

2023-01-05 18:05:07

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 03/45] drm/amd: Convert SMUv11 microcode to use `amdgpu_ucode_ip_version_decode`

Remove the special casing from SMU v11 code. No intended functional
changes.

Signed-off-by: Mario Limonciello <[email protected]>
Acked-by: Christian König <[email protected]>
Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
.../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 35 ++-----------------
1 file changed, 3 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index ad66d57aa102..d4756bd30830 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -93,7 +93,7 @@ static void smu_v11_0_poll_baco_exit(struct smu_context *smu)
int smu_v11_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- const char *chip_name;
+ char ucode_prefix[30];
char fw_name[SMU_FW_NAME_LEN];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
@@ -105,38 +105,9 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
(adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7))))
return 0;

- switch (adev->ip_versions[MP1_HWIP][0]) {
- 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, 7):
- chip_name = "sienna_cichlid";
- break;
- case IP_VERSION(11, 0, 11):
- chip_name = "navy_flounder";
- break;
- case IP_VERSION(11, 0, 12):
- chip_name = "dimgrey_cavefish";
- break;
- case IP_VERSION(11, 0, 13):
- chip_name = "beige_goby";
- break;
- case IP_VERSION(11, 0, 2):
- chip_name = "arcturus";
- break;
- default:
- dev_err(adev->dev, "Unsupported IP version 0x%x\n",
- adev->ip_versions[MP1_HWIP][0]);
- return -EINVAL;
- }
+ amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", ucode_prefix);

err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
if (err)
--
2.34.1

2023-01-05 18:05:42

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 38/45] drm/amd: Use `amdgpu_ucode_*` helpers for UVD

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 6eac649499d3..482fcf71d1c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -260,19 +260,11 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
return -EINVAL;
}

- r = request_firmware(&adev->uvd.fw, fw_name, adev->dev);
- if (r) {
- dev_err(adev->dev, "amdgpu_uvd: Can't load firmware \"%s\"\n",
- fw_name);
- return r;
- }
-
- r = amdgpu_ucode_validate(adev->uvd.fw);
+ r = amdgpu_ucode_request(adev, &adev->uvd.fw, fw_name);
if (r) {
dev_err(adev->dev, "amdgpu_uvd: Can't validate firmware \"%s\"\n",
fw_name);
- release_firmware(adev->uvd.fw);
- adev->uvd.fw = NULL;
+ amdgpu_ucode_release(&adev->uvd.fw);
return r;
}

@@ -394,7 +386,7 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]);
}
amdgpu_bo_free_kernel(&adev->uvd.ib_bo, NULL, &addr);
- release_firmware(adev->uvd.fw);
+ amdgpu_ucode_release(&adev->uvd.fw);

return 0;
}
--
2.34.1

2023-01-05 18:06:01

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 41/45] drm/amd: Use `amdgpu_ucode_*` helpers for GPU info bin

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index cdb681398a99..406d53ac3096 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1983,17 +1983,10 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
- err = request_firmware(&adev->firmware.gpu_info_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_request(adev, &adev->firmware.gpu_info_fw, fw_name);
if (err) {
dev_err(adev->dev,
- "Failed to load gpu_info firmware \"%s\"\n",
- fw_name);
- goto out;
- }
- err = amdgpu_ucode_validate(adev->firmware.gpu_info_fw);
- if (err) {
- dev_err(adev->dev,
- "Failed to validate gpu_info firmware \"%s\"\n",
+ "Failed to get gpu_info firmware \"%s\"\n",
fw_name);
goto out;
}
@@ -4030,8 +4023,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)

amdgpu_fence_driver_sw_fini(adev);
amdgpu_device_ip_fini(adev);
- release_firmware(adev->firmware.gpu_info_fw);
- adev->firmware.gpu_info_fw = NULL;
+ amdgpu_ucode_release(&adev->firmware.gpu_info_fw);
adev->accel_working = false;
dma_fence_put(rcu_dereference_protected(adev->gang_submit, true));

--
2.34.1

2023-01-05 18:06:21

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v7 23/45] drm/amd: Use `amdgpu_ucode_*` helpers for PSP

The `amdgpu_ucode_request` helper will ensure that the return code for
missing firmware is -ENODEV so that early_init can fail.

The `amdgpu_ucode_release` helper is for symmetry on unloading.

Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
---
v5->v6:
* Adjust for amdgpu_ucode_release argument change
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 80 +++++++------------------
1 file changed, 21 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 73d67a4d0f5b..aae76acc38e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -510,20 +510,11 @@ static int psp_sw_fini(void *handle)

psp_memory_training_fini(psp);

- release_firmware(psp->sos_fw);
- psp->sos_fw = NULL;
-
- release_firmware(psp->asd_fw);
- psp->asd_fw = NULL;
-
- release_firmware(psp->ta_fw);
- psp->ta_fw = NULL;
-
- release_firmware(psp->cap_fw);
- psp->cap_fw = NULL;
-
- release_firmware(psp->toc_fw);
- psp->toc_fw = NULL;
+ amdgpu_ucode_release(&psp->sos_fw);
+ amdgpu_ucode_release(&psp->asd_fw);
+ amdgpu_ucode_release(&psp->ta_fw);
+ amdgpu_ucode_release(&psp->cap_fw);
+ amdgpu_ucode_release(&psp->toc_fw);

if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7))
@@ -2912,11 +2903,7 @@ int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
int err = 0;

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)
- goto out;
-
- err = amdgpu_ucode_validate(adev->psp.asd_fw);
+ err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, fw_name);
if (err)
goto out;

@@ -2928,9 +2915,7 @@ int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes);
return 0;
out:
- dev_err(adev->dev, "fail to initialize asd microcode\n");
- release_firmware(adev->psp.asd_fw);
- adev->psp.asd_fw = NULL;
+ amdgpu_ucode_release(&adev->psp.asd_fw);
return err;
}

@@ -2942,11 +2927,7 @@ int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name)
int err = 0;

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)
- goto out;
-
- err = amdgpu_ucode_validate(adev->psp.toc_fw);
+ err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
if (err)
goto out;

@@ -2958,9 +2939,7 @@ int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name)
le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes);
return 0;
out:
- dev_err(adev->dev, "fail to request/validate toc microcode\n");
- release_firmware(adev->psp.toc_fw);
- adev->psp.toc_fw = NULL;
+ amdgpu_ucode_release(&adev->psp.toc_fw);
return err;
}

@@ -3105,11 +3084,7 @@ int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
int fw_index = 0;

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)
- goto out;
-
- err = amdgpu_ucode_validate(adev->psp.sos_fw);
+ err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, fw_name);
if (err)
goto out;

@@ -3181,10 +3156,7 @@ int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)

return 0;
out:
- dev_err(adev->dev,
- "failed to init sos firmware\n");
- release_firmware(adev->psp.sos_fw);
- adev->psp.sos_fw = NULL;
+ amdgpu_ucode_release(&adev->psp.sos_fw);

return err;
}
@@ -3341,10 +3313,7 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
int err;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
- err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
- if (err)
- return err;
- err = amdgpu_ucode_validate(adev->psp.ta_fw);
+ err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, fw_name);
if (err)
return err;

@@ -3361,11 +3330,8 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
err = -EINVAL;
}

- if (err) {
- dev_err(adev->dev, "fail to initialize ta microcode\n");
- release_firmware(adev->psp.ta_fw);
- adev->psp.ta_fw = NULL;
- }
+ if (err)
+ amdgpu_ucode_release(&adev->psp.ta_fw);

return err;
}
@@ -3384,17 +3350,14 @@ int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name);
- err = request_firmware(&adev->psp.cap_fw, fw_name, adev->dev);
- if (err) {
- dev_warn(adev->dev, "cap microcode does not exist, skip\n");
- err = 0;
- goto out;
- }
-
- err = amdgpu_ucode_validate(adev->psp.cap_fw);
+ err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, fw_name);
if (err) {
+ if (err == -ENODEV) {
+ dev_warn(adev->dev, "cap microcode does not exist, skip\n");
+ err = 0;
+ goto out;
+ }
dev_err(adev->dev, "fail to initialize cap microcode\n");
- goto out;
}

info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP];
@@ -3411,8 +3374,7 @@ int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
return 0;

out:
- release_firmware(adev->psp.cap_fw);
- adev->psp.cap_fw = NULL;
+ amdgpu_ucode_release(&adev->psp.cap_fw);
return err;
}

--
2.34.1

2023-01-05 18:19:16

by Alex Deucher

[permalink] [raw]
Subject: Re: [PATCH v7 00/45] Recover from failure to probe GPU

On Thu, Jan 5, 2023 at 12:02 PM Mario Limonciello
<[email protected]> wrote:
>
> One of the first thing that KMS drivers do during initialization is
> destroy the system firmware framebuffer by means of
> `drm_aperture_remove_conflicting_pci_framebuffers`
>
> This means that if for any reason the GPU failed to probe the user
> will be stuck with at best a screen frozen at the last thing that
> was shown before the KMS driver continued it's probe.
>
> The problem is most pronounced when new GPU support is introduced
> because users will need to have a recent linux-firmware snapshot
> on their system when they boot a kernel with matching support.
>
> However the problem is further exaggerated in the case of amdgpu because
> it has migrated to "IP discovery" where amdgpu will attempt to load
> on "ALL" AMD GPUs even if the driver is missing support for IP blocks
> contained in that GPU.
>
> IP discovery requires some probing and isn't run until after the
> framebuffer has been destroyed.
>
> This means a situation can occur where a user purchases a new GPU not
> yet supported by a distribution and when booting the installer it will
> "freeze" even if the distribution doesn't have the matching kernel support
> for those IP blocks.
>
> The perfect example of this is Ubuntu 22.10 and the new dGPUs just
> launched by AMD. The installation media ships with kernel 5.19 (which
> has IP discovery) but the amdgpu support for those IP blocks landed in
> kernel 6.0. The matching linux-firmware was released after 22.10's launch.
> The screen will freeze without nomodeset. Even if a user manages to install
> and then upgrades to kernel 6.0 after install they'll still have the
> problem of missing firmware, and the same experience.
>
> This is quite jarring for users, particularly if they don't know
> that they have to use "nomodeset" to install.
>
> To help the situation make changes to GPU discovery:
> 1) Delay releasing the firmware framebuffer until after early_init
> completed. This will help the situation of an older kernel that doesn't
> yet support the IP blocks probing a new GPU. IP discovery will have failed.
> 2) Request loading all PSP, VCN, SDMA, SMU, DMCUB, MES and GC microcode
> into memory during early_init. This will help the situation of new enough
> kernel for the IP discovery phase to otherwise pass but missing microcode
> from linux-firmware.git.

Series is:
Reviewed-by: Alex Deucher <[email protected]>

>
> v6->v7:
> * Pick up tags
> * Fix PSP TAv1 handling to match previous behavior (securedisplay_context
> only is set on PSPv10 and PSPv12/Renoir)
> v5->v6:
> * Fix arguments for amdgpu_ucode_release to allow clearing pointer
> * Fix whitespace mistake in VCN
> * Pick up tags
> v4->v5:
> * Rename amdgpu_ucode_load to amdgpu_ucode_request
> * Add and utilize amdgpu_ucode_release throughout existing patches
> * Update all amdgpu code to stop using request_firmware and
> release_firmware for microcode
> * Drop export of amdgpu_ucode_validate outside of amdgpu_ucode.c
> * Pick up relevant tags for some patches
> v3->v4:
> * Rework to delay framebuffer release until early_init is done
> * Make IP load microcode during early init phase
> * Add SMU and DMCUB checks for early_init loading
> * Add some new helper code for wrapping request_firmware calls (needed for
> early_init to return something besides -ENOENT)
> v2->v3:
> * Pick up tags for patches 1-10
> * Rework patch 11 to not validate during discovery
> * Fix bugs with GFX9 due to gfx.num_gfx_rings not being set during
> discovery
> * Fix naming scheme for SDMA on dGPUs
> v1->v2:
> * Take the suggestion from v1 thread to delay the framebuffer release
> until ip discovery is done. This patch is CC to stable to that older
> stable kernels with IP discovery won't try to probe unknown IP.
> * Drop changes to drm aperature.
> * Fetch SDMA, VCN, MES, GC and PSP microcode during IP discovery.
>
> Mario Limonciello (27):
> drm/amd: Delay removal of the firmware framebuffer
> drm/amd: Add a legacy mapping to "amdgpu_ucode_ip_version_decode"
> drm/amd: Convert SMUv11 microcode to use
> `amdgpu_ucode_ip_version_decode`
> drm/amd: Convert SMUv13 microcode to use
> `amdgpu_ucode_ip_version_decode`
> drm/amd: Add a new helper for loading/validating microcode
> drm/amd: Use `amdgpu_ucode_request` helper for SDMA
> drm/amd: Convert SDMA to use `amdgpu_ucode_ip_version_decode`
> drm/amd: Make SDMA firmware load failures less noisy.
> drm/amd: Use `amdgpu_ucode_*` helpers for VCN
> drm/amd: Load VCN microcode during early_init
> drm/amd: Load MES microcode during early_init
> drm/amd: Use `amdgpu_ucode_*` helpers for MES
> drm/amd: Remove superfluous assignment for `adev->mes.adev`
> drm/amd: Use `amdgpu_ucode_*` helpers for GFX9
> drm/amd: Load GFX9 microcode during early_init
> drm/amd: Use `amdgpu_ucode_*` helpers for GFX10
> drm/amd: Load GFX10 microcode during early_init
> drm/amd: Use `amdgpu_ucode_*` helpers for GFX11
> drm/amd: Load GFX11 microcode during early_init
> drm/amd: Parse both v1 and v2 TA microcode headers using same function
> drm/amd: Avoid BUG() for case of SRIOV missing IP version
> drm/amd: Load PSP microcode during early_init
> drm/amd: Use `amdgpu_ucode_*` helpers for PSP
> drm/amd/display: Load DMUB microcode during early_init
> drm/amd: Use `amdgpu_ucode_release` helper for DMUB
> drm/amd: Use `amdgpu_ucode_*` helpers for SMU
> drm/amd: Load SMU microcode during early_init
> drm/amd: Optimize SRIOV switch/case for PSP microcode load
> drm/amd: Use `amdgpu_ucode_*` helpers for GFX6
> drm/amd: Use `amdgpu_ucode_*` helpers for GFX7
> drm/amd: Use `amdgpu_ucode_*` helpers for GFX8
> drm/amd: Use `amdgpu_ucode_*` helpers for GMC6
> drm/amd: Use `amdgpu_ucode_*` helpers for GMC7
> drm/amd: Use `amdgpu_ucode_*` helpers for GMC8
> drm/amd: Use `amdgpu_ucode_*` helpers for SDMA2.4
> drm/amd: Use `amdgpu_ucode_*` helpers for SDMA3.0
> drm/amd: Use `amdgpu_ucode_*` helpers for SDMA on CIK
> drm/amd: Use `amdgpu_ucode_*` helpers for UVD
> drm/amd: Use `amdgpu_ucode_*` helpers for VCE
> drm/amd: Use `amdgpu_ucode_*` helpers for CGS
> drm/amd: Use `amdgpu_ucode_*` helpers for GPU info bin
> drm/amd: Use `amdgpu_ucode_*` helpers for DMCU
> drm/amd: Use `amdgpu_ucode_release` helper for powerplay
> drm/amd: Use `amdgpu_ucode_release` helper for si
> drm/amd: make amdgpu_ucode_validate static
>
> drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 11 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 22 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 6 -
> drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 59 ++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 299 +++++++++---------
> drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 25 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 4 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 259 ++++++++++++++-
> drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 4 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 14 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 14 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 65 +---
> drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 1 +
> drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 16 +-
> drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 155 +++------
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 124 +++-----
> drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 30 +-
> drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 68 +---
> drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 94 ++----
> drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 140 ++------
> drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 14 +-
> drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 13 +-
> drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 13 +-
> drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 7 +-
> drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 108 ++-----
> drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 99 ++----
> drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 80 +----
> drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 131 +-------
> drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 79 +----
> drivers/gpu/drm/amd/amdgpu/psp_v13_0.c | 27 +-
> drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c | 14 +-
> drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 16 +-
> drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 18 +-
> drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 18 +-
> drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 47 +--
> drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 30 +-
> drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 55 +---
> drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 25 +-
> drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 5 +-
> drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 5 +-
> drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 5 +-
> drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 5 +-
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 5 +-
> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 110 ++++---
> drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 11 +-
> .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 3 +-
> drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 +-
> .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 51 +--
> .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 28 +-
> 50 files changed, 900 insertions(+), 1545 deletions(-)
>
> --
> 2.34.1
>

2023-01-06 03:43:55

by Lazar, Lijo

[permalink] [raw]
Subject: Re: [PATCH v7 20/45] drm/amd: Parse both v1 and v2 TA microcode headers using same function



On 1/5/2023 10:31 PM, Mario Limonciello wrote:
> Several IP versions duplicate code and can't use the common helpers.
> Move this code into a single function so that the helpers can be used.
>
> Signed-off-by: Mario Limonciello <[email protected]>
> ---
> v6->v7:
> * Drop tags
> * Only set adev->psp.securedisplay_context.context on PSPv12 Renoir and
> PSP v10 which matches previous behavior. If it should match for Cezanne
> and PSPv11 too we can undo this part of the check.
> v5->v6:
> * Rebase on earlier patches
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 123 ++++++++++++++++++------
> drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 64 +-----------
> drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 80 ++-------------
> drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 66 ++-----------
> 4 files changed, 115 insertions(+), 218 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
> index 7a2fc920739b..bdc2bf87a286 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
> @@ -3272,41 +3272,76 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
> return 0;
> }
>
> -int psp_init_ta_microcode(struct psp_context *psp,
> - const char *chip_name)
> +static int parse_ta_v1_microcode(struct psp_context *psp)
> {
> + const struct ta_firmware_header_v1_0 *ta_hdr;
> struct amdgpu_device *adev = psp->adev;
> - char fw_name[PSP_FW_NAME_LEN];
> - const struct ta_firmware_header_v2_0 *ta_hdr;
> - int err = 0;
> - int ta_index = 0;
>
> - if (!chip_name) {
> - dev_err(adev->dev, "invalid chip name for ta microcode\n");
> + ta_hdr = (const struct ta_firmware_header_v1_0 *) adev->psp.ta_fw->data;
> +
> + if (le16_to_cpu(ta_hdr->header.header_version_major) != 1)
> return -EINVAL;
> - }
>
> - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
> - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> - if (err)
> - goto out;
> + adev->psp.xgmi_context.context.bin_desc.fw_version =
> + le32_to_cpu(ta_hdr->xgmi.fw_version);
> + adev->psp.xgmi_context.context.bin_desc.size_bytes =
> + le32_to_cpu(ta_hdr->xgmi.size_bytes);
> + adev->psp.xgmi_context.context.bin_desc.start_addr =
> + (uint8_t *)ta_hdr +
> + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
> +
> + adev->psp.ras_context.context.bin_desc.fw_version =
> + le32_to_cpu(ta_hdr->ras.fw_version);
> + adev->psp.ras_context.context.bin_desc.size_bytes =
> + le32_to_cpu(ta_hdr->ras.size_bytes);
> + adev->psp.ras_context.context.bin_desc.start_addr =
> + (uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr +
> + le32_to_cpu(ta_hdr->ras.offset_bytes);
> +
> + adev->psp.hdcp_context.context.bin_desc.fw_version =
> + le32_to_cpu(ta_hdr->hdcp.fw_version);
> + adev->psp.hdcp_context.context.bin_desc.size_bytes =
> + le32_to_cpu(ta_hdr->hdcp.size_bytes);
> + adev->psp.hdcp_context.context.bin_desc.start_addr =
> + (uint8_t *)ta_hdr +
> + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
> +
> + adev->psp.dtm_context.context.bin_desc.fw_version =
> + le32_to_cpu(ta_hdr->dtm.fw_version);
> + adev->psp.dtm_context.context.bin_desc.size_bytes =
> + le32_to_cpu(ta_hdr->dtm.size_bytes);
> + adev->psp.dtm_context.context.bin_desc.start_addr =
> + (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
> + le32_to_cpu(ta_hdr->dtm.offset_bytes);
> +
> + adev->psp.securedisplay_context.context.bin_desc.fw_version =
> + le32_to_cpu(ta_hdr->securedisplay.fw_version);
> + adev->psp.securedisplay_context.context.bin_desc.size_bytes =
> + le32_to_cpu(ta_hdr->securedisplay.size_bytes);
> + adev->psp.securedisplay_context.context.bin_desc.start_addr =
> + (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
> + le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
> +
> + adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
>
> - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> - if (err)
> - goto out;
> + return 0;
> +}
> +
> +static int parse_ta_v2_microcode(struct psp_context *psp)
> +{
> + const struct ta_firmware_header_v2_0 *ta_hdr;
> + struct amdgpu_device *adev = psp->adev;
> + int err = 0;
> + int ta_index = 0;
>
> ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data;
>
> - if (le16_to_cpu(ta_hdr->header.header_version_major) != 2) {
> - dev_err(adev->dev, "unsupported TA header version\n");
> - err = -EINVAL;
> - goto out;
> - }
> + if (le16_to_cpu(ta_hdr->header.header_version_major) != 2)
> + return -EINVAL;
>
> if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
> dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
> - err = -EINVAL;
> - goto out;
> + return -EINVAL;
> }
>
> for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) {
> @@ -3314,14 +3349,46 @@ int psp_init_ta_microcode(struct psp_context *psp,
> &ta_hdr->ta_fw_bin[ta_index],
> ta_hdr);
> if (err)
> - goto out;
> + return err;
> }
>
> return 0;
> -out:
> - dev_err(adev->dev, "fail to initialize ta microcode\n");
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> +}
> +
> +int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
> +{
> + const struct common_firmware_header *hdr;
> + struct amdgpu_device *adev = psp->adev;
> + char fw_name[PSP_FW_NAME_LEN];
> + int err;
> +
> + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
> + err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> + if (err)
> + return err;
> + err = amdgpu_ucode_validate(adev->psp.ta_fw);
> + if (err)
> + return err;
> +
> + hdr = (const struct common_firmware_header *)adev->psp.ta_fw->data;
> + switch (le16_to_cpu(hdr->header_version_major)) {
> + case 1:
> + err = parse_ta_v1_microcode(psp);
> + break;
> + case 2:
> + err = parse_ta_v2_microcode(psp);
> + break;
> + default:
> + dev_err(adev->dev, "unsupported TA header version\n");
> + err = -EINVAL;
> + }
> +
> + if (err) {
> + dev_err(adev->dev, "fail to initialize ta microcode\n");
> + release_firmware(adev->psp.ta_fw);
> + adev->psp.ta_fw = NULL;
> + }
> +
> return err;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> index 9de46fa8f46c..f14fcfb9c425 100644
> --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> @@ -48,9 +48,8 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
> {
> struct amdgpu_device *adev = psp->adev;
> const char *chip_name;
> - char fw_name[30];
> + char ucode_prefix[30];
> int err = 0;
> - const struct ta_firmware_header_v1_0 *ta_hdr;
> DRM_DEBUG("\n");
>
> switch (adev->asic_type) {
> @@ -64,66 +63,13 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
> 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)
> - goto out;
> -
> - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
> - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> - if (err) {
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> - dev_info(adev->dev,
> - "psp v10.0: Failed to load firmware \"%s\"\n",
> - fw_name);
> - } else {
> - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> - if (err)
> - goto out2;
> -
> - ta_hdr = (const struct ta_firmware_header_v1_0 *)
> - adev->psp.ta_fw->data;
> - adev->psp.hdcp_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->hdcp.fw_version);
> - adev->psp.hdcp_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->hdcp.size_bytes);
> - adev->psp.hdcp_context.context.bin_desc.start_addr =
> - (uint8_t *)ta_hdr +
> - le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
> -
> - adev->psp.dtm_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->dtm.fw_version);
> - adev->psp.dtm_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->dtm.size_bytes);
> - adev->psp.dtm_context.context.bin_desc.start_addr =
> - (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
> - le32_to_cpu(ta_hdr->dtm.offset_bytes);
> -
> - adev->psp.securedisplay_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->securedisplay.fw_version);
> - adev->psp.securedisplay_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->securedisplay.size_bytes);
> - adev->psp.securedisplay_context.context.bin_desc.start_addr =
> - (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
> - le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
> -
> - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
> - }
> -
> - return 0;
> -
> -out2:
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> -out:
> - if (err) {
> - dev_err(adev->dev,
> - "psp v10.0: Failed to load firmware \"%s\"\n",
> - fw_name);
> - }
> + return err;
>
> - return err;
> + return psp_init_ta_microcode(psp, ucode_prefix);
> }
>
> static int psp_v10_0_ring_create(struct psp_context *psp,
> diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
> index bd3e3e23a939..41e29b777666 100644
> --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
> @@ -89,9 +89,8 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
> {
> struct amdgpu_device *adev = psp->adev;
> const char *chip_name;
> - char fw_name[PSP_FW_NAME_LEN];
> + char ucode_prefix[30];
> int err = 0;
> - const struct ta_firmware_header_v1_0 *ta_hdr;
>
> DRM_DEBUG("\n");
>
> @@ -129,7 +128,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
> 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):
> @@ -140,35 +139,8 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
> err = psp_init_asd_microcode(psp, chip_name);
> if (err)
> return err;
> - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
> - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> - if (err) {
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> - dev_info(adev->dev,
> - "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
> - } else {
> - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> - if (err)
> - goto out2;
> -
> - ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
> - adev->psp.xgmi_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->xgmi.fw_version);
> - adev->psp.xgmi_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->xgmi.size_bytes);
> - adev->psp.xgmi_context.context.bin_desc.start_addr =
> - (uint8_t *)ta_hdr +
> - le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
> - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
> - adev->psp.ras_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->ras.fw_version);
> - adev->psp.ras_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->ras.size_bytes);
> - adev->psp.ras_context.context.bin_desc.start_addr =
> - (uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr +
> - le32_to_cpu(ta_hdr->ras.offset_bytes);
> - }
> + err = psp_init_ta_microcode(psp, ucode_prefix);
> + adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
> break;
> case IP_VERSION(11, 0, 0):
> case IP_VERSION(11, 0, 5):
> @@ -179,39 +151,8 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
> err = psp_init_asd_microcode(psp, chip_name);
> if (err)
> return err;
> - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
> - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> - if (err) {
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> - dev_info(adev->dev,
> - "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
> - } else {
> - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> - if (err)
> - goto out2;
> -
> - ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
> - adev->psp.hdcp_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->hdcp.fw_version);
> - adev->psp.hdcp_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->hdcp.size_bytes);
> - adev->psp.hdcp_context.context.bin_desc.start_addr =
> - (uint8_t *)ta_hdr +
> - le32_to_cpu(
> - ta_hdr->header.ucode_array_offset_bytes);
> -
> - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
> -
> - adev->psp.dtm_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->dtm.fw_version);
> - adev->psp.dtm_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->dtm.size_bytes);
> - adev->psp.dtm_context.context.bin_desc.start_addr =
> - (uint8_t *)adev->psp.hdcp_context.context
> - .bin_desc.start_addr +
> - le32_to_cpu(ta_hdr->dtm.offset_bytes);
> - }
> + err = psp_init_ta_microcode(psp, ucode_prefix);
> + adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
> break;
> case IP_VERSION(11, 0, 7):
> case IP_VERSION(11, 0, 11):
> @@ -221,26 +162,17 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
> if (err)
> return err;
> err = psp_init_ta_microcode(psp, chip_name);
> - if (err)
> - return err;
> break;
> case IP_VERSION(11, 5, 0):
> err = psp_init_asd_microcode(psp, chip_name);
> if (err)
> return err;
> err = psp_init_toc_microcode(psp, chip_name);
> - if (err)
> - return err;
> break;
> default:
> BUG();
> }
>
> - return 0;
> -
> -out2:
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> return err;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
> index 8ed2281b6557..67118e699219 100644
> --- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
> @@ -49,9 +49,8 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
> {
> struct amdgpu_device *adev = psp->adev;
> const char *chip_name;
> - char fw_name[30];
> + char ucode_prefix[30];
> int err = 0;
> - const struct ta_firmware_header_v1_0 *ta_hdr;
> DRM_DEBUG("\n");
>
> switch (adev->asic_type) {
> @@ -64,67 +63,20 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
> default:
> BUG();
> }
> + amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
>
> err = psp_init_asd_microcode(psp, chip_name);
> + if (err)
> + return err;
> + err = psp_init_ta_microcode(psp, ucode_prefix);
> if (err)
> return err;
>
> - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
> - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> - if (err) {
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> - dev_info(adev->dev,
> - "psp v12.0: Failed to load firmware \"%s\"\n",
> - fw_name);
> - } else {
> - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> - if (err)
> - goto out;
> -
> - ta_hdr = (const struct ta_firmware_header_v1_0 *)
> - adev->psp.ta_fw->data;
> - adev->psp.hdcp_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->hdcp.fw_version);
> - adev->psp.hdcp_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->hdcp.size_bytes);
> - adev->psp.hdcp_context.context.bin_desc.start_addr =
> - (uint8_t *)ta_hdr +
> - le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
> -
> - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
> -
> - adev->psp.dtm_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->dtm.fw_version);
> - adev->psp.dtm_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->dtm.size_bytes);
> - adev->psp.dtm_context.context.bin_desc.start_addr =
> - (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
> - le32_to_cpu(ta_hdr->dtm.offset_bytes);
> -
> - if (adev->apu_flags & AMD_APU_IS_RENOIR) {
> - adev->psp.securedisplay_context.context.bin_desc.fw_version =
> - le32_to_cpu(ta_hdr->securedisplay.fw_version);
> - adev->psp.securedisplay_context.context.bin_desc.size_bytes =
> - le32_to_cpu(ta_hdr->securedisplay.size_bytes);
> - adev->psp.securedisplay_context.context.bin_desc.start_addr =
> - (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
> - le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
> - }
> - }
> -
> - return 0;
> -
> -out:
> - release_firmware(adev->psp.ta_fw);
> - adev->psp.ta_fw = NULL;
> - if (err) {
> - dev_err(adev->dev,
> - "psp v12.0: Failed to load firmware \"%s\"\n",
> - fw_name);
> - }
> + /* only supported on renoir */
> + if (!(adev->apu_flags & AMD_APU_IS_RENOIR))
> + adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
>
> - return err;
> + return psp_init_ta_microcode(psp, ucode_prefix);

I meant the below lines to come after this call. Even if it gets some
value during parsing for other SOCs, force to 0.

if (!(adev->apu_flags & AMD_APU_IS_RENOIR))
adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;

Thanks,
Lijo

> }
>
> static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)

2023-01-09 19:41:22

by Mario Limonciello

[permalink] [raw]
Subject: RE: [PATCH v7 20/45] drm/amd: Parse both v1 and v2 TA microcode headers using same function

[AMD Official Use Only - General]



> -----Original Message-----
> From: Lazar, Lijo <[email protected]>
> Sent: Thursday, January 5, 2023 21:27
> To: Limonciello, Mario <[email protected]>; Deucher, Alexander
> <[email protected]>; [email protected]
> Cc: Javier Martinez Canillas <[email protected]>; Carlos Soriano Sanchez
> <[email protected]>; [email protected]; dri-
> [email protected]; David Airlie <[email protected]>; Daniel Vetter
> <[email protected]>; Koenig, Christian <[email protected]>; Pan,
> Xinhui <[email protected]>; David Airlie <[email protected]>
> Subject: Re: [PATCH v7 20/45] drm/amd: Parse both v1 and v2 TA microcode
> headers using same function
>
>
>
> On 1/5/2023 10:31 PM, Mario Limonciello wrote:
> > Several IP versions duplicate code and can't use the common helpers.
> > Move this code into a single function so that the helpers can be used.
> >
> > Signed-off-by: Mario Limonciello <[email protected]>
> > ---
> > v6->v7:
> > * Drop tags
> > * Only set adev->psp.securedisplay_context.context on PSPv12 Renoir
> and
> > PSP v10 which matches previous behavior. If it should match for Cezanne
> > and PSPv11 too we can undo this part of the check.
> > v5->v6:
> > * Rebase on earlier patches
> > ---
> > drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 123
> ++++++++++++++++++------
> > drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 64 +-----------
> > drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 80 ++-------------
> > drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 66 ++-----------
> > 4 files changed, 115 insertions(+), 218 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
> > index 7a2fc920739b..bdc2bf87a286 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
> > @@ -3272,41 +3272,76 @@ static int parse_ta_bin_descriptor(struct
> psp_context *psp,
> > return 0;
> > }
> >
> > -int psp_init_ta_microcode(struct psp_context *psp,
> > - const char *chip_name)
> > +static int parse_ta_v1_microcode(struct psp_context *psp)
> > {
> > + const struct ta_firmware_header_v1_0 *ta_hdr;
> > struct amdgpu_device *adev = psp->adev;
> > - char fw_name[PSP_FW_NAME_LEN];
> > - const struct ta_firmware_header_v2_0 *ta_hdr;
> > - int err = 0;
> > - int ta_index = 0;
> >
> > - if (!chip_name) {
> > - dev_err(adev->dev, "invalid chip name for ta microcode\n");
> > + ta_hdr = (const struct ta_firmware_header_v1_0 *) adev-
> >psp.ta_fw->data;
> > +
> > + if (le16_to_cpu(ta_hdr->header.header_version_major) != 1)
> > return -EINVAL;
> > - }
> >
> > - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin",
> chip_name);
> > - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> > - if (err)
> > - goto out;
> > + adev->psp.xgmi_context.context.bin_desc.fw_version =
> > + le32_to_cpu(ta_hdr->xgmi.fw_version);
> > + adev->psp.xgmi_context.context.bin_desc.size_bytes =
> > + le32_to_cpu(ta_hdr->xgmi.size_bytes);
> > + adev->psp.xgmi_context.context.bin_desc.start_addr =
> > + (uint8_t *)ta_hdr +
> > + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
> > +
> > + adev->psp.ras_context.context.bin_desc.fw_version =
> > + le32_to_cpu(ta_hdr->ras.fw_version);
> > + adev->psp.ras_context.context.bin_desc.size_bytes =
> > + le32_to_cpu(ta_hdr->ras.size_bytes);
> > + adev->psp.ras_context.context.bin_desc.start_addr =
> > + (uint8_t *)adev-
> >psp.xgmi_context.context.bin_desc.start_addr +
> > + le32_to_cpu(ta_hdr->ras.offset_bytes);
> > +
> > + adev->psp.hdcp_context.context.bin_desc.fw_version =
> > + le32_to_cpu(ta_hdr->hdcp.fw_version);
> > + adev->psp.hdcp_context.context.bin_desc.size_bytes =
> > + le32_to_cpu(ta_hdr->hdcp.size_bytes);
> > + adev->psp.hdcp_context.context.bin_desc.start_addr =
> > + (uint8_t *)ta_hdr +
> > + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
> > +
> > + adev->psp.dtm_context.context.bin_desc.fw_version =
> > + le32_to_cpu(ta_hdr->dtm.fw_version);
> > + adev->psp.dtm_context.context.bin_desc.size_bytes =
> > + le32_to_cpu(ta_hdr->dtm.size_bytes);
> > + adev->psp.dtm_context.context.bin_desc.start_addr =
> > + (uint8_t *)adev-
> >psp.hdcp_context.context.bin_desc.start_addr +
> > + le32_to_cpu(ta_hdr->dtm.offset_bytes);
> > +
> > + adev->psp.securedisplay_context.context.bin_desc.fw_version =
> > + le32_to_cpu(ta_hdr->securedisplay.fw_version);
> > + adev->psp.securedisplay_context.context.bin_desc.size_bytes =
> > + le32_to_cpu(ta_hdr->securedisplay.size_bytes);
> > + adev->psp.securedisplay_context.context.bin_desc.start_addr =
> > + (uint8_t *)adev-
> >psp.hdcp_context.context.bin_desc.start_addr +
> > + le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
> > +
> > + adev->psp.ta_fw_version = le32_to_cpu(ta_hdr-
> >header.ucode_version);
> >
> > - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> > - if (err)
> > - goto out;
> > + return 0;
> > +}
> > +
> > +static int parse_ta_v2_microcode(struct psp_context *psp)
> > +{
> > + const struct ta_firmware_header_v2_0 *ta_hdr;
> > + struct amdgpu_device *adev = psp->adev;
> > + int err = 0;
> > + int ta_index = 0;
> >
> > ta_hdr = (const struct ta_firmware_header_v2_0 *)adev-
> >psp.ta_fw->data;
> >
> > - if (le16_to_cpu(ta_hdr->header.header_version_major) != 2) {
> > - dev_err(adev->dev, "unsupported TA header version\n");
> > - err = -EINVAL;
> > - goto out;
> > - }
> > + if (le16_to_cpu(ta_hdr->header.header_version_major) != 2)
> > + return -EINVAL;
> >
> > if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >=
> UCODE_MAX_PSP_PACKAGING) {
> > dev_err(adev->dev, "packed TA count exceeds maximum
> limit\n");
> > - err = -EINVAL;
> > - goto out;
> > + return -EINVAL;
> > }
> >
> > for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr-
> >ta_fw_bin_count); ta_index++) {
> > @@ -3314,14 +3349,46 @@ int psp_init_ta_microcode(struct psp_context
> *psp,
> > &ta_hdr->ta_fw_bin[ta_index],
> > ta_hdr);
> > if (err)
> > - goto out;
> > + return err;
> > }
> >
> > return 0;
> > -out:
> > - dev_err(adev->dev, "fail to initialize ta microcode\n");
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > +}
> > +
> > +int psp_init_ta_microcode(struct psp_context *psp, const char
> *chip_name)
> > +{
> > + const struct common_firmware_header *hdr;
> > + struct amdgpu_device *adev = psp->adev;
> > + char fw_name[PSP_FW_NAME_LEN];
> > + int err;
> > +
> > + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin",
> chip_name);
> > + err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> > + if (err)
> > + return err;
> > + err = amdgpu_ucode_validate(adev->psp.ta_fw);
> > + if (err)
> > + return err;
> > +
> > + hdr = (const struct common_firmware_header *)adev->psp.ta_fw-
> >data;
> > + switch (le16_to_cpu(hdr->header_version_major)) {
> > + case 1:
> > + err = parse_ta_v1_microcode(psp);
> > + break;
> > + case 2:
> > + err = parse_ta_v2_microcode(psp);
> > + break;
> > + default:
> > + dev_err(adev->dev, "unsupported TA header version\n");
> > + err = -EINVAL;
> > + }
> > +
> > + if (err) {
> > + dev_err(adev->dev, "fail to initialize ta microcode\n");
> > + release_firmware(adev->psp.ta_fw);
> > + adev->psp.ta_fw = NULL;
> > + }
> > +
> > return err;
> > }
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> > index 9de46fa8f46c..f14fcfb9c425 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> > @@ -48,9 +48,8 @@ static int psp_v10_0_init_microcode(struct
> psp_context *psp)
> > {
> > struct amdgpu_device *adev = psp->adev;
> > const char *chip_name;
> > - char fw_name[30];
> > + char ucode_prefix[30];
> > int err = 0;
> > - const struct ta_firmware_header_v1_0 *ta_hdr;
> > DRM_DEBUG("\n");
> >
> > switch (adev->asic_type) {
> > @@ -64,66 +63,13 @@ static int psp_v10_0_init_microcode(struct
> psp_context *psp)
> > 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)
> > - goto out;
> > -
> > - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin",
> chip_name);
> > - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> > - if (err) {
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > - dev_info(adev->dev,
> > - "psp v10.0: Failed to load firmware \"%s\"\n",
> > - fw_name);
> > - } else {
> > - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> > - if (err)
> > - goto out2;
> > -
> > - ta_hdr = (const struct ta_firmware_header_v1_0 *)
> > - adev->psp.ta_fw->data;
> > - adev->psp.hdcp_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->hdcp.fw_version);
> > - adev->psp.hdcp_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->hdcp.size_bytes);
> > - adev->psp.hdcp_context.context.bin_desc.start_addr =
> > - (uint8_t *)ta_hdr +
> > - le32_to_cpu(ta_hdr-
> >header.ucode_array_offset_bytes);
> > -
> > - adev->psp.dtm_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->dtm.fw_version);
> > - adev->psp.dtm_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->dtm.size_bytes);
> > - adev->psp.dtm_context.context.bin_desc.start_addr =
> > - (uint8_t *)adev-
> >psp.hdcp_context.context.bin_desc.start_addr +
> > - le32_to_cpu(ta_hdr->dtm.offset_bytes);
> > -
> > - adev-
> >psp.securedisplay_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->securedisplay.fw_version);
> > - adev-
> >psp.securedisplay_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->securedisplay.size_bytes);
> > - adev-
> >psp.securedisplay_context.context.bin_desc.start_addr =
> > - (uint8_t *)adev-
> >psp.hdcp_context.context.bin_desc.start_addr +
> > - le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
> > -
> > - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr-
> >header.ucode_version);
> > - }
> > -
> > - return 0;
> > -
> > -out2:
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > -out:
> > - if (err) {
> > - dev_err(adev->dev,
> > - "psp v10.0: Failed to load firmware \"%s\"\n",
> > - fw_name);
> > - }
> > + return err;
> >
> > - return err;
> > + return psp_init_ta_microcode(psp, ucode_prefix);
> > }
> >
> > static int psp_v10_0_ring_create(struct psp_context *psp,
> > diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
> b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
> > index bd3e3e23a939..41e29b777666 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
> > @@ -89,9 +89,8 @@ static int psp_v11_0_init_microcode(struct
> psp_context *psp)
> > {
> > struct amdgpu_device *adev = psp->adev;
> > const char *chip_name;
> > - char fw_name[PSP_FW_NAME_LEN];
> > + char ucode_prefix[30];
> > int err = 0;
> > - const struct ta_firmware_header_v1_0 *ta_hdr;
> >
> > DRM_DEBUG("\n");
> >
> > @@ -129,7 +128,7 @@ static int psp_v11_0_init_microcode(struct
> psp_context *psp)
> > 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):
> > @@ -140,35 +139,8 @@ static int psp_v11_0_init_microcode(struct
> psp_context *psp)
> > err = psp_init_asd_microcode(psp, chip_name);
> > if (err)
> > return err;
> > - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin",
> chip_name);
> > - err = request_firmware(&adev->psp.ta_fw, fw_name, adev-
> >dev);
> > - if (err) {
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > - dev_info(adev->dev,
> > - "psp v11.0: Failed to load firmware
> \"%s\"\n", fw_name);
> > - } else {
> > - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> > - if (err)
> > - goto out2;
> > -
> > - ta_hdr = (const struct ta_firmware_header_v1_0
> *)adev->psp.ta_fw->data;
> > - adev-
> >psp.xgmi_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->xgmi.fw_version);
> > - adev-
> >psp.xgmi_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->xgmi.size_bytes);
> > - adev-
> >psp.xgmi_context.context.bin_desc.start_addr =
> > - (uint8_t *)ta_hdr +
> > - le32_to_cpu(ta_hdr-
> >header.ucode_array_offset_bytes);
> > - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr-
> >header.ucode_version);
> > - adev->psp.ras_context.context.bin_desc.fw_version
> =
> > - le32_to_cpu(ta_hdr->ras.fw_version);
> > - adev->psp.ras_context.context.bin_desc.size_bytes
> =
> > - le32_to_cpu(ta_hdr->ras.size_bytes);
> > - adev->psp.ras_context.context.bin_desc.start_addr
> =
> > - (uint8_t *)adev-
> >psp.xgmi_context.context.bin_desc.start_addr +
> > - le32_to_cpu(ta_hdr->ras.offset_bytes);
> > - }
> > + err = psp_init_ta_microcode(psp, ucode_prefix);
> > + adev-
> >psp.securedisplay_context.context.bin_desc.size_bytes = 0;
> > break;
> > case IP_VERSION(11, 0, 0):
> > case IP_VERSION(11, 0, 5):
> > @@ -179,39 +151,8 @@ static int psp_v11_0_init_microcode(struct
> psp_context *psp)
> > err = psp_init_asd_microcode(psp, chip_name);
> > if (err)
> > return err;
> > - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin",
> chip_name);
> > - err = request_firmware(&adev->psp.ta_fw, fw_name, adev-
> >dev);
> > - if (err) {
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > - dev_info(adev->dev,
> > - "psp v11.0: Failed to load firmware
> \"%s\"\n", fw_name);
> > - } else {
> > - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> > - if (err)
> > - goto out2;
> > -
> > - ta_hdr = (const struct ta_firmware_header_v1_0
> *)adev->psp.ta_fw->data;
> > - adev-
> >psp.hdcp_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->hdcp.fw_version);
> > - adev-
> >psp.hdcp_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->hdcp.size_bytes);
> > - adev-
> >psp.hdcp_context.context.bin_desc.start_addr =
> > - (uint8_t *)ta_hdr +
> > - le32_to_cpu(
> > - ta_hdr-
> >header.ucode_array_offset_bytes);
> > -
> > - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr-
> >header.ucode_version);
> > -
> > - adev-
> >psp.dtm_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->dtm.fw_version);
> > - adev-
> >psp.dtm_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->dtm.size_bytes);
> > - adev-
> >psp.dtm_context.context.bin_desc.start_addr =
> > - (uint8_t *)adev->psp.hdcp_context.context
> > - .bin_desc.start_addr +
> > - le32_to_cpu(ta_hdr->dtm.offset_bytes);
> > - }
> > + err = psp_init_ta_microcode(psp, ucode_prefix);
> > + adev-
> >psp.securedisplay_context.context.bin_desc.size_bytes = 0;
> > break;
> > case IP_VERSION(11, 0, 7):
> > case IP_VERSION(11, 0, 11):
> > @@ -221,26 +162,17 @@ static int psp_v11_0_init_microcode(struct
> psp_context *psp)
> > if (err)
> > return err;
> > err = psp_init_ta_microcode(psp, chip_name);
> > - if (err)
> > - return err;
> > break;
> > case IP_VERSION(11, 5, 0):
> > err = psp_init_asd_microcode(psp, chip_name);
> > if (err)
> > return err;
> > err = psp_init_toc_microcode(psp, chip_name);
> > - if (err)
> > - return err;
> > break;
> > default:
> > BUG();
> > }
> >
> > - return 0;
> > -
> > -out2:
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > return err;
> > }
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
> b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
> > index 8ed2281b6557..67118e699219 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
> > @@ -49,9 +49,8 @@ static int psp_v12_0_init_microcode(struct
> psp_context *psp)
> > {
> > struct amdgpu_device *adev = psp->adev;
> > const char *chip_name;
> > - char fw_name[30];
> > + char ucode_prefix[30];
> > int err = 0;
> > - const struct ta_firmware_header_v1_0 *ta_hdr;
> > DRM_DEBUG("\n");
> >
> > switch (adev->asic_type) {
> > @@ -64,67 +63,20 @@ static int psp_v12_0_init_microcode(struct
> psp_context *psp)
> > default:
> > BUG();
> > }
> > + amdgpu_ucode_ip_version_decode(adev, MP0_HWIP,
> ucode_prefix, sizeof(ucode_prefix));
> >
> > err = psp_init_asd_microcode(psp, chip_name);
> > + if (err)
> > + return err;
> > + err = psp_init_ta_microcode(psp, ucode_prefix);
> > if (err)
> > return err;
> >
> > - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin",
> chip_name);
> > - err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
> > - if (err) {
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > - dev_info(adev->dev,
> > - "psp v12.0: Failed to load firmware \"%s\"\n",
> > - fw_name);
> > - } else {
> > - err = amdgpu_ucode_validate(adev->psp.ta_fw);
> > - if (err)
> > - goto out;
> > -
> > - ta_hdr = (const struct ta_firmware_header_v1_0 *)
> > - adev->psp.ta_fw->data;
> > - adev->psp.hdcp_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->hdcp.fw_version);
> > - adev->psp.hdcp_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->hdcp.size_bytes);
> > - adev->psp.hdcp_context.context.bin_desc.start_addr =
> > - (uint8_t *)ta_hdr +
> > - le32_to_cpu(ta_hdr-
> >header.ucode_array_offset_bytes);
> > -
> > - adev->psp.ta_fw_version = le32_to_cpu(ta_hdr-
> >header.ucode_version);
> > -
> > - adev->psp.dtm_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr->dtm.fw_version);
> > - adev->psp.dtm_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr->dtm.size_bytes);
> > - adev->psp.dtm_context.context.bin_desc.start_addr =
> > - (uint8_t *)adev-
> >psp.hdcp_context.context.bin_desc.start_addr +
> > - le32_to_cpu(ta_hdr->dtm.offset_bytes);
> > -
> > - if (adev->apu_flags & AMD_APU_IS_RENOIR) {
> > - adev-
> >psp.securedisplay_context.context.bin_desc.fw_version =
> > - le32_to_cpu(ta_hdr-
> >securedisplay.fw_version);
> > - adev-
> >psp.securedisplay_context.context.bin_desc.size_bytes =
> > - le32_to_cpu(ta_hdr-
> >securedisplay.size_bytes);
> > - adev-
> >psp.securedisplay_context.context.bin_desc.start_addr =
> > - (uint8_t *)adev-
> >psp.hdcp_context.context.bin_desc.start_addr +
> > - le32_to_cpu(ta_hdr-
> >securedisplay.offset_bytes);
> > - }
> > - }
> > -
> > - return 0;
> > -
> > -out:
> > - release_firmware(adev->psp.ta_fw);
> > - adev->psp.ta_fw = NULL;
> > - if (err) {
> > - dev_err(adev->dev,
> > - "psp v12.0: Failed to load firmware \"%s\"\n",
> > - fw_name);
> > - }
> > + /* only supported on renoir */
> > + if (!(adev->apu_flags & AMD_APU_IS_RENOIR))
> > + adev-
> >psp.securedisplay_context.context.bin_desc.size_bytes = 0;
> >
> > - return err;
> > + return psp_init_ta_microcode(psp, ucode_prefix);
>
> I meant the below lines to come after this call. Even if it gets some
> value during parsing for other SOCs, force to 0.
>
> if (!(adev->apu_flags & AMD_APU_IS_RENOIR))
> adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0;
>

Thanks, this was squashed in as it was committed.

> Thanks,
> Lijo
>
> > }
> >
> > static int psp_v12_0_bootloader_load_sysdrv(struct psp_context *psp)