RE: [PATCH 3/3] drm/amdgpu: Use NPS ranges from discovery table

2024-05-14 Thread Zhang, Hawking
[AMD Official Use Only - AMD Internal Distribution Only]

Series is

Reviewed-by: Hawking Zhang 

Regards,
Hawking
-Original Message-
From: Lazar, Lijo 
Sent: Tuesday, May 14, 2024 16:36
To: amd-gfx@lists.freedesktop.org
Cc: Zhang, Hawking ; Deucher, Alexander 
; Koenig, Christian ; Ma, 
Le ; Ma, Le 
Subject: [PATCH 3/3] drm/amdgpu: Use NPS ranges from discovery table

Add GMC API to fetch NPS range information from discovery table. Use NPS range 
information in GMC 9.4.3 SOCs when available, otherwise fallback to software 
method.

Signed-off-by: Lijo Lazar 
Reviewed-by: Le Ma 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 92 +++  
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h |  5 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c   | 76 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h   | 11 +++
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 40 +---
 5 files changed, 212 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 43528ff50e72..afe8d12667f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -367,6 +367,35 @@ static void amdgpu_discovery_harvest_config_quirk(struct 
amdgpu_device *adev)
}
 }

+static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev,
+  struct binary_header *bhdr)
+{
+   struct table_info *info;
+   uint16_t checksum;
+   uint16_t offset;
+
+   info = >table_list[NPS_INFO];
+   offset = le16_to_cpu(info->offset);
+   checksum = le16_to_cpu(info->checksum);
+
+   struct nps_info_header *nhdr =
+   (struct nps_info_header *)(adev->mman.discovery_bin + offset);
+
+   if (le32_to_cpu(nhdr->table_id) != NPS_INFO_TABLE_ID) {
+   dev_dbg(adev->dev, "invalid ip discovery nps info table id\n");
+   return -EINVAL;
+   }
+
+   if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
+ le32_to_cpu(nhdr->size_bytes),
+ checksum)) {
+   dev_dbg(adev->dev, "invalid nps info data table checksum\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int amdgpu_discovery_init(struct amdgpu_device *adev)  {
struct table_info *info;
@@ -1681,6 +1710,69 @@ static int amdgpu_discovery_get_vcn_info(struct 
amdgpu_device *adev)
return 0;
 }

+union nps_info {
+   struct nps_info_v1_0 v1;
+};
+
+int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
+ uint32_t *nps_type,
+ struct amdgpu_gmc_memrange **ranges,
+ int *range_cnt)
+{
+   struct amdgpu_gmc_memrange *mem_ranges;
+   struct binary_header *bhdr;
+   union nps_info *nps_info;
+   u16 offset;
+   int i;
+
+   if (!nps_type || !range_cnt || !ranges)
+   return -EINVAL;
+
+   if (!adev->mman.discovery_bin) {
+   dev_err(adev->dev,
+   "fetch mem range failed, ip discovery uninitialized\n");
+   return -EINVAL;
+   }
+
+   bhdr = (struct binary_header *)adev->mman.discovery_bin;
+   offset = le16_to_cpu(bhdr->table_list[NPS_INFO].offset);
+
+   if (!offset)
+   return -ENOENT;
+
+   /* If verification fails, return as if NPS table doesn't exist */
+   if (amdgpu_discovery_verify_npsinfo(adev, bhdr))
+   return -ENOENT;
+
+   nps_info = (union nps_info *)(adev->mman.discovery_bin + offset);
+
+   switch (le16_to_cpu(nps_info->v1.header.version_major)) {
+   case 1:
+   *nps_type = nps_info->v1.nps_type;
+   *range_cnt = nps_info->v1.count;
+   mem_ranges = kvzalloc(
+   *range_cnt * sizeof(struct amdgpu_gmc_memrange),
+   GFP_KERNEL);
+   for (i = 0; i < *range_cnt; i++) {
+   mem_ranges[i].base_address =
+   nps_info->v1.instance_info[i].base_address;
+   mem_ranges[i].limit_address =
+   nps_info->v1.instance_info[i].limit_address;
+   mem_ranges[i].nid_mask = -1;
+   mem_ranges[i].flags = 0;
+   }
+   *ranges = mem_ranges;
+   break;
+   default:
+   dev_err(adev->dev, "Unhandled NPS info table %d.%d\n",
+   le16_to_cpu(nps_info->v1.header.version_major),
+   le16_to_cpu(nps_info->v1.header.version_minor));
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int amdgpu_di

[PATCH 3/3] drm/amdgpu: Use NPS ranges from discovery table

2024-05-14 Thread Lijo Lazar
Add GMC API to fetch NPS range information from discovery table. Use NPS
range information in GMC 9.4.3 SOCs when available, otherwise fallback
to software method.

Signed-off-by: Lijo Lazar 
Reviewed-by: Le Ma 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 92 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h |  5 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c   | 76 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h   | 11 +++
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 40 +---
 5 files changed, 212 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 43528ff50e72..afe8d12667f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -367,6 +367,35 @@ static void amdgpu_discovery_harvest_config_quirk(struct 
amdgpu_device *adev)
}
 }
 
