AMD-GFX Archive mirror
 help / color / mirror / Atom feed
From: "Zhang, Hawking" <Hawking.Zhang@amd.com>
To: "Lazar, Lijo" <Lijo.Lazar@amd.com>,
	"amd-gfx@lists.freedesktop.org" <amd-gfx@lists.freedesktop.org>
Cc: "Deucher, Alexander" <Alexander.Deucher@amd.com>,
	"Koenig, Christian" <Christian.Koenig@amd.com>,
	"Ma, Le" <Le.Ma@amd.com>, "Ma, Le" <Le.Ma@amd.com>
Subject: RE: [PATCH 3/3] drm/amdgpu: Use NPS ranges from discovery table
Date: Tue, 14 May 2024 10:08:06 +0000	[thread overview]
Message-ID: <BN9PR12MB52579B1ADE566FFC3E0D0E2FFCE32@BN9PR12MB5257.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20240514083626.378626-3-lijo.lazar@amd.com>

[AMD Official Use Only - AMD Internal Distribution Only]

Series is

Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>

Regards,
Hawking
-----Original Message-----
From: Lazar, Lijo <Lijo.Lazar@amd.com>
Sent: Tuesday, May 14, 2024 16:36
To: amd-gfx@lists.freedesktop.org
Cc: Zhang, Hawking <Hawking.Zhang@amd.com>; Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian <Christian.Koenig@amd.com>; Ma, Le <Le.Ma@amd.com>; Ma, Le <Le.Ma@amd.com>
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 <lijo.lazar@amd.com>
Reviewed-by: Le Ma <le.ma@amd.com>
---
 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 = &bhdr->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);

+int amdgpu_discovery_get_nps_info(struct amdgpu_device *adev,
+                                 uint32_t *nps_type,
+                                 struct amdgpu_gmc_memrange **ranges,
+                                 int *range_cnt);
+
 #endif /* __AMDGPU_DISCOVERY__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index f8ed886ffca3..78cd31e929c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -1165,3 +1165,79 @@ void amdgpu_gmc_sysfs_fini(struct amdgpu_device *adev)  {
        device_remove_file(adev->dev, &dev_attr_current_memory_partition);
 }
+
+int amdgpu_gmc_get_nps_memranges(struct amdgpu_device *adev,
+                                struct amdgpu_mem_partition_info *mem_ranges,
+                                int exp_ranges)
+{
+       struct amdgpu_gmc_memrange *ranges;
+       int range_cnt, ret, i, j;
+       uint32_t nps_type;
+
+       if (!mem_ranges)
+               return -EINVAL;
+
+       ret = amdgpu_discovery_get_nps_info(adev, &nps_type, &ranges,
+                                           &range_cnt);
+
+       if (ret)
+               return ret;
+
+       /* TODO: For now, expect ranges and partition count to be the same.
+        * Adjust if there are holes expected in any NPS domain.
+        */
+       if (range_cnt != exp_ranges) {
+               dev_warn(
+                       adev->dev,
+                       "NPS config mismatch - expected ranges: %d discovery - nps mode: %d, nps ranges: %d",
+                       exp_ranges, nps_type, range_cnt);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       for (i = 0; i < exp_ranges; ++i) {
+               if (ranges[i].base_address >= ranges[i].limit_address) {
+                       dev_warn(
+                               adev->dev,
+                               "Invalid NPS range - nps mode: %d, range[%d]: base: %llx limit: %llx",
+                               nps_type, i, ranges[i].base_address,
+                               ranges[i].limit_address);
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               /* Check for overlaps, not expecting any now */
+               for (j = i - 1; j >= 0; j--) {
+                       if (max(ranges[j].base_address,
+                               ranges[i].base_address) <=
+                           min(ranges[j].limit_address,
+                               ranges[i].limit_address)) {
+                               dev_warn(
+                                       adev->dev,
+                                       "overlapping ranges detected [ %llx - %llx ] | [%llx - %llx]",
+                                       ranges[j].base_address,
+                                       ranges[j].limit_address,
+                                       ranges[i].base_address,
+                                       ranges[i].limit_address);
+                               ret = -EINVAL;
+                               goto err;
+                       }
+               }
+
+               mem_ranges[i].range.fpfn =
+                       (ranges[i].base_address -
+                        adev->vm_manager.vram_base_offset) >>
+                       AMDGPU_GPU_PAGE_SHIFT;
+               mem_ranges[i].range.lpfn =
+                       (ranges[i].limit_address -
+                        adev->vm_manager.vram_base_offset) >>
+                       AMDGPU_GPU_PAGE_SHIFT;
+               mem_ranges[i].size =
+                       ranges[i].limit_address - ranges[i].base_address + 1;
+       }
+
+err:
+       kfree(ranges);
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
index 17f40ea1104b..febca3130497 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -199,6 +199,13 @@ struct amdgpu_mem_partition_info {

 #define INVALID_PFN    -1

+struct amdgpu_gmc_memrange {
+       uint64_t base_address;
+       uint64_t limit_address;
+       uint32_t flags;
+       int nid_mask;
+};
+
 enum amdgpu_gart_placement {
        AMDGPU_GART_PLACEMENT_BEST_FIT = 0,
        AMDGPU_GART_PLACEMENT_HIGH,
@@ -439,4 +446,8 @@ int amdgpu_gmc_vram_checking(struct amdgpu_device *adev);  int amdgpu_gmc_sysfs_init(struct amdgpu_device *adev);  void amdgpu_gmc_sysfs_fini(struct amdgpu_device *adev);

+int amdgpu_gmc_get_nps_memranges(struct amdgpu_device *adev,
+                                struct amdgpu_mem_partition_info *mem_ranges,
+                                int exp_ranges);
+
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 7c4e2adae7b3..094c08cb98e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1895,7 +1895,7 @@ gmc_v9_0_init_sw_mem_ranges(struct amdgpu_device *adev,  {
        enum amdgpu_memory_partition mode;
        u32 start_addr = 0, size;
-       int i;
+       int i, r, l;

        mode = gmc_v9_0_query_memory_partition(adev);

@@ -1918,23 +1918,39 @@ gmc_v9_0_init_sw_mem_ranges(struct amdgpu_device *adev,
                break;
        }

-       size = (adev->gmc.real_vram_size + SZ_16M) >> AMDGPU_GPU_PAGE_SHIFT;
-       size /= adev->gmc.num_mem_partitions;
+       /* Use NPS range info, if populated */
+       r = amdgpu_gmc_get_nps_memranges(adev, mem_ranges,
+                                        adev->gmc.num_mem_partitions);
+       if (!r) {
+               l = 0;
+               for (i = 1; i < adev->gmc.num_mem_partitions; ++i) {
+                       if (mem_ranges[i].range.lpfn >
+                           mem_ranges[i - 1].range.lpfn)
+                               l = i;
+               }
+
+       } else {
+               /* Fallback to sw based calculation */
+               size = (adev->gmc.real_vram_size + SZ_16M) >> AMDGPU_GPU_PAGE_SHIFT;
+               size /= adev->gmc.num_mem_partitions;
+
+               for (i = 0; i < adev->gmc.num_mem_partitions; ++i) {
+                       mem_ranges[i].range.fpfn = start_addr;
+                       mem_ranges[i].size =
+                               ((u64)size << AMDGPU_GPU_PAGE_SHIFT);
+                       mem_ranges[i].range.lpfn = start_addr + size - 1;
+                       start_addr += size;
+               }

-       for (i = 0; i < adev->gmc.num_mem_partitions; ++i) {
-               mem_ranges[i].range.fpfn = start_addr;
-               mem_ranges[i].size = ((u64)size << AMDGPU_GPU_PAGE_SHIFT);
-               mem_ranges[i].range.lpfn = start_addr + size - 1;
-               start_addr += size;
+               l = adev->gmc.num_mem_partitions - 1;
        }

        /* Adjust the last one */
-       mem_ranges[adev->gmc.num_mem_partitions - 1].range.lpfn =
+       mem_ranges[l].range.lpfn =
                (adev->gmc.real_vram_size >> AMDGPU_GPU_PAGE_SHIFT) - 1;
-       mem_ranges[adev->gmc.num_mem_partitions - 1].size =
+       mem_ranges[l].size =
                adev->gmc.real_vram_size -
-               ((u64)mem_ranges[adev->gmc.num_mem_partitions - 1].range.fpfn
-                << AMDGPU_GPU_PAGE_SHIFT);
+               ((u64)mem_ranges[l].range.fpfn << AMDGPU_GPU_PAGE_SHIFT);
 }

 static int gmc_v9_0_init_mem_ranges(struct amdgpu_device *adev)
--
2.25.1


      reply	other threads:[~2024-05-14 10:08 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-14  8:36 [PATCH 1/3] drm/amdgpu: Fix memory range calculation Lijo Lazar
2024-05-14  8:36 ` [PATCH 2/3] drm/amdgpu: Add nps info table to IP discovery Lijo Lazar
2024-05-14  8:36 ` [PATCH 3/3] drm/amdgpu: Use NPS ranges from discovery table Lijo Lazar
2024-05-14 10:08   ` Zhang, Hawking [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BN9PR12MB52579B1ADE566FFC3E0D0E2FFCE32@BN9PR12MB5257.namprd12.prod.outlook.com \
    --to=hawking.zhang@amd.com \
    --cc=Alexander.Deucher@amd.com \
    --cc=Christian.Koenig@amd.com \
    --cc=Le.Ma@amd.com \
    --cc=Lijo.Lazar@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).