[PATCH 5/8] drm/amdgpu/atomfirmware: add memory training related helper functions
Tuikov, Luben
Luben.Tuikov at amd.com
Wed Oct 9 03:34:11 UTC 2019
On 2019-10-08 3:29 p.m., Alex Deucher wrote:
> From: "Tianci.Yin" <tianci.yin at amd.com>
>
> parse firmware to get memory training capability and fb location.
>
> Change-Id: I147c1d48e255e0191be4beb1ad6b637da607bf75
> Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
> Signed-off-by: Tianci.Yin <tianci.yin at amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 7 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 5 +
> .../gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 130 ++++++++++++++++++
> .../gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h | 1 +
> 4 files changed, 143 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 0d60c2e6c592..eeb6b6282fce 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -288,6 +288,9 @@ struct amdgpu_ip_block_version {
> const struct amd_ip_funcs *funcs;
> };
>
> +#define hw_revision(major, minor, revision) \
> + ((((uint32_t) major) << 16) | ((uint32_t) minor << 8) | ((uint32_t) revision))
> +
> struct amdgpu_ip_block {
> struct amdgpu_ip_block_status status;
> const struct amdgpu_ip_block_version *version;
> @@ -630,6 +633,10 @@ struct amdgpu_fw_vram_usage {
> u64 size;
> struct amdgpu_bo *reserved_bo;
> void *va;
> +
> + /*offset on the top of vram, used as c2p write buffer*/
> + u64 mem_train_fb_loc;
> + bool mem_train_support;
> };
>
> /*
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> index 1c9d40f97a9b..5f5a2d3fff9b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
> @@ -2038,6 +2038,11 @@ int amdgpu_atombios_init(struct amdgpu_device *adev)
> if (adev->is_atom_fw) {
> amdgpu_atomfirmware_scratch_regs_init(adev);
> amdgpu_atomfirmware_allocate_fb_scratch(adev);
> + ret = amdgpu_atomfirmware_get_mem_train_fb_loc(adev);
> + if(ret) {
Space after a keyword: "if (ret)" according to LKCS.
> + DRM_ERROR("Failed to get mem train fb location.\n");
> + return ret;
> + }
> } else {
> amdgpu_atombios_scratch_regs_init(adev);
> amdgpu_atombios_allocate_fb_scratch(adev);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
> index 39fd8ae5a822..dfaebd929332 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
> @@ -27,6 +27,7 @@
> #include "amdgpu_atomfirmware.h"
> #include "atom.h"
> #include "atombios.h"
> +#include "soc15_hw_ip.h"
>
> bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev)
> {
> @@ -462,3 +463,132 @@ int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev)
> }
> return -EINVAL;
> }
> +
> +/*
> + * Check if VBIOS supports GDDR6 training data save/restore
> + */
> +static bool gddr6_mem_train_vbios_support(struct amdgpu_device *adev)
> +{
> + uint16_t data_offset;
> + int index;
> +
> + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
> + firmwareinfo);
> + if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, NULL,
> + NULL, NULL, &data_offset)) {
> + struct atom_firmware_info_v3_1 *firmware_info =
> + (struct atom_firmware_info_v3_1 *)(adev->mode_info.atom_context->bios +
> + data_offset);
> +
> + DRM_DEBUG("atom firmware capability:0x%08x.\n",
> + le32_to_cpu(firmware_info->firmware_capability));
> +
> + if (le32_to_cpu(firmware_info->firmware_capability) &
> + ATOM_FIRMWARE_CAP_ENABLE_2STAGE_BIST_TRAINING)
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static int gddr6_mem_train_support(struct amdgpu_device *adev)
> +{
> + int ret = 0;
int ret;
Don't preinitialize. Instead, explicitly set on all contingencies.
This makes the code more secure. See below.
> + bool vbios_support = false;
> + uint32_t major, minor, revision, hw_v;
> +
> + if (!amdgpu_sriov_vf(adev) &&
> + gddr6_mem_train_vbios_support(adev)) {
> + vbios_support = true;
> + }
> +
> + amdgpu_discovery_get_ip_version(adev, MP0_HWID, &major, &minor, &revision);
> + hw_v = hw_revision(major, minor, revision);
> + /*
> + * treat 0 revision as a special case since register for MP0 and MMHUB is missing
> + * for some Navi10 A0, preventing driver from discovering the hwip information since
> + * none of the functions will be initialized, it should not cause any problems
> + */
> + switch(hw_v) {
Space after keyword: "switch (hw_v) {" according to LKCS.
> + case hw_revision(11, 0, 0):
> + case hw_revision(11, 0, 5):
> + ret = vbios_support;
> + break;
> + default:
> + if (vbios_support) {
> + DRM_ERROR("memory training vbios supports but psp hw(%08x)"
> + " doesn't support!\n", hw_v);
> + ret = -1;
> + }
} else {
ret = 0;
}
break;
> + break;
> + }
> +
> + DRM_DEBUG("mp0 hw_v %08x, ret:%d.\n", hw_v, ret);
> + return ret;
> +}
> +
> +int amdgpu_atomfirmware_get_mem_train_fb_loc(struct amdgpu_device *adev)
> +{
> + struct atom_context *ctx = adev->mode_info.atom_context;
> + unsigned char *bios = ctx->bios;
> + struct vram_reserve_block *reserved_block;
> + int index, block_number;
> + uint8_t frev, crev;
> + uint16_t data_offset, size;
> + uint32_t start_address_in_kb = 0;
> + uint64_t offset;
> + int ret = 0;
> +
> + adev->fw_vram_usage.mem_train_support = false;
> + ret = gddr6_mem_train_support(adev);
> + if (ret == -1)
> + return -EINVAL;
> + else if (ret == 0)
> + return 0;
> +
> + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
> + vram_usagebyfirmware);
> + ret = amdgpu_atom_parse_data_header(ctx, index, &size, &frev, &crev,
> + &data_offset);
> + if (!ret) {
if (ret == 0)
Since it is an integer and not a pointer--compare to 0 integer.
Regards,
Luben
> + DRM_ERROR("parse data header failed.\n");
> + return -EINVAL;
> + }
> +
> + DRM_DEBUG("atom firmware common table header size:0x%04x, frev:0x%02x,"
> + " crev:0x%02x, data_offset:0x%04x.\n", size, frev, crev, data_offset);
> + /* only support 2.1+ */
> + if (((uint16_t)frev << 8 | crev) < 0x0201) {
> + DRM_ERROR("frev:0x%02x, crev:0x%02x < 2.1 !\n", frev, crev);
> + return -EINVAL;
> + }
> +
> + reserved_block = (struct vram_reserve_block *)
> + (bios + data_offset + sizeof(struct atom_common_table_header));
> + block_number = ((unsigned int)size - sizeof(struct atom_common_table_header))
> + / sizeof(struct vram_reserve_block);
> + reserved_block += (block_number > 0) ? block_number-1 : 0;
> + DRM_DEBUG("block_number:0x%04x, last block: 0x%08xkb sz, %dkb fw, %dkb drv.\n",
> + block_number,
> + le32_to_cpu(reserved_block->start_address_in_kb),
> + le16_to_cpu(reserved_block->used_by_firmware_in_kb),
> + le16_to_cpu(reserved_block->used_by_driver_in_kb));
> + if (reserved_block->used_by_firmware_in_kb > 0) {
> + start_address_in_kb = le32_to_cpu(reserved_block->start_address_in_kb);
> + offset = (uint64_t)start_address_in_kb * ONE_K;
> + if ((offset & (ONE_MEG - 1)) < (4 * ONE_K + 1) ) {
> + offset -= ONE_MEG;
> + }
> +
> + offset &= ~(ONE_MEG - 1);
> + adev->fw_vram_usage.mem_train_fb_loc = offset;
> + adev->fw_vram_usage.mem_train_support = true;
> + DRM_DEBUG("mem_train_fb_loc:0x%09llx.\n", offset);
> + ret = 0;
> + } else {
> + DRM_ERROR("used_by_firmware_in_kb is 0!\n");
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
> index 53449fc7baf4..f871af5ea6f3 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
> @@ -31,6 +31,7 @@ void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
> int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
> int amdgpu_atomfirmware_get_vram_info(struct amdgpu_device *adev,
> int *vram_width, int *vram_type, int *vram_vendor);
> +int amdgpu_atomfirmware_get_mem_train_fb_loc(struct amdgpu_device *adev);
> int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
> int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
> bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
>
More information about the amd-gfx
mailing list