aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3420-drm-amdkfd-Decouple-CRAT-parsing-from-device-list-up.patch
diff options
context:
space:
mode:
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.patch554
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
+