Skip to content

Commit

Permalink
drm/amdgpu: Add interface to load SRIOV cap FW
Browse files Browse the repository at this point in the history
- Add interface to load SRIOV cap FW. If the FW does not
  exist, simply skip this FW loading routine.
  This FW will only be loaded under SRIOV. Other driver
  configuration will not be affected.
  By adding this interface, it will make us easier to
  prepare SRIOV Linux guest driver for different users.

- Update sysfs interface to read cap FW version.

- Refactor PSP FW loading routine under SRIOV to use a
  unified SWITCH statement instead of using IF statement

- Remove redundant amdgpu_sriov_vf() check in FW loading
  routine

Acked-by: Monk Liu <monk.liu@amd.com>
Acked-by: Guchun Chen <guchun.chen@amd.com>
Signed-off-by: Bokun Zhang <Bokun.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
bokun-xxmtg authored and alexdeucher committed Jan 14, 2022
1 parent 20c5e42 commit c4381d0
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 15 deletions.
14 changes: 14 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
fw_info->ver = adev->psp.toc.fw_version;
fw_info->feature = adev->psp.toc.feature_version;
break;
case AMDGPU_INFO_FW_CAP:
fw_info->ver = adev->psp.cap_fw_version;
fw_info->feature = adev->psp.cap_feature_version;
break;
default:
return -EINVAL;
}
Expand Down Expand Up @@ -1617,6 +1621,16 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused)
seq_printf(m, "TOC feature version: %u, firmware version: 0x%08x\n",
fw_info.feature, fw_info.ver);

/* CAP */
if (adev->psp.cap_fw) {
query_fw.fw_type = AMDGPU_INFO_FW_CAP;
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
if (ret)
return ret;
seq_printf(m, "CAP feature version: %u, firmware version: 0x%08x\n",
fw_info.feature, fw_info.ver);
}

seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version);

return 0;
Expand Down
108 changes: 95 additions & 13 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,32 @@ 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):
ret = psp_init_cap_microcode(psp, "vega10");
break;
case IP_VERSION(11, 0, 9):
ret = psp_init_cap_microcode(psp, "navi12");
break;
case IP_VERSION(11, 0, 7):
ret = psp_init_cap_microcode(psp, "sienna_cichlid");
break;
case IP_VERSION(13, 0, 2):
ret = psp_init_ta_microcode(psp, "aldebaran");
break;
default:
BUG();
break;
}

return ret;
}

static int psp_sw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Expand All @@ -273,19 +299,13 @@ static int psp_sw_init(void *handle)
ret = -ENOMEM;
}

if (!amdgpu_sriov_vf(adev)) {
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;
}
} else if (amdgpu_sriov_vf(adev) &&
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2)) {
ret = psp_init_ta_microcode(psp, "aldebaran");
if (ret) {
DRM_ERROR("Failed to initialize ta microcode!\n");
return ret;
}
if (ret) {
DRM_ERROR("Failed to load psp firmware!\n");
return ret;
}

memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry));
Expand Down Expand Up @@ -353,6 +373,10 @@ static int psp_sw_fini(void *handle)
release_firmware(psp->ta_fw);
psp->ta_fw = NULL;
}
if (adev->psp.cap_fw) {
release_firmware(psp->cap_fw);
psp->cap_fw = NULL;
}

if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7))
Expand Down Expand Up @@ -491,7 +515,10 @@ psp_cmd_submit_buf(struct psp_context *psp,
DRM_WARN("psp gfx command %s(0x%X) failed and response status is (0x%X)\n",
psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), psp->cmd_buf_mem->cmd_id,
psp->cmd_buf_mem->resp.status);
if (!timeout) {
/* If we load CAP FW, PSP must return 0 under SRIOV
* also return failure in case of timeout
*/
if ((ucode && (ucode->ucode_id == AMDGPU_UCODE_ID_CAP)) || !timeout) {
ret = -EINVAL;
goto exit;
}
Expand Down Expand Up @@ -2051,6 +2078,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
enum psp_gfx_fw_type *type)
{
switch (ucode->ucode_id) {
case AMDGPU_UCODE_ID_CAP:
*type = GFX_FW_TYPE_CAP;
break;
case AMDGPU_UCODE_ID_SDMA0:
*type = GFX_FW_TYPE_SDMA0;
break;
Expand Down Expand Up @@ -3217,6 +3247,58 @@ int psp_init_ta_microcode(struct psp_context *psp,
return err;
}

int psp_init_cap_microcode(struct psp_context *psp,
const char *chip_name)
{
struct amdgpu_device *adev = psp->adev;
char fw_name[PSP_FW_NAME_LEN];
const struct psp_firmware_header_v1_0 *cap_hdr_v1_0;
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);
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);
if (err) {
dev_err(adev->dev, "fail to initialize cap microcode\n");
goto out;
}

info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP];
info->ucode_id = AMDGPU_UCODE_ID_CAP;
info->fw = adev->psp.cap_fw;
cap_hdr_v1_0 = (const struct psp_firmware_header_v1_0 *)
adev->psp.cap_fw->data;
adev->firmware.fw_size += ALIGN(
le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes), PAGE_SIZE);
adev->psp.cap_fw_version = le32_to_cpu(cap_hdr_v1_0->header.ucode_version);
adev->psp.cap_feature_version = le32_to_cpu(cap_hdr_v1_0->sos.fw_version);
adev->psp.cap_ucode_size = le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes);

return 0;

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

static int psp_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{
Expand Down
9 changes: 9 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,9 @@ struct psp_context
/* toc firmware */
const struct firmware *toc_fw;

/* cap firmware */
const struct firmware *cap_fw;

/* fence buffer */
struct amdgpu_bo *fence_buf_bo;
uint64_t fence_buf_mc_addr;
Expand All @@ -327,6 +330,10 @@ struct psp_context
const struct firmware *ta_fw;
uint32_t ta_fw_version;

uint32_t cap_fw_version;
uint32_t cap_feature_version;
uint32_t cap_ucode_size;

struct ta_context asd_context;
struct psp_xgmi_context xgmi_context;
struct psp_ras_context ras_context;
Expand Down Expand Up @@ -440,6 +447,8 @@ int psp_init_sos_microcode(struct psp_context *psp,
const char *chip_name);
int psp_init_ta_microcode(struct psp_context *psp,
const char *chip_name);
int psp_init_cap_microcode(struct psp_context *psp,
const char *chip_name);
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
uint64_t *output_ptr);

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ enum AMDGPU_UCODE_ID {
AMDGPU_UCODE_ID_VCN0_RAM,
AMDGPU_UCODE_ID_VCN1_RAM,
AMDGPU_UCODE_ID_DMCUB,
AMDGPU_UCODE_ID_CAP,
AMDGPU_UCODE_ID_MAXIMUM,
};

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ enum psp_gfx_fw_type {
GFX_FW_TYPE_SDMA6 = 56, /* SDMA6 MI */
GFX_FW_TYPE_SDMA7 = 57, /* SDMA7 MI */
GFX_FW_TYPE_VCN1 = 58, /* VCN1 MI */
GFX_FW_TYPE_CAP = 62, /* CAP_FW */
GFX_FW_TYPE_REG_LIST = 67, /* REG_LIST MI */
GFX_FW_TYPE_MAX
};
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ MODULE_FIRMWARE("amdgpu/navi14_ta.bin");
MODULE_FIRMWARE("amdgpu/navi12_sos.bin");
MODULE_FIRMWARE("amdgpu/navi12_asd.bin");
MODULE_FIRMWARE("amdgpu/navi12_ta.bin");
MODULE_FIRMWARE("amdgpu/navi12_cap.bin");
MODULE_FIRMWARE("amdgpu/arcturus_sos.bin");
MODULE_FIRMWARE("amdgpu/arcturus_asd.bin");
MODULE_FIRMWARE("amdgpu/arcturus_ta.bin");
MODULE_FIRMWARE("amdgpu/sienna_cichlid_sos.bin");
MODULE_FIRMWARE("amdgpu/sienna_cichlid_ta.bin");
MODULE_FIRMWARE("amdgpu/sienna_cichlid_cap.bin");
MODULE_FIRMWARE("amdgpu/navy_flounder_sos.bin");
MODULE_FIRMWARE("amdgpu/navy_flounder_ta.bin");
MODULE_FIRMWARE("amdgpu/vangogh_asd.bin");
Expand Down Expand Up @@ -177,8 +179,6 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
err = psp_init_asd_microcode(psp, chip_name);
if (err)
return err;
if (amdgpu_sriov_vf(adev))
break;
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
if (err) {
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

MODULE_FIRMWARE("amdgpu/vega10_sos.bin");
MODULE_FIRMWARE("amdgpu/vega10_asd.bin");
MODULE_FIRMWARE("amdgpu/vega10_cap.bin");
MODULE_FIRMWARE("amdgpu/vega12_sos.bin");
MODULE_FIRMWARE("amdgpu/vega12_asd.bin");

Expand Down
2 changes: 2 additions & 0 deletions include/uapi/drm/amdgpu_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,8 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INFO_FW_DMCUB 0x14
/* Subquery id: Query TOC firmware version */
#define AMDGPU_INFO_FW_TOC 0x15
/* Subquery id: Query CAP firmware version */
#define AMDGPU_INFO_FW_CAP 0x16

/* number of bytes moved for TTM migration */
#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f
Expand Down

0 comments on commit c4381d0

Please sign in to comment.