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

Reply via email to