2023-01-03 22:42:23

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 00/27] 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.

v3->v4:
* Rework to delay framebuffer release until early_init is done
* Make individual IPs load microcode during early init phase
* Add SMU and DMCUB cases 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_load` 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_load` helper for VCN
drm/amd: Load VCN microcode during early_init
drm/amd: Load MES microcode during early_init
drm/amd: Use `amdgpu_ucode_load` helper for MES
drm/amd: Remove superfluous assignment for `adev->mes.adev`
drm/amd: Use `amdgpu_ucode_load` helper for GFX9
drm/amd: Load GFX9 microcode during early_init
drm/amd: Use `amdgpu_ucode_load` helper for GFX10
drm/amd: Load GFX10 microcode during early_init
drm/amd: Use `amdgpu_ucode_load` helper 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_load` helper for PSP
drm/amd/display: Load DMUB microcode during early_init
drm/amd: Use `amdgpu_ucode_load` helper for SMU
drm/amd: Load SMU microcode during early_init
drm/amd: Optimize SRIOV switch/case for PSP microcode load

drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 +
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 6 -
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 60 ++++
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 276 +++++++++---------
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 15 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 18 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 245 ++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 103 +++----
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 1 +
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 117 ++------
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 101 +++----
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 101 ++-----
drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 98 ++-----
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 89 ++----
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 80 +----
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 129 +-------
drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 75 +----
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_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 | 89 ++++--
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 +-
.../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 40 +--
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 17 +-
36 files changed, 751 insertions(+), 1174 deletions(-)

--
2.34.1


2023-01-03 22:43:09

by Mario Limonciello

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

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

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 ac4d675abcb5..d51fe3431e2b 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-03 22:44:30

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 08/27] 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.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* New patch
---
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 83e8f0dae647..f052173ef1e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -277,10 +277,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-03 22:44:32

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 16/27] drm/amd: Use `amdgpu_ucode_load` helper for GFX10

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

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* New patch
---
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 35 ++++++--------------------
1 file changed, 8 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 49d34c7bbf20..5f6b59e23313 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -4030,41 +4030,31 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp%s.bin", chip_name, wks);
- 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_load(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);
- 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_load(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);
- 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_load(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);
- err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
- if (err)
- goto out;
+ err = amdgpu_ucode_load(adev, &adev->gfx.rlc_fw, fw_name);
/* don't check this. There are apparently firmwares in the wild with
* incorrect size in the header
*/
- err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
+ if (err == -ENODEV)
+ goto out;
if (err)
dev_dbg(adev->dev,
"gfx10: amdgpu_ucode_validate() failed \"%s\"\n",
@@ -4078,21 +4068,15 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec%s.bin", chip_name, wks);
- 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_load(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);
- err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+ err = amdgpu_ucode_load(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 {
@@ -4103,9 +4087,6 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
gfx_v10_0_check_fw_write_wait(adev);
out:
if (err) {
- dev_err(adev->dev,
- "gfx10: 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);
--
2.34.1

2023-01-03 22:45:24

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 22/27] 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.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* new patch
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 128 +++++++++--------------
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 3 +
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 16 +--
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 55 ++--------
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 +--
8 files changed, 79 insertions(+), 193 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index d51fe3431e2b..3b0644600a1f 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,20 +2904,14 @@ 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, char *ucode_prefix)
{
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);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", ucode_prefix);
err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev);
if (err)
goto out;
@@ -2944,20 +2934,14 @@ 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, char *ucode_prefix)
{
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);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix);
err = request_firmware(&adev->psp.toc_fw, fw_name, adev->dev);
if (err)
goto out;
@@ -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, char *ucode_prefix)
{
struct amdgpu_device *adev = psp->adev;
char fw_name[PSP_FW_NAME_LEN];
@@ -3121,12 +3104,7 @@ 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);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", ucode_prefix);
err = request_firmware(&adev->psp.sos_fw, fw_name, adev->dev);
if (err)
goto out;
@@ -3391,8 +3369,7 @@ int psp_init_ta_microcode(struct psp_context *psp, char *ucode_prefix)
return err;
}

-int psp_init_cap_microcode(struct psp_context *psp,
- const char *chip_name)
+int psp_init_cap_microcode(struct psp_context *psp, char *ucode_prefix)
{
struct amdgpu_device *adev = psp->adev;
char fw_name[PSP_FW_NAME_LEN];
@@ -3400,17 +3377,12 @@ 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;
}

- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", ucode_prefix);
err = request_firmware(&adev->psp.cap_fw, fw_name, adev->dev);
if (err) {
dev_warn(adev->dev, "cap microcode does not exist, skip\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 45dc370f96bd..47b88233bf94 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -502,6 +502,9 @@ int psp_ring_cmd_submit(struct psp_context *psp,
uint64_t cmd_buf_mc_addr,
uint64_t fence_mc_addr,
int index);
+int psp_init_asd_microcode(struct psp_context *psp, char *ucode_prefix);
+int psp_init_toc_microcode(struct psp_context *psp, char *ucode_prefix);
+int psp_init_sos_microcode(struct psp_context *psp, char *ucode_prefix);
int psp_init_ta_microcode(struct psp_context *psp, char *ucode_prefix);
int psp_init_cap_microcode(struct psp_context *psp,
const char *chip_name);
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index 7fb48c1dec71..e1b7fca09666 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -47,27 +47,15 @@ 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, chip_name);
+ err = psp_init_asd_microcode(psp, ucode_prefix);
if (err)
- goto out;
+ return err;

return psp_init_ta_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 5f140b7c30d2..5fb572d3e42a 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -88,57 +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 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");

- 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);
@@ -148,10 +111,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);
@@ -162,18 +125,18 @@ 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);
if (err)
return err;
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);
if (err)
return err;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
index 634fa2822d8a..45810e4a7e45 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;
return 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-03 22:45:44

by Mario Limonciello

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

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

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* new patch
---
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-03 22:47:09

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 11/27] 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.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* Introduce new early_init phase for MES
v2->v3:
* Add a missing newline
---
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-03 22:47:33

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 06/27] drm/amd: Use `amdgpu_ucode_load` helper for SDMA

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

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* New patch
---
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index ea5278f094c0..9e85a078d918 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);
@@ -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_load(adev, &adev->sdma.instance[instance].fw, fw_name);
if (err)
goto out;

--
2.34.1

2023-01-03 22:47:53

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 24/27] 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.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* New patch
---
.../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..eeccc8af0320 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_load(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-03 22:48:41

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 10/27] 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.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* Move out of IP discovery and introduce early_init phase for VCN
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 94 ++++++++++---------------
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, 52 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 6d9cb7fb67cf..48fc9059c386 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -36,25 +36,25 @@
#include "soc15d.h"

/* Firmware Names */
-#define FIRMWARE_RAVEN "amdgpu/raven_vcn.bin"
-#define FIRMWARE_PICASSO "amdgpu/picasso_vcn.bin"
-#define FIRMWARE_RAVEN2 "amdgpu/raven2_vcn.bin"
-#define FIRMWARE_ARCTURUS "amdgpu/arcturus_vcn.bin"
-#define FIRMWARE_RENOIR "amdgpu/renoir_vcn.bin"
-#define FIRMWARE_GREEN_SARDINE "amdgpu/green_sardine_vcn.bin"
-#define FIRMWARE_NAVI10 "amdgpu/navi10_vcn.bin"
-#define FIRMWARE_NAVI14 "amdgpu/navi14_vcn.bin"
-#define FIRMWARE_NAVI12 "amdgpu/navi12_vcn.bin"
-#define FIRMWARE_SIENNA_CICHLID "amdgpu/sienna_cichlid_vcn.bin"
-#define FIRMWARE_NAVY_FLOUNDER "amdgpu/navy_flounder_vcn.bin"
-#define FIRMWARE_VANGOGH "amdgpu/vangogh_vcn.bin"
-#define FIRMWARE_DIMGREY_CAVEFISH "amdgpu/dimgrey_cavefish_vcn.bin"
-#define FIRMWARE_ALDEBARAN "amdgpu/aldebaran_vcn.bin"
-#define FIRMWARE_BEIGE_GOBY "amdgpu/beige_goby_vcn.bin"
-#define FIRMWARE_YELLOW_CARP "amdgpu/yellow_carp_vcn.bin"
-#define FIRMWARE_VCN_3_1_2 "amdgpu/vcn_3_1_2.bin"
-#define FIRMWARE_VCN4_0_0 "amdgpu/vcn_4_0_0.bin"
-#define FIRMWARE_VCN4_0_2 "amdgpu/vcn_4_0_2.bin"
+#define FIRMWARE_RAVEN "amdgpu/raven_vcn.bin"
+#define FIRMWARE_PICASSO "amdgpu/picasso_vcn.bin"
+#define FIRMWARE_RAVEN2 "amdgpu/raven2_vcn.bin"
+#define FIRMWARE_ARCTURUS "amdgpu/arcturus_vcn.bin"
+#define FIRMWARE_RENOIR "amdgpu/renoir_vcn.bin"
+#define FIRMWARE_GREEN_SARDINE "amdgpu/green_sardine_vcn.bin"
+#define FIRMWARE_NAVI10 "amdgpu/navi10_vcn.bin"
+#define FIRMWARE_NAVI14 "amdgpu/navi14_vcn.bin"
+#define FIRMWARE_NAVI12 "amdgpu/navi12_vcn.bin"
+#define FIRMWARE_SIENNA_CICHLID "amdgpu/sienna_cichlid_vcn.bin"
+#define FIRMWARE_NAVY_FLOUNDER "amdgpu/navy_flounder_vcn.bin"
+#define FIRMWARE_VANGOGH "amdgpu/vangogh_vcn.bin"
+#define FIRMWARE_DIMGREY_CAVEFISH "amdgpu/dimgrey_cavefish_vcn.bin"
+#define FIRMWARE_ALDEBARAN "amdgpu/aldebaran_vcn.bin"
+#define FIRMWARE_BEIGE_GOBY "amdgpu/beige_goby_vcn.bin"
+#define FIRMWARE_YELLOW_CARP "amdgpu/yellow_carp_vcn.bin"
+#define FIRMWARE_VCN_3_1_2 "amdgpu/vcn_3_1_2.bin"
+#define FIRMWARE_VCN4_0_0 "amdgpu/vcn_4_0_0.bin"
+#define FIRMWARE_VCN4_0_2 "amdgpu/vcn_4_0_2.bin"
#define FIRMWARE_VCN4_0_4 "amdgpu/vcn_4_0_4.bin"

MODULE_FIRMWARE(FIRMWARE_RAVEN);
@@ -80,10 +80,26 @@ 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_load(adev, &adev->vcn.fw, fw_name);
+ if (r) {
+ release_firmware(adev->vcn.fw);
+ adev->vcn.fw = NULL;
+ }
+
+ 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 +115,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 +143,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,13 +191,6 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
return -EINVAL;
}

- r = amdgpu_ucode_load(adev, &adev->vcn.fw, fw_name);
- if (r) {
- if (adev->vcn.fw)
- release_firmware(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-03 22:49:05

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 04/27] 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.

Reviewed-by: Alex Deucher <[email protected]>
Signed-off-by: Mario Limonciello <[email protected]>
Acked-by: Christian König <[email protected]>
---
v3->v4:
* No changes
---
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-03 22:49:22

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 03/27] 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]>
---
v3->v4:
* No changes
---
.../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-03 22:50:18

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 07/27] 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`.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* Move out of IP discovery and instead simplify early_init
v2->v3:
* Fix dGPU naming scheme
---
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 7 ++-
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, 13 insertions(+), 155 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 9e85a078d918..83e8f0dae647 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -200,15 +200,18 @@ 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));
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s%s.bin", ucode_prefix, !instance ? "" : "1");
err = amdgpu_ucode_load(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-03 23:02:25

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 13/27] drm/amd: Remove superfluous assignment for `adev->mes.adev`

`amdgpu_mes_init` already sets `adev->mes.adev`, so there is no need
to also set it in the IP specific versions.

Signed-off-by: Mario Limonciello <[email protected]>
---
v4:
* New patch
---
drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 1 -
drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 1 -
2 files changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
index 9c5ff8b7c202..f58debf2783c 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -931,7 +931,6 @@ static int mes_v10_1_sw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int pipe, r;

- adev->mes.adev = adev;
adev->mes.funcs = &mes_v10_1_funcs;
adev->mes.kiq_hw_init = &mes_v10_1_kiq_hw_init;

diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index 3af77a32baac..c8bdee9a66c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -1020,7 +1020,6 @@ static int mes_v11_0_sw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int pipe, r;

- adev->mes.adev = adev;
adev->mes.funcs = &mes_v11_0_funcs;
adev->mes.kiq_hw_init = &mes_v11_0_kiq_hw_init;
adev->mes.kiq_hw_fini = &mes_v11_0_kiq_hw_fini;
--
2.34.1

2023-01-03 23:02:31

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 14/27] drm/amd: Use `amdgpu_ucode_load` helper for GFX9

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

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* new patch
---
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 43 +++++----------------------
1 file changed, 8 insertions(+), 35 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..27040821d764 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -1257,37 +1257,25 @@ 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_load(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_load(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_load(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);
@@ -1328,10 +1316,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_load(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;
@@ -1341,12 +1326,10 @@ static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev,
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;
}
+
return err;
}

@@ -1371,12 +1354,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);
- if (err)
- goto out;
- err = amdgpu_ucode_validate(adev->gfx.mec_fw);
+ err = amdgpu_ucode_load(adev, &adev->gfx.mec_fw, fw_name);
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 +1366,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_load(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,13 +1379,9 @@ 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);
--
2.34.1

2023-01-03 23:02:42

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 25/27] drm/amd: Use `amdgpu_ucode_load` helper for SMU

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

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* New patch
---
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 5 +----
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 5 +----
2 files changed, 2 insertions(+), 8 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..1d693cda5818 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_load(adev, &adev->pm.fw, fw_name);
if (err)
goto out;

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..845a7fc83ba8 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_load(adev, &adev->pm.fw, fw_name);
if (err)
goto out;

--
2.34.1

2023-01-03 23:03:09

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 05/27] 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.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3-v4:
* New patch
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 24 +++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 +
2 files changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index eafcddce58d3..8c4a7b09e344 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -1312,3 +1312,27 @@ 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_load - Load 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_load(struct amdgpu_device *adev, const struct firmware **fw, 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;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 552e06929229..b9139fb44506 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -544,6 +544,7 @@ 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_load(struct amdgpu_device *adev, const struct firmware **fw, char *fw_name);
bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
uint16_t hdr_major, uint16_t hdr_minor);

--
2.34.1

2023-01-03 23:12:28

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 17/27] 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.

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* Move out of discovery into early_init
---
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 82 ++++++--------------------
1 file changed, 17 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 5f6b59e23313..75781722c7e9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -3974,9 +3974,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;
@@ -3984,71 +3984,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_load(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_load(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_load(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_load(adev, &adev->gfx.rlc_fw, fw_name);
/* don't check this. There are apparently firmwares in the wild with
* incorrect size in the header
@@ -4067,14 +4027,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_load(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_load(adev, &adev->gfx.mec2_fw, fw_name);
if (!err) {
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2);
@@ -4083,6 +4043,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:
@@ -4251,19 +4213,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)
@@ -4631,9 +4585,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) {
@@ -7611,7 +7563,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-03 23:16:36

by Mario Limonciello

[permalink] [raw]
Subject: [PATCH v4 23/27] drm/amd: Use `amdgpu_ucode_load` helper for PSP

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

Signed-off-by: Mario Limonciello <[email protected]>
---
v3->v4:
* New patch
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 42 ++++++-------------------
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 3 +-
2 files changed, 11 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 3b0644600a1f..f45362dd8228 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -2912,11 +2912,7 @@ int psp_init_asd_microcode(struct psp_context *psp, char *ucode_prefix)
int err = 0;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", ucode_prefix);
- 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_load(adev, &adev->psp.asd_fw, fw_name);
if (err)
goto out;

@@ -2928,7 +2924,6 @@ int psp_init_asd_microcode(struct psp_context *psp, char *ucode_prefix)
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;
return err;
@@ -2942,11 +2937,7 @@ int psp_init_toc_microcode(struct psp_context *psp, char *ucode_prefix)
int err = 0;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", ucode_prefix);
- 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_load(adev, &adev->psp.toc_fw, fw_name);
if (err)
goto out;

@@ -2958,7 +2949,6 @@ int psp_init_toc_microcode(struct psp_context *psp, char *ucode_prefix)
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;
return err;
@@ -3105,11 +3095,7 @@ int psp_init_sos_microcode(struct psp_context *psp, char *ucode_prefix)
int fw_index = 0;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", ucode_prefix);
- 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_load(adev, &adev->psp.sos_fw, fw_name);
if (err)
goto out;

@@ -3181,8 +3167,6 @@ int psp_init_sos_microcode(struct psp_context *psp, char *ucode_prefix)

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

@@ -3340,10 +3324,7 @@ int psp_init_ta_microcode(struct psp_context *psp, char *ucode_prefix)
int err;

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", ucode_prefix);
- 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_load(adev, &adev->psp.ta_fw, fw_name);
if (err)
return err;

@@ -3383,17 +3364,14 @@ int psp_init_cap_microcode(struct psp_context *psp, char *ucode_prefix)
}

snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", ucode_prefix);
- 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_load(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];
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 47b88233bf94..415d32306b9a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -506,8 +506,7 @@ int psp_init_asd_microcode(struct psp_context *psp, char *ucode_prefix);
int psp_init_toc_microcode(struct psp_context *psp, char *ucode_prefix);
int psp_init_sos_microcode(struct psp_context *psp, char *ucode_prefix);
int psp_init_ta_microcode(struct psp_context *psp, char *ucode_prefix);
-int psp_init_cap_microcode(struct psp_context *psp,
- const char *chip_name);
+int psp_init_cap_microcode(struct psp_context *psp, char *ucode_prefix);
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
uint64_t *output_ptr);

--
2.34.1

2023-01-04 05:08:27

by Lazar, Lijo

[permalink] [raw]
Subject: Re: [PATCH v4 05/27] drm/amd: Add a new helper for loading/validating microcode



On 1/4/2023 3:48 AM, Mario Limonciello wrote:
> 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.
>
> Signed-off-by: Mario Limonciello <[email protected]>
> ---
> v3-v4:
> * New patch
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 24 +++++++++++++++++++++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 +
> 2 files changed, 25 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
> index eafcddce58d3..8c4a7b09e344 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
> @@ -1312,3 +1312,27 @@ 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_load - Load 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_load(struct amdgpu_device *adev, const struct firmware **fw, char *fw_name)

'load' also takes a different meaning of loading firmware to ASIC. Maybe
keep it as 'get' and keep another corresponding common 'put' for
release_firmware?

Thanks,
Lijo

> +{
> + 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;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
> index 552e06929229..b9139fb44506 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
> @@ -544,6 +544,7 @@ 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_load(struct amdgpu_device *adev, const struct firmware **fw, char *fw_name);
> bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
> uint16_t hdr_major, uint16_t hdr_minor);
>

2023-01-04 05:22:35

by Lazar, Lijo

[permalink] [raw]
Subject: Re: [PATCH v4 07/27] drm/amd: Convert SDMA to use `amdgpu_ucode_ip_version_decode`



On 1/4/2023 3:48 AM, Mario Limonciello wrote:
> Simplifies the code so that all SDMA versions will get the firmware
> name from `amdgpu_ucode_ip_version_decode`.
>
> Signed-off-by: Mario Limonciello <[email protected]>
> ---
> v3->v4:
> * Move out of IP discovery and instead simplify early_init
> v2->v3:
> * Fix dGPU naming scheme
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 7 ++-
> 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, 13 insertions(+), 155 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
> index 9e85a078d918..83e8f0dae647 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
> @@ -200,15 +200,18 @@ 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));
> + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s%s.bin", ucode_prefix, !instance ? "" : "1");

It is safer to keep the original logic with instance number as suffix
rather than hardcoding to 1.

Thanks,
Lijo

> err = amdgpu_ucode_load(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;

2023-01-04 09:39:53

by Christian König

[permalink] [raw]
Subject: Re: [PATCH v4 05/27] drm/amd: Add a new helper for loading/validating microcode

Am 04.01.23 um 05:53 schrieb Lazar, Lijo:
>
>
> On 1/4/2023 3:48 AM, Mario Limonciello wrote:
>> 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.
>>
>> Signed-off-by: Mario Limonciello <[email protected]>
>> ---
>> v3-v4:
>>   * New patch
>> ---
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 24 +++++++++++++++++++++++
>>   drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h |  1 +
>>   2 files changed, 25 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
>> index eafcddce58d3..8c4a7b09e344 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
>> @@ -1312,3 +1312,27 @@ 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_load - Load 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_load(struct amdgpu_device *adev, const struct
>> firmware **fw, char *fw_name)
>
> 'load' also takes a different meaning of loading firmware to ASIC.
> Maybe keep it as 'get' and keep another corresponding common 'put' for
> release_firmware?

get/put are usually used for reference counting, how about sticking with
request/release instead? That's used by the underlying functionality as
well IIRC.

Christian.

>
> Thanks,
> Lijo
>
>> +{
>> +    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;
>> +}
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
>> index 552e06929229..b9139fb44506 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
>> @@ -544,6 +544,7 @@ 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_load(struct amdgpu_device *adev, const struct
>> firmware **fw, char *fw_name);
>>   bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
>>                   uint16_t hdr_major, uint16_t hdr_minor);

2023-01-04 16:03:51

by Harry Wentland

[permalink] [raw]
Subject: Re: [PATCH v4 24/27] drm/amd/display: Load DMUB microcode during early_init

On 1/3/23 17:18, Mario Limonciello wrote:
> 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.
>
> Signed-off-by: Mario Limonciello <[email protected]>

In addition to changing the FW load order this also changes
request_firmware_direct to request_firmware but this seems to
be the correct thing here anyways, since DMUB is not optional.

Reviewed-by: Harry Wentland <[email protected]>

Harry

> ---
> v3->v4:
> * New patch
> ---
> .../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..eeccc8af0320 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_load(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)