[PATCH 11/14] drm/amdgpu/discovery: skip MEM_RESERVED_INFO on unsupported ASICs
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Feifei Xu <[email protected]> Some ASICs' MEM_RESERVED_INFO table_entry may carry non-zero garbage, causing signature check failed thus probe fail. Move signature check in amdgpu_discovery_get_mem_reserved_info_table(), returning -ENOENT when invalid so the table is skipped. v1->v2: Add discovery binary header check before populate the mem_reserved_info table. (Lijo) Signed-off-by: Feifei Xu <[email protected]> Reviewed-by: Candice Li <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 9bbdb9cba5018..6f3da085939b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -685,15 +685,11 @@ static int amdgpu_discovery_table_check(struct amdgpu_device *adev, check_table = false; break; } - case MEM_RESERVED_INFO: { - struct mem_reserved_info_header *mrhdr = - (struct mem_reserved_info_header *)(discovery_bin + offset); - act_val = le32_to_cpu(mrhdr->signature); - exp_val = MEM_RSV_TABLE_SIGNATURE; - table_size = le32_to_cpu(mrhdr->size); + case MEM_RESERVED_INFO: + /* Optional table; signature is validated in get_mem_reserved_info_table(). */ table_name = "mem_reserved table"; + check_table = false; break; - } default: dev_err(adev->dev, "invalid ip discovery table id %d specified\n", table_id); check_table = false; @@ -2497,7 +2493,10 @@ void amdgpu_discovery_mem_reserved_info_sysfs_fini(struct amdgpu_device *adev) int amdgpu_discovery_get_mem_reserved_info_table(struct amdgpu_device *adev) { uint8_t *discovery_bin = adev->discovery.bin; + struct mem_reserved_info_header *mrhdr; + struct binary_header *bhdr; struct table_info *info; + u16 offset; /* If already queried, do not query again. */ if (adev->discovery.mem_reserved_table) @@ -2508,19 +2507,37 @@ int amdgpu_discovery_get_mem_reserved_info_table(struct amdgpu_device *adev) return -ENOENT; } + /* MEM_RESERVED_INFO only exists in binary_header >= v2. Skip populating it on v1 */ + bhdr = (struct binary_header *)discovery_bin; + if (le16_to_cpu(bhdr->version_major) < 2) { + dev_dbg(adev->dev, "header version = %d\n", le16_to_cpu(bhdr->version_major)); + return -ENOENT; + } + if (amdgpu_discovery_get_table_info(adev, &info, MEM_RESERVED_INFO)) { dev_dbg(adev->dev, "MEM_RESERVED_INFO table entry not present\n"); return -EINVAL; } - if (!le16_to_cpu(info->offset)) { + offset = le16_to_cpu(info->offset); + if (!offset) { dev_dbg(adev->dev, "MEM_RESERVED_INFO table offset is 0, invalid!\n"); return -EINVAL; } + /* + * Only populated when the signature matches; skip ASICs whose + * slot points to unrelated data. + */ + mrhdr = (struct mem_reserved_info_header *)(discovery_bin + offset); + if (le32_to_cpu(mrhdr->signature) != MEM_RSV_TABLE_SIGNATURE) { + dev_dbg(adev->dev, "MEM_RESERVED_INFO table signature mismatch, skipping\n"); + return -ENOENT; + } + /* Cache for subsequent lookups. */ adev->discovery.mem_reserved_table = - (struct mem_reserved_info_table_v1_0 *)(discovery_bin + le16_to_cpu(info->offset)); + (struct mem_reserved_info_table_v1_0 *)mrhdr; dev_dbg(adev->dev, "MEM_RESERVED_INFO table exist\n"); return 0; -- 2.55.0