[PATCH 6/7] drm/amdgpu: Create proximity domains and VCRAT entries for CPU-less and memory-less NUMA nodes
Donet Tom <[email protected]> Tue, 4 Aug 2026 15:22:35 +0530
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <0b31dfae2fb95800d6b58683a4f1ea03a5545653.1785833981.git.donettom@linux.ibm.com> |
The current implementation creates proximity domains and the associated VCRAT entries only for NUMA nodes that contain CPUs. However, Linux systems can have CPU-less, memory-less, or CPU-less and memory-less NUMA nodes. When proximity domains and VCRAT entries are not created for these NUMA nodes, the generated VCRAT is incomplete and KFD topology initialization fails while parsing it. For example: available: 3 nodes (0,2-3) node 0 cpus: 0-39 node 0 size: 519305 MB node 2 cpus: node 2 size: 519305 MB node 3 cpus: node 3 size: With the current implementation, only node 0 is assigned a CPU proximity domain (domain 0). A GPU attached to NUMA node 3 is assigned GPU proximity domain 1, and its proximity_domain_to field references the CPU proximity domain corresponding to node 3. Since no CPU proximity domain exists for node 3, the referenced proximity domain is missing, causing VCRAT parsing to fail. Fix this by creating proximity domains and the corresponding VCRAT entries for all online NUMA nodes, including CPU-less and memory-less nodes. This ensures that every online NUMA node has a corresponding proximity domain, allowing GPU affinity information to be resolved correctly during VCRAT parsing. Signed-off-by: Donet Tom <[email protected]> --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 78 ++++++++++++++------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index b38208965fc8..df698109c17a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -1974,51 +1974,55 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size) sub_type_hdr = (struct crat_subtype_generic *)(crat_table+1); for_each_online_node(numa_node_id) { - if (kfd_numa_node_to_apic_id(numa_node_id) == -1) - continue; - - /* Fill in Subtype: Compute Unit */ - ret = kfd_fill_cu_for_cpu(numa_node_id, &avail_size, - crat_table->num_domains, - (struct crat_subtype_computeunit *)sub_type_hdr); - if (ret < 0) - return ret; - crat_table->length += sub_type_hdr->length; - crat_table->total_entries++; + int apic_id = kfd_numa_node_to_apic_id(numa_node_id); + int mem = node_state(numa_node_id, N_MEMORY); + + if (apic_id != -1) { + /* Fill in Subtype: Compute Unit */ + ret = kfd_fill_cu_for_cpu(numa_node_id, &avail_size, + crat_table->num_domains, + (struct crat_subtype_computeunit *)sub_type_hdr); + if (ret < 0) + return ret; + crat_table->length += sub_type_hdr->length; + crat_table->total_entries++; - sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + - sub_type_hdr->length); + sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + + sub_type_hdr->length); - /* Fill in Subtype: Memory */ - ret = kfd_fill_mem_info_for_cpu(numa_node_id, &avail_size, - crat_table->num_domains, - (struct crat_subtype_memory *)sub_type_hdr); - if (ret < 0) - return ret; - crat_table->length += sub_type_hdr->length; - crat_table->total_entries++; + /* Fill in Subtype: IO Link */ +#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) + ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size, + &entries, + (struct crat_subtype_iolink *)sub_type_hdr); + if (ret < 0) + return ret; - sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + - sub_type_hdr->length); + if (entries) { + crat_table->length += (sub_type_hdr->length * entries); + crat_table->total_entries += entries; - /* Fill in Subtype: IO Link */ -#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) - ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size, - &entries, - (struct crat_subtype_iolink *)sub_type_hdr); - if (ret < 0) - return ret; + sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + + sub_type_hdr->length * entries); + } +#else + pr_info("IO link not available for non x86 platforms\n"); +#endif + } - if (entries) { - crat_table->length += (sub_type_hdr->length * entries); - crat_table->total_entries += entries; + if (mem) { + /* Fill in Subtype: Memory */ + ret = kfd_fill_mem_info_for_cpu(numa_node_id, &avail_size, + crat_table->num_domains, + (struct crat_subtype_memory *)sub_type_hdr); + if (ret < 0) + return ret; + crat_table->length += sub_type_hdr->length; + crat_table->total_entries++; sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + - sub_type_hdr->length * entries); + sub_type_hdr->length); } -#else - pr_info("IO link not available for non x86 platforms\n"); -#endif ret = kfd_fill_numa_info_for_cpu(&avail_size, (struct crat_subtype_numa *)sub_type_hdr, -- 2.54.0