diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3420-drm-amdkfd-Decouple-CRAT-parsing-from-device-list-up.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3420-drm-amdkfd-Decouple-CRAT-parsing-from-device-list-up.patch | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3420-drm-amdkfd-Decouple-CRAT-parsing-from-device-list-up.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3420-drm-amdkfd-Decouple-CRAT-parsing-from-device-list-up.patch new file mode 100644 index 00000000..9308efa3 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3420-drm-amdkfd-Decouple-CRAT-parsing-from-device-list-up.patch @@ -0,0 +1,554 @@ +From f9517f06efd717aef12fd23f667c82af472bb084 Mon Sep 17 00:00:00 2001 +From: Harish Kasiviswanathan <harish.kasiviswanathan@amd.com> +Date: Fri, 8 Dec 2017 23:08:52 -0500 +Subject: [PATCH 3420/4131] drm/amdkfd: Decouple CRAT parsing from device list + update + +Currently, CRAT parsing is intertwined with topology_device_list and +hence repeated calls to kfd_parse_crat_table() will fail. Decouple +kfd_parse_crat_table() and topology_device_list. + +kfd_parse_crat_table() will parse CRAT and add topology devices to a +temporary list temp_topology_device_list and then +kfd_topology_update_device_list will move contents from temporary list to +master list. + +Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com> +Signed-off-by: Kent Russell <kent.russell@amd.com> +Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> +Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com> +Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com> +--- + drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 118 +++++++++++++++++------------- + drivers/gpu/drm/amd/amdkfd/kfd_crat.h | 3 +- + drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 84 ++++++++++++++------- + drivers/gpu/drm/amd/amdkfd/kfd_topology.h | 6 +- + 4 files changed, 132 insertions(+), 79 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +index aa754c1..bae91fd 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +@@ -23,8 +23,6 @@ + #include "kfd_crat.h" + #include "kfd_topology.h" + +-static int topology_crat_parsed; +-extern struct list_head topology_device_list; + extern struct kfd_system_properties sys_props; + + static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev, +@@ -57,16 +55,18 @@ static void kfd_populated_cu_info_gpu(struct kfd_topology_device *dev, + pr_info("CU GPU: id_base=%d\n", cu->processor_id_low); + } + +-/* kfd_parse_subtype_cu is called when the topology mutex is already acquired */ +-static int kfd_parse_subtype_cu(struct crat_subtype_computeunit *cu) ++/* kfd_parse_subtype_cu - parse compute unit subtypes and attach it to correct ++ * topology device present in the device_list ++ */ ++static int kfd_parse_subtype_cu(struct crat_subtype_computeunit *cu, ++ struct list_head *device_list) + { + struct kfd_topology_device *dev; +- int i = 0; + + pr_info("Found CU entry in CRAT table with proximity_domain=%d caps=%x\n", + cu->proximity_domain, cu->hsa_capability); +- list_for_each_entry(dev, &topology_device_list, list) { +- if (cu->proximity_domain == i) { ++ list_for_each_entry(dev, device_list, list) { ++ if (cu->proximity_domain == dev->proximity_domain) { + if (cu->flags & CRAT_CU_FLAGS_CPU_PRESENT) + kfd_populated_cu_info_cpu(dev, cu); + +@@ -74,26 +74,24 @@ static int kfd_parse_subtype_cu(struct crat_subtype_computeunit *cu) + kfd_populated_cu_info_gpu(dev, cu); + break; + } +- i++; + } + + return 0; + } + +-/* +- * kfd_parse_subtype_mem is called when the topology mutex is +- * already acquired ++/* kfd_parse_subtype_mem - parse memory subtypes and attach it to correct ++ * topology device present in the device_list + */ +-static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem) ++static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem, ++ struct list_head *device_list) + { + struct kfd_mem_properties *props; + struct kfd_topology_device *dev; +- int i = 0; + + pr_info("Found memory entry in CRAT table with proximity_domain=%d\n", + mem->proximity_domain); +- list_for_each_entry(dev, &topology_device_list, list) { +- if (mem->proximity_domain == i) { ++ list_for_each_entry(dev, device_list, list) { ++ if (mem->proximity_domain == dev->proximity_domain) { + props = kfd_alloc_struct(props); + if (!props) + return -ENOMEM; +@@ -118,17 +116,16 @@ static int kfd_parse_subtype_mem(struct crat_subtype_memory *mem) + + break; + } +- i++; + } + + return 0; + } + +-/* +- * kfd_parse_subtype_cache is called when the topology mutex +- * is already acquired ++/* kfd_parse_subtype_cache - parse cache subtypes and attach it to correct ++ * topology device present in the device_list + */ +-static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache) ++static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache, ++ struct list_head *device_list) + { + struct kfd_cache_properties *props; + struct kfd_topology_device *dev; +@@ -137,7 +134,7 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache) + id = cache->processor_id_low; + + pr_info("Found cache entry in CRAT table with processor_id=%d\n", id); +- list_for_each_entry(dev, &topology_device_list, list) ++ list_for_each_entry(dev, device_list, list) + if (id == dev->node_props.cpu_core_id_base || + id == dev->node_props.simd_id_base) { + props = kfd_alloc_struct(props); +@@ -171,15 +168,14 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache) + return 0; + } + +-/* +- * kfd_parse_subtype_iolink is called when the topology mutex +- * is already acquired ++/* kfd_parse_subtype_iolink - parse iolink subtypes and attach it to correct ++ * topology device present in the device_list + */ +-static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink) ++static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink, ++ struct list_head *device_list) + { + struct kfd_iolink_properties *props; + struct kfd_topology_device *dev; +- uint32_t i = 0; + uint32_t id_from; + uint32_t id_to; + +@@ -187,8 +183,8 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink) + id_to = iolink->proximity_domain_to; + + pr_info("Found IO link entry in CRAT table with id_from=%d\n", id_from); +- list_for_each_entry(dev, &topology_device_list, list) { +- if (id_from == i) { ++ list_for_each_entry(dev, device_list, list) { ++ if (id_from == dev->proximity_domain) { + props = kfd_alloc_struct(props); + if (!props) + return -ENOMEM; +@@ -216,13 +212,18 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink) + + break; + } +- i++; + } + + return 0; + } + +-static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr) ++/* kfd_parse_subtype - parse subtypes and attach it to correct topology device ++ * present in the device_list ++ * @sub_type_hdr - subtype section of crat_image ++ * @device_list - list of topology devices present in this crat_image ++ */ ++static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr, ++ struct list_head *device_list) + { + struct crat_subtype_computeunit *cu; + struct crat_subtype_memory *mem; +@@ -233,15 +234,15 @@ static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr) + switch (sub_type_hdr->type) { + case CRAT_SUBTYPE_COMPUTEUNIT_AFFINITY: + cu = (struct crat_subtype_computeunit *)sub_type_hdr; +- ret = kfd_parse_subtype_cu(cu); ++ ret = kfd_parse_subtype_cu(cu, device_list); + break; + case CRAT_SUBTYPE_MEMORY_AFFINITY: + mem = (struct crat_subtype_memory *)sub_type_hdr; +- ret = kfd_parse_subtype_mem(mem); ++ ret = kfd_parse_subtype_mem(mem, device_list); + break; + case CRAT_SUBTYPE_CACHE_AFFINITY: + cache = (struct crat_subtype_cache *)sub_type_hdr; +- ret = kfd_parse_subtype_cache(cache); ++ ret = kfd_parse_subtype_cache(cache, device_list); + break; + case CRAT_SUBTYPE_TLB_AFFINITY: + /* +@@ -257,7 +258,7 @@ static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr) + break; + case CRAT_SUBTYPE_IOLINK_AFFINITY: + iolink = (struct crat_subtype_iolink *)sub_type_hdr; +- ret = kfd_parse_subtype_iolink(iolink); ++ ret = kfd_parse_subtype_iolink(iolink, device_list); + break; + default: + pr_warn("Unknown subtype %d in CRAT\n", +@@ -267,12 +268,23 @@ static int kfd_parse_subtype(struct crat_subtype_generic *sub_type_hdr) + return ret; + } + +-int kfd_parse_crat_table(void *crat_image) ++/* kfd_parse_crat_table - parse CRAT table. For each node present in CRAT ++ * create a kfd_topology_device and add in to device_list. Also parse ++ * CRAT subtypes and attach it to appropriate kfd_topology_device ++ * @crat_image - input image containing CRAT ++ * @device_list - [OUT] list of kfd_topology_device generated after ++ * parsing crat_image ++ * @proximity_domain - Proximity domain of the first device in the table ++ * ++ * Return - 0 if successful else -ve value ++ */ ++int kfd_parse_crat_table(void *crat_image, struct list_head *device_list, ++ uint32_t proximity_domain) + { + struct kfd_topology_device *top_dev; + struct crat_subtype_generic *sub_type_hdr; + uint16_t node_id; +- int ret; ++ int ret = 0; + struct crat_header *crat_table = (struct crat_header *)crat_image; + uint16_t num_nodes; + uint32_t image_len; +@@ -280,17 +292,26 @@ int kfd_parse_crat_table(void *crat_image) + if (!crat_image) + return -EINVAL; + ++ if (!list_empty(device_list)) { ++ pr_warn("Error device list should be empty\n"); ++ return -EINVAL; ++ } ++ + num_nodes = crat_table->num_domains; + image_len = crat_table->length; + + pr_info("Parsing CRAT table with %d nodes\n", num_nodes); + + for (node_id = 0; node_id < num_nodes; node_id++) { +- top_dev = kfd_create_topology_device(); +- if (!top_dev) { +- kfd_release_live_view(); +- return -ENOMEM; +- } ++ top_dev = kfd_create_topology_device(device_list); ++ if (!top_dev) ++ break; ++ top_dev->proximity_domain = proximity_domain++; ++ } ++ ++ if (!top_dev) { ++ ret = -ENOMEM; ++ goto err; + } + + sys_props.platform_id = +@@ -302,21 +323,20 @@ int kfd_parse_crat_table(void *crat_image) + while ((char *)sub_type_hdr + sizeof(struct crat_subtype_generic) < + ((char *)crat_image) + image_len) { + if (sub_type_hdr->flags & CRAT_SUBTYPE_FLAGS_ENABLED) { +- ret = kfd_parse_subtype(sub_type_hdr); +- if (ret != 0) { +- kfd_release_live_view(); +- return ret; +- } ++ ret = kfd_parse_subtype(sub_type_hdr, device_list); ++ if (ret) ++ break; + } + + sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr + + sub_type_hdr->length); + } + +- sys_props.generation_count++; +- topology_crat_parsed = 1; ++err: ++ if (ret) ++ kfd_release_topology_device_list(device_list); + +- return 0; ++ return ret; + } + + /* +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h +index da83105..4e683ae 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h +@@ -293,6 +293,7 @@ struct cdit_header { + + int kfd_create_crat_image_acpi(void **crat_image, size_t *size); + void kfd_destroy_crat_image(void *crat_image); +-int kfd_parse_crat_table(void *crat_image); ++int kfd_parse_crat_table(void *crat_image, struct list_head *device_list, ++ uint32_t proximity_domain); + + #endif /* KFD_CRAT_H_INCLUDED */ +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +index 35da4af..f64350b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +@@ -34,7 +34,8 @@ + #include "kfd_topology.h" + #include "kfd_device_queue_manager.h" + +-struct list_head topology_device_list; ++/* topology_device_list - Master list of all topology devices */ ++static struct list_head topology_device_list; + struct kfd_system_properties sys_props; + + static DECLARE_RWSEM(topology_lock); +@@ -105,24 +106,27 @@ static void kfd_release_topology_device(struct kfd_topology_device *dev) + } + + kfree(dev); +- +- sys_props.num_devices--; + } + +-void kfd_release_live_view(void) ++void kfd_release_topology_device_list(struct list_head *device_list) + { + struct kfd_topology_device *dev; + +- while (topology_device_list.next != &topology_device_list) { +- dev = container_of(topology_device_list.next, +- struct kfd_topology_device, list); ++ while (!list_empty(device_list)) { ++ dev = list_first_entry(device_list, ++ struct kfd_topology_device, list); + kfd_release_topology_device(dev); ++ } + } + ++static void kfd_release_live_view(void) ++{ ++ kfd_release_topology_device_list(&topology_device_list); + memset(&sys_props, 0, sizeof(sys_props)); + } + +-struct kfd_topology_device *kfd_create_topology_device(void) ++struct kfd_topology_device *kfd_create_topology_device( ++ struct list_head *device_list) + { + struct kfd_topology_device *dev; + +@@ -136,8 +140,7 @@ struct kfd_topology_device *kfd_create_topology_device(void) + INIT_LIST_HEAD(&dev->cache_props); + INIT_LIST_HEAD(&dev->io_link_props); + +- list_add_tail(&dev->list, &topology_device_list); +- sys_props.num_devices++; ++ list_add_tail(&dev->list, device_list); + + return dev; + } +@@ -682,16 +685,32 @@ static void kfd_topology_release_sysfs(void) + } + } + ++/* Called with write topology_lock acquired */ ++static void kfd_topology_update_device_list(struct list_head *temp_list, ++ struct list_head *master_list) ++{ ++ while (!list_empty(temp_list)) { ++ list_move_tail(temp_list->next, master_list); ++ sys_props.num_devices++; ++ } ++} ++ + int kfd_topology_init(void) + { + void *crat_image = NULL; + size_t image_size = 0; + int ret; ++ struct list_head temp_topology_device_list; + +- /* +- * Initialize the head for the topology device list ++ /* topology_device_list - Master list of all topology devices ++ * temp_topology_device_list - temporary list created while parsing CRAT ++ * or VCRAT. Once parsing is complete the contents of list is moved to ++ * topology_device_list + */ ++ ++ /* Initialize the head for the both the lists */ + INIT_LIST_HEAD(&topology_device_list); ++ INIT_LIST_HEAD(&temp_topology_device_list); + init_rwsem(&topology_lock); + + memset(&sys_props, 0, sizeof(sys_props)); +@@ -701,7 +720,8 @@ int kfd_topology_init(void) + */ + ret = kfd_create_crat_image_acpi(&crat_image, &image_size); + if (!ret) { +- ret = kfd_parse_crat_table(crat_image); ++ ret = kfd_parse_crat_table(crat_image, ++ &temp_topology_device_list, 0); + if (ret) + goto err; + } else if (ret == -ENODATA) { +@@ -714,12 +734,15 @@ int kfd_topology_init(void) + } + + down_write(&topology_lock); ++ kfd_topology_update_device_list(&temp_topology_device_list, ++ &topology_device_list); + ret = kfd_topology_update_sysfs(); + up_write(&topology_lock); + +- if (!ret) ++ if (!ret) { ++ sys_props.generation_count++; + pr_info("Finished initializing topology\n"); +- else ++ } else + pr_err("Failed to update topology in sysfs ret=%d\n", ret); + + err: +@@ -729,8 +752,10 @@ int kfd_topology_init(void) + + void kfd_topology_shutdown(void) + { ++ down_write(&topology_lock); + kfd_topology_release_sysfs(); + kfd_release_live_view(); ++ up_write(&topology_lock); + } + + static void kfd_debug_print_topology(void) +@@ -806,13 +831,15 @@ int kfd_topology_add_device(struct kfd_dev *gpu) + uint32_t gpu_id; + struct kfd_topology_device *dev; + struct kfd_cu_info cu_info; +- int res; ++ int res = 0; ++ struct list_head temp_topology_device_list; ++ ++ INIT_LIST_HEAD(&temp_topology_device_list); + + gpu_id = kfd_generate_gpu_id(gpu); + + pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id); + +- down_write(&topology_lock); + /* + * Try to assign the GPU to existing topology device (generated from + * CRAT table +@@ -821,11 +848,12 @@ int kfd_topology_add_device(struct kfd_dev *gpu) + if (!dev) { + pr_info("GPU was not found in the current topology. Extending.\n"); + kfd_debug_print_topology(); +- dev = kfd_create_topology_device(); ++ dev = kfd_create_topology_device(&temp_topology_device_list); + if (!dev) { + res = -ENOMEM; + goto err; + } ++ + dev->gpu = gpu; + + /* +@@ -833,12 +861,18 @@ int kfd_topology_add_device(struct kfd_dev *gpu) + * GPU vBIOS + */ + ++ down_write(&topology_lock); ++ kfd_topology_update_device_list(&temp_topology_device_list, ++ &topology_device_list); ++ + /* Update the SYSFS tree, since we added another topology + * device + */ + if (kfd_topology_update_sysfs() < 0) + kfd_topology_release_sysfs(); + ++ up_write(&topology_lock); ++ + } + + dev->gpu_id = gpu_id; +@@ -859,30 +893,26 @@ int kfd_topology_add_device(struct kfd_dev *gpu) + pr_info("Adding doorbell packet type capability\n"); + } + +- res = 0; +- +-err: +- up_write(&topology_lock); +- +- if (res == 0) ++ if (!res) + kfd_notify_gpu_change(gpu_id, 1); +- ++err: + return res; + } + + int kfd_topology_remove_device(struct kfd_dev *gpu) + { +- struct kfd_topology_device *dev; ++ struct kfd_topology_device *dev, *tmp; + uint32_t gpu_id; + int res = -ENODEV; + + down_write(&topology_lock); + +- list_for_each_entry(dev, &topology_device_list, list) ++ list_for_each_entry_safe(dev, tmp, &topology_device_list, list) + if (dev->gpu == gpu) { + gpu_id = dev->gpu_id; + kfd_remove_sysfs_node_entry(dev); + kfd_release_topology_device(dev); ++ sys_props.num_devices--; + res = 0; + if (kfd_topology_update_sysfs() < 0) + kfd_topology_release_sysfs(); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h +index 9996458..0d98b61 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h +@@ -135,6 +135,7 @@ struct kfd_iolink_properties { + struct kfd_topology_device { + struct list_head list; + uint32_t gpu_id; ++ uint32_t proximity_domain; + struct kfd_node_properties node_props; + uint32_t mem_bank_count; + struct list_head mem_props; +@@ -164,7 +165,8 @@ struct kfd_system_properties { + struct attribute attr_props; + }; + +-struct kfd_topology_device *kfd_create_topology_device(void); +-void kfd_release_live_view(void); ++struct kfd_topology_device *kfd_create_topology_device( ++ struct list_head *device_list); ++void kfd_release_topology_device_list(struct list_head *device_list); + + #endif /* __KFD_TOPOLOGY_H__ */ +-- +2.7.4 + |