+static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev,
+  struct binary_header *bhdr)
+{
+   struct table_info *info;
+   uint16_t checksum;
+   uint16_t offset;
+
+   info = >table_list[NPS_INFO];
+   offset = le16_to_cpu(info->offset);
+   checksum = le16_to_cpu(info->checksum);
+
+   struct nps_info_header *nhdr =
+   (struct nps_info_header *)(adev->mman.discovery_bin + offset);
+
+   if (le32_to_cpu(nhdr->table_id) != NPS_INFO_TABLE_ID) {
+   dev_dbg(adev->dev, "invalid ip discovery nps info table id\n");
+   return -EINVAL;
+   }
+
+   if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset,
+ le32_to_cpu(nhdr->size_bytes),
+ checksum)) {
+   dev_dbg(adev->dev, "invalid nps info data table checksum\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int amdgpu_discovery_init(struct amdgpu_device *adev)
 {
struct table_info *info;
@@ -1681,6 +1710,69 @@ static int amdgpu_discovery_get_vcn_info(struct 
amdgpu_device *adev)
return 0;
 }
 
+union nps_info {
+   struct nps_info_v1_0 v1;
+};
+
+int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
+ uint32_t *nps_type,
+ struct amdgpu_gmc_memrange **ranges,
+ int *range_cnt)
+{
+   struct amdgpu_gmc_memrange *mem_ranges;
+   struct binary_header *bhdr;
+   union nps_info *nps_info;
+   u16 offset;
+   int i;
+
+   if (!nps_type || !range_cnt || !ranges)
+   return -EINVAL;
+
+   if (!adev->mman.discovery_bin) {
+   dev_err(adev->dev,
+   "fetch mem range failed, ip discovery uninitialized\n");
+   return -EINVAL;
+   }
+
+   bhdr = (struct binary_header *)adev->mman.discovery_bin;
+   offset = le16_to_cpu(bhdr->table_list[NPS_INFO].offset);
+
+   if (!offset)
+   return -ENOENT;
+
+   /* If verification fails, return as if NPS table doesn't exist */
+   if (amdgpu_discovery_verify_npsinfo(adev, bhdr))
+   return -ENOENT;
+
+   nps_info = (union nps_info *)(adev->mman.discovery_bin + offset);
+
+   switch (le16_to_cpu(nps_info->v1.header.version_major)) {
+   case 1:
+   *nps_type = nps_info->v1.nps_type;
+   *range_cnt = nps_info->v1.count;
+   mem_ranges = kvzalloc(
+   *range_cnt * sizeof(struct amdgpu_gmc_memrange),
+   GFP_KERNEL);
+   for (i = 0; i < *range_cnt; i++) {
+   mem_ranges[i].base_address =
+   nps_info->v1.instance_info[i].base_address;
+   mem_ranges[i].limit_address =
+   nps_info->v1.instance_info[i].limit_address;
+   mem_ranges[i].nid_mask = -1;
+   mem_ranges[i].flags = 0;
+   }
+   *ranges = mem_ranges;
+   break;
+   default:
+   dev_err(adev->dev, "Unhandled NPS info table %d.%d\n",
+   le16_to_cpu(nps_info->v1.header.version_major),
+   le16_to_cpu(nps_info->v1.header.version_minor));
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
 {
/* what IP to use for this? */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
index 4d03cd5b3410..f5d36525ec3e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
@@ -30,4 +30,9 @@
 void amdgpu_discovery_fini(struct amdgpu_device *adev);
 int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev);