[PATCH 5/7] drm/amdgpu: Fix VCRAT proximity domain mappings for GPU nodes
Donet Tom <[email protected]> Tue, 4 Aug 2026 15:22:34 +0530
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <93378702b915679811543bf162e9424ee02382a7.1785833981.git.donettom@linux.ibm.com> |
The VCRAT CPU builder, kfd_create_vcrat_image_cpu(), assigns proximity domains sequentially while iterating over for_each_online_node(). As a result, the first online node is assigned proximity domain 0, the second online node is assigned proximity domain 1, and so on. The GPU VCRAT builder creates GPU proximity domains after the CPU proximity domains and programs the GPU-to-CPU affinity (proximity_domain_to) using the NUMA node ID of the node to which the GPU is attached. This is only correct when NUMA node IDs are contiguous, because the CPU proximity domains happen to match the NUMA node IDs. On systems with discontiguous NUMA node IDs, the CPU proximity domains no longer correspond to the NUMA node IDs. For example: available: 3 nodes (0,2,4) Node IDs: 0 2 4 CPU proximity: 0 1 2 GPU proximity: 3 In this example, a GPU attached to NUMA node 4 is assigned GPU proximity domain 3. However, its proximity_domain_to field is programmed with the NUMA node ID (4) instead of the corresponding CPU proximity domain (2). During VCRAT parsing, no CPU proximity domain with value 4 exists, so the GPU affinity cannot be resolved and topology initialization fails: amdgpu: Virtual CRAT table created for GPU amdgpu: Error parsing VCRAT kfd: amdgpu: Error adding device to topology kfd: amdgpu: Error initializing KFD node Fix this by translating the GPU's NUMA node ID to the corresponding CPU proximity domain assigned during GPU VCRAT creation before programming proximity_domain_to. This ensures that GPU affinity entries always reference a valid CPU proximity domain, allowing VCRAT parsing and KFD topology initialization to succeed on systems with discontiguous NUMA node IDs. Signed-off-by: Donet Tom <[email protected]> --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 10 +++++++--- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_topology.h | 2 ++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 079bce6d904d..b38208965fc8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -1267,6 +1267,7 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink, iolink->recommended_transfer_size; dev->node_props.io_links_count++; + dev->numa_node = kfd_proximity_domain_to_numa_node(id_to); list_add_tail(&props->list, &dev->io_link_props); break; } @@ -1888,8 +1889,10 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size, sub_type_hdr->flags = CRAT_SUBTYPE_FLAGS_ENABLED; /* Fill in IO link data */ - sub_type_hdr->proximity_domain_from = numa_node_id; - sub_type_hdr->proximity_domain_to = nid; + sub_type_hdr->proximity_domain_from = + kfd_numa_node_to_proximity_domain(numa_node_id); + sub_type_hdr->proximity_domain_to = + kfd_numa_node_to_proximity_domain(nid); sub_type_hdr->io_interface_type = link_type; (*num_entries)++; @@ -2237,7 +2240,8 @@ static int kfd_fill_gpu_direct_io_link_to_cpu(int *avail_size, if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE) sub_type_hdr->proximity_domain_to = 0; else - sub_type_hdr->proximity_domain_to = kdev->adev->pdev->dev.numa_node; + sub_type_hdr->proximity_domain_to = + kfd_numa_node_to_proximity_domain(kdev->adev->pdev->dev.numa_node); #else sub_type_hdr->proximity_domain_to = 0; #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index f4b7cb44daff..d3269f0ffec3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -2463,3 +2463,25 @@ void kfd_update_svm_support_properties(struct amdgpu_device *adev) } up_write(&topology_lock); } + +int kfd_proximity_domain_to_numa_node(uint32_t proximity_domain) +{ + struct kfd_topology_device *dev; + + list_for_each_entry(dev, &topology_device_list, list) { + if (dev->proximity_domain == proximity_domain) + return dev->numa_node; + } + return -1; +} + +int kfd_numa_node_to_proximity_domain(int target_node) +{ + struct kfd_topology_device *dev; + + list_for_each_entry(dev, &topology_device_list, list) { + if (dev->numa_node == target_node) + return dev->proximity_domain; + } + return -1; +} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h index f5e00f5df922..312802754096 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h @@ -201,6 +201,8 @@ struct dmi_mem_device { struct kfd_topology_device *kfd_create_topology_device( struct list_head *device_list); void kfd_release_topology_device_list(struct list_head *device_list); +int kfd_numa_node_to_proximity_domain(int target_node); +int kfd_proximity_domain_to_numa_node(uint32_t proximity_domain); #if IS_ENABLED(CONFIG_HSA_AMD) void kfd_update_svm_support_properties(struct amdgpu_device *adev); -- 2.54.0