[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.