* [PATCH v3 1/2] drm/amdkfd: Remove unused code in CRAT initialization
2026-10-30 8:33 [PATCH v3 0/2] drm/amdkfd: Add support for discontiguous and CPU-less NUMA topologies Dhruv B
@ 2026-10-30 8:33 ` Dhruv B
2026-10-30 8:33 ` [PATCH v3 2/2] drm/amdkfd: Add support for discontiguous and CPU-less NUMA topologies Dhruv B
1 sibling, 0 replies; 3+ messages in thread
From: Dhruv B @ 2026-10-30 8:33 UTC (permalink / raw)
To: amd-gfx, Felix Kuehling, Alex Deucher, Alex Deucher,
Christian König, Philip Yang
Cc: David.YatSin, Kent.Russell, Ritesh Harjani,
Vaidyanathan Srinivasan, David Airlie, Simona Vetter, donettom,
dhruv.b, Felix Kuehling
The 'size' argument in kfd_create_crat_image_virtual() is not used
by callers to retrieve the allocated CRAT image size. The callers
rely solely on the returned image pointer and inspect the parsed CRAT
table header directly for entry counts and lengths.
Additionally, in kfd_topology_init(), the 'kdev' pointer assignment
via list_first_entry() after parsing the CPU CRAT table is not being
used and can be removed.
Clean up the function signature of kfd_create_crat_image_virtual() by
dropping the unused 'size' parameter, manage the buffer size locally,
and remove the unused variable assignments in kfd_topology_init().
Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
Co-developed-by: Donet Tom <donettom@linux.ibm.com>
Signed-off-by: Donet Tom <donettom@linux.ibm.com>
Signed-off-by: Dhruv B <dhruv.b@linux.ibm.com>
---
drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 10 ++++------
drivers/gpu/drm/amd/amdkfd/kfd_crat.h | 2 +-
drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 11 ++---------
3 files changed, 7 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 6e0df685503d..99b0c7f825fe 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -2411,7 +2411,6 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
*
* @crat_image: VCRAT image created because ACPI does not have a
* CRAT for this device
- * @size: [OUT] size of virtual crat_image
* @flags: COMPUTE_UNIT_CPU - Create VCRAT for CPU device
* COMPUTE_UNIT_GPU - Create VCRAT for GPU
* (COMPUTE_UNIT_CPU | COMPUTE_UNIT_GPU) - Create VCRAT for APU
@@ -2421,7 +2420,7 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
*
* Return 0 if successful else return -ve value
*/
-int kfd_create_crat_image_virtual(void **crat_image, size_t *size,
+int kfd_create_crat_image_virtual(void **crat_image,
int flags, struct kfd_node *kdev,
uint32_t proximity_domain)
{
@@ -2449,9 +2448,8 @@ int kfd_create_crat_image_virtual(void **crat_image, size_t *size,
pcrat_image = kvmalloc(dyn_size, GFP_KERNEL);
if (!pcrat_image)
return -ENOMEM;
- *size = dyn_size;
pr_debug("CRAT size is %ld", dyn_size);
- ret = kfd_create_vcrat_image_cpu(pcrat_image, size);
+ ret = kfd_create_vcrat_image_cpu(pcrat_image, &dyn_size);
break;
case COMPUTE_UNIT_GPU:
if (!kdev)
@@ -2459,8 +2457,8 @@ int kfd_create_crat_image_virtual(void **crat_image, size_t *size,
pcrat_image = kvmalloc(VCRAT_SIZE_FOR_GPU, GFP_KERNEL);
if (!pcrat_image)
return -ENOMEM;
- *size = VCRAT_SIZE_FOR_GPU;
- ret = kfd_create_vcrat_image_gpu(pcrat_image, size, kdev,
+ dyn_size = VCRAT_SIZE_FOR_GPU;
+ ret = kfd_create_vcrat_image_gpu(pcrat_image, &dyn_size, kdev,
proximity_domain);
break;
case (COMPUTE_UNIT_CPU | COMPUTE_UNIT_GPU):
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
index a8ca7ecb6d27..418a3939eda3 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
@@ -313,7 +313,7 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
void kfd_destroy_crat_image(void *crat_image);
int kfd_parse_crat_table(void *crat_image, struct list_head *device_list,
uint32_t proximity_domain);
-int kfd_create_crat_image_virtual(void **crat_image, size_t *size,
+int kfd_create_crat_image_virtual(void **crat_image,
int flags, struct kfd_node *kdev,
uint32_t proximity_domain);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 35b3abe57b80..b38d12f3da84 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -996,7 +996,6 @@ static void kfd_add_non_crat_information(struct kfd_topology_device *kdev)
int kfd_topology_init(void)
{
void *crat_image = NULL;
- size_t image_size = 0;
int ret;
struct list_head temp_topology_device_list;
int cpu_only_node = 0;
@@ -1023,8 +1022,7 @@ int kfd_topology_init(void)
*/
proximity_domain = 0;
- ret = kfd_create_crat_image_virtual(&crat_image, &image_size,
- COMPUTE_UNIT_CPU, NULL,
+ ret = kfd_create_crat_image_virtual(&crat_image, COMPUTE_UNIT_CPU, NULL,
proximity_domain);
cpu_only_node = 1;
if (ret) {
@@ -1040,9 +1038,6 @@ int kfd_topology_init(void)
goto err;
}
- kdev = list_first_entry(&temp_topology_device_list,
- struct kfd_topology_device, list);
-
down_write(&topology_lock);
kfd_topology_update_device_list(&temp_topology_device_list,
&topology_device_list);
@@ -1871,11 +1866,9 @@ static int kfd_topology_add_device_locked(struct kfd_node *gpu,
int proximity_domain = ++topology_crat_proximity_domain;
struct list_head temp_topology_device_list;
void *crat_image = NULL;
- size_t image_size = 0;
int res;
- res = kfd_create_crat_image_virtual(&crat_image, &image_size,
- COMPUTE_UNIT_GPU, gpu,
+ res = kfd_create_crat_image_virtual(&crat_image, COMPUTE_UNIT_GPU, gpu,
proximity_domain);
if (res) {
dev_err(gpu->adev->dev, "Error creating VCRAT\n");
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH v3 2/2] drm/amdkfd: Add support for discontiguous and CPU-less NUMA topologies
2026-10-30 8:33 [PATCH v3 0/2] drm/amdkfd: Add support for discontiguous and CPU-less NUMA topologies Dhruv B
2026-10-30 8:33 ` [PATCH v3 1/2] drm/amdkfd: Remove unused code in CRAT initialization Dhruv B
@ 2026-10-30 8:33 ` Dhruv B
1 sibling, 0 replies; 3+ messages in thread
From: Dhruv B @ 2026-10-30 8:33 UTC (permalink / raw)
To: amd-gfx, Felix Kuehling, Alex Deucher, Alex Deucher,
Christian König, Philip Yang
Cc: David.YatSin, Kent.Russell, Ritesh Harjani,
Vaidyanathan Srinivasan, David Airlie, Simona Vetter, donettom,
dhruv.b
On systems with discontiguous NUMA node IDs, the GPU driver fails to
load with the following errors:
[ 5.609767] amdgpu 0038:12:00.0: Error parsing VCRAT
[ 5.609781] kfd kfd: Error adding device to topology
[ 5.609848] kfd kfd: Error initializing KFD node
In the current KFD code, proximity domains are created contiguously
when generating the VCRAT. With discontiguous NUMA node IDs, this
creates a mismatch between the proximity domain ID and the NUMA node ID.
For example, if NUMA nodes 0, 2 and 3 are online, the current code
assigns proximity domains 0, 1 and 2 to these nodes respectively,
instead of domains 0, 2 and 3.
The KFD topology uses the NUMA node and proximity domain information to
create topology devices representing the CPU and memory resources
associated with each NUMA node. This topology is exposed to userspace
through sysfs, where the NUMA node and proximity domain information are
used to identify the topology devices. The mismatch between the NUMA
node ID and proximity domain therefore results in an inconsistent KFD
topology and causes topology parsing to fail.
Make the proximity domain ID correspond directly to the NUMA node ID by
iterating through the complete NUMA node ID range up to the last online
node. Account for every node ID when assigning proximity domains, while
skipping resource entry creation for offline nodes. This preserves the
NUMA-node-to-proximity-domain mapping and allows the KFD topology and
its sysfs representation to correctly reflect discontiguous NUMA
topologies.
A NUMA node may also be CPU-less, memory-less, or both. Only create a
Compute Unit CRAT entry if the node has CPUs, and only create a Memory
CRAT entry if the node has memory.
Additionally, update kfd_parse_subtype_mem() to use simd_count instead
of cpu_cores_count to distinguish host nodes from GPU nodes. This ensures
that memory on CPU-less host NUMA nodes is correctly classified as
system memory (HSA_MEM_HEAP_TYPE_SYSTEM) rather than private GPU
framebuffer memory.
The placeholder domains created for offline node IDs have no IO links,
so skip offline and CPU-less nodes when building the indirect GPU to CPU
links.
Co-developed-by: Donet Tom <donettom@linux.ibm.com>
Signed-off-by: Donet Tom <donettom@linux.ibm.com>
Signed-off-by: Dhruv B <dhruv.b@linux.ibm.com>
---
drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 59 +++++++++++++----------
drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 3 ++
2 files changed, 36 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 99b0c7f825fe..bebbc6715b2f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1103,8 +1103,10 @@ static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem,
mem->proximity_domain);
list_for_each_entry(dev, device_list, list) {
if (mem->proximity_domain == dev->proximity_domain) {
- /* We're on GPU node */
- if (dev->node_props.cpu_cores_count == 0) {
+ if (dev->node_props.simd_count == 0) {
+ heap_type = HSA_MEM_HEAP_TYPE_SYSTEM;
+ } else {
+ /* We're on GPU node */
/* APU */
if (mem->visibility_type == 0)
heap_type =
@@ -1112,8 +1114,7 @@ static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem,
/* dGPU */
else
heap_type = mem->visibility_type;
- } else
- heap_type = HSA_MEM_HEAP_TYPE_SYSTEM;
+ }
if (mem->flags & CRAT_MEM_FLAGS_HOT_PLUGGABLE)
flags |= HSA_MEM_FLAGS_HOT_PLUGGABLE;
@@ -1899,7 +1900,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
acpi_status status;
struct crat_subtype_generic *sub_type_hdr;
int avail_size = *size;
- int numa_node_id;
+ int numa_node_id, last_node;
#if defined(CONFIG_X86_64) && !defined(CONFIG_UML)
uint32_t entries = 0;
#endif
@@ -1935,34 +1936,41 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
crat_table->num_domains = 0;
sub_type_hdr = (struct crat_subtype_generic *)(crat_table+1);
+ last_node = find_last_bit(node_online_map.bits, MAX_NUMNODES);
- for_each_online_node(numa_node_id) {
- if (kfd_numa_node_to_apic_id(numa_node_id) == -1)
+ for (numa_node_id = 0; numa_node_id <= last_node; numa_node_id++) {
+ if (!node_online(numa_node_id)) {
+ crat_table->num_domains++;
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++;
+ if (kfd_numa_node_to_apic_id(numa_node_id) != -1) {
+ 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++;
+ if (node_state(numa_node_id, N_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);
+ sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
+ sub_type_hdr->length);
+ }
/* Fill in Subtype: IO Link */
#if defined(CONFIG_X86_64) && !defined(CONFIG_UML)
@@ -1982,7 +1990,6 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
#else
pr_info("IO link not available for non x86 platforms\n");
#endif
-
crat_table->num_domains++;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index b38d12f3da84..d2fbe73e57ef 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -1419,6 +1419,9 @@ static int kfd_create_indirect_link_prop(struct kfd_topology_device *kdev, int g
struct kfd_iolink_properties, list);
for (i = 0; i < num_cpu; i++) {
+ if (!node_online(i) || !node_state(i, N_CPU))
+ continue;
+
/* CPU <--> GPU */
if (gpu_link->node_to == i)
continue;
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread