15b5c4e40SEvgeny Pinchuk /* 25b5c4e40SEvgeny Pinchuk * Copyright 2014 Advanced Micro Devices, Inc. 35b5c4e40SEvgeny Pinchuk * 45b5c4e40SEvgeny Pinchuk * Permission is hereby granted, free of charge, to any person obtaining a 55b5c4e40SEvgeny Pinchuk * copy of this software and associated documentation files (the "Software"), 65b5c4e40SEvgeny Pinchuk * to deal in the Software without restriction, including without limitation 75b5c4e40SEvgeny Pinchuk * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85b5c4e40SEvgeny Pinchuk * and/or sell copies of the Software, and to permit persons to whom the 95b5c4e40SEvgeny Pinchuk * Software is furnished to do so, subject to the following conditions: 105b5c4e40SEvgeny Pinchuk * 115b5c4e40SEvgeny Pinchuk * The above copyright notice and this permission notice shall be included in 125b5c4e40SEvgeny Pinchuk * all copies or substantial portions of the Software. 135b5c4e40SEvgeny Pinchuk * 145b5c4e40SEvgeny Pinchuk * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155b5c4e40SEvgeny Pinchuk * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165b5c4e40SEvgeny Pinchuk * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175b5c4e40SEvgeny Pinchuk * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 185b5c4e40SEvgeny Pinchuk * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 195b5c4e40SEvgeny Pinchuk * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 205b5c4e40SEvgeny Pinchuk * OTHER DEALINGS IN THE SOFTWARE. 215b5c4e40SEvgeny Pinchuk */ 225b5c4e40SEvgeny Pinchuk 235b5c4e40SEvgeny Pinchuk #include <linux/types.h> 245b5c4e40SEvgeny Pinchuk #include <linux/kernel.h> 255b5c4e40SEvgeny Pinchuk #include <linux/pci.h> 265b5c4e40SEvgeny Pinchuk #include <linux/errno.h> 275b5c4e40SEvgeny Pinchuk #include <linux/acpi.h> 285b5c4e40SEvgeny Pinchuk #include <linux/hash.h> 295b5c4e40SEvgeny Pinchuk #include <linux/cpufreq.h> 30f7c826adSAlexey Skidanov #include <linux/log2.h> 315b5c4e40SEvgeny Pinchuk 325b5c4e40SEvgeny Pinchuk #include "kfd_priv.h" 335b5c4e40SEvgeny Pinchuk #include "kfd_crat.h" 345b5c4e40SEvgeny Pinchuk #include "kfd_topology.h" 35851a645eSFelix Kuehling #include "kfd_device_queue_manager.h" 365b5c4e40SEvgeny Pinchuk 37174de876SFelix Kuehling struct list_head topology_device_list; 38174de876SFelix Kuehling struct kfd_system_properties sys_props; 395b5c4e40SEvgeny Pinchuk 405b5c4e40SEvgeny Pinchuk static DECLARE_RWSEM(topology_lock); 415b5c4e40SEvgeny Pinchuk 425b5c4e40SEvgeny Pinchuk struct kfd_dev *kfd_device_by_id(uint32_t gpu_id) 435b5c4e40SEvgeny Pinchuk { 445b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 455b5c4e40SEvgeny Pinchuk struct kfd_dev *device = NULL; 465b5c4e40SEvgeny Pinchuk 475b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 485b5c4e40SEvgeny Pinchuk 495b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) 505b5c4e40SEvgeny Pinchuk if (top_dev->gpu_id == gpu_id) { 515b5c4e40SEvgeny Pinchuk device = top_dev->gpu; 525b5c4e40SEvgeny Pinchuk break; 535b5c4e40SEvgeny Pinchuk } 545b5c4e40SEvgeny Pinchuk 555b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 565b5c4e40SEvgeny Pinchuk 575b5c4e40SEvgeny Pinchuk return device; 585b5c4e40SEvgeny Pinchuk } 595b5c4e40SEvgeny Pinchuk 605b5c4e40SEvgeny Pinchuk struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev) 615b5c4e40SEvgeny Pinchuk { 625b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 635b5c4e40SEvgeny Pinchuk struct kfd_dev *device = NULL; 645b5c4e40SEvgeny Pinchuk 655b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 665b5c4e40SEvgeny Pinchuk 675b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) 685b5c4e40SEvgeny Pinchuk if (top_dev->gpu->pdev == pdev) { 695b5c4e40SEvgeny Pinchuk device = top_dev->gpu; 705b5c4e40SEvgeny Pinchuk break; 715b5c4e40SEvgeny Pinchuk } 725b5c4e40SEvgeny Pinchuk 735b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 745b5c4e40SEvgeny Pinchuk 755b5c4e40SEvgeny Pinchuk return device; 765b5c4e40SEvgeny Pinchuk } 775b5c4e40SEvgeny Pinchuk 785b5c4e40SEvgeny Pinchuk static void kfd_release_topology_device(struct kfd_topology_device *dev) 795b5c4e40SEvgeny Pinchuk { 805b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 815b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 825b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 835b5c4e40SEvgeny Pinchuk 845b5c4e40SEvgeny Pinchuk list_del(&dev->list); 855b5c4e40SEvgeny Pinchuk 865b5c4e40SEvgeny Pinchuk while (dev->mem_props.next != &dev->mem_props) { 875b5c4e40SEvgeny Pinchuk mem = container_of(dev->mem_props.next, 885b5c4e40SEvgeny Pinchuk struct kfd_mem_properties, list); 895b5c4e40SEvgeny Pinchuk list_del(&mem->list); 905b5c4e40SEvgeny Pinchuk kfree(mem); 915b5c4e40SEvgeny Pinchuk } 925b5c4e40SEvgeny Pinchuk 935b5c4e40SEvgeny Pinchuk while (dev->cache_props.next != &dev->cache_props) { 945b5c4e40SEvgeny Pinchuk cache = container_of(dev->cache_props.next, 955b5c4e40SEvgeny Pinchuk struct kfd_cache_properties, list); 965b5c4e40SEvgeny Pinchuk list_del(&cache->list); 975b5c4e40SEvgeny Pinchuk kfree(cache); 985b5c4e40SEvgeny Pinchuk } 995b5c4e40SEvgeny Pinchuk 1005b5c4e40SEvgeny Pinchuk while (dev->io_link_props.next != &dev->io_link_props) { 1015b5c4e40SEvgeny Pinchuk iolink = container_of(dev->io_link_props.next, 1025b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties, list); 1035b5c4e40SEvgeny Pinchuk list_del(&iolink->list); 1045b5c4e40SEvgeny Pinchuk kfree(iolink); 1055b5c4e40SEvgeny Pinchuk } 1065b5c4e40SEvgeny Pinchuk 1075b5c4e40SEvgeny Pinchuk kfree(dev); 1085b5c4e40SEvgeny Pinchuk 1095b5c4e40SEvgeny Pinchuk sys_props.num_devices--; 1105b5c4e40SEvgeny Pinchuk } 1115b5c4e40SEvgeny Pinchuk 112174de876SFelix Kuehling void kfd_release_live_view(void) 1135b5c4e40SEvgeny Pinchuk { 1145b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 1155b5c4e40SEvgeny Pinchuk 1165b5c4e40SEvgeny Pinchuk while (topology_device_list.next != &topology_device_list) { 1175b5c4e40SEvgeny Pinchuk dev = container_of(topology_device_list.next, 1185b5c4e40SEvgeny Pinchuk struct kfd_topology_device, list); 1195b5c4e40SEvgeny Pinchuk kfd_release_topology_device(dev); 1205b5c4e40SEvgeny Pinchuk } 1215b5c4e40SEvgeny Pinchuk 1225b5c4e40SEvgeny Pinchuk memset(&sys_props, 0, sizeof(sys_props)); 1235b5c4e40SEvgeny Pinchuk } 1245b5c4e40SEvgeny Pinchuk 125174de876SFelix Kuehling struct kfd_topology_device *kfd_create_topology_device(void) 1265b5c4e40SEvgeny Pinchuk { 1275b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 1285b5c4e40SEvgeny Pinchuk 1295b5c4e40SEvgeny Pinchuk dev = kfd_alloc_struct(dev); 1304eacc26bSKent Russell if (!dev) { 1315b5c4e40SEvgeny Pinchuk pr_err("No memory to allocate a topology device"); 13216b9201cSOded Gabbay return NULL; 1335b5c4e40SEvgeny Pinchuk } 1345b5c4e40SEvgeny Pinchuk 1355b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->mem_props); 1365b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->cache_props); 1375b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->io_link_props); 1385b5c4e40SEvgeny Pinchuk 1395b5c4e40SEvgeny Pinchuk list_add_tail(&dev->list, &topology_device_list); 1405b5c4e40SEvgeny Pinchuk sys_props.num_devices++; 1415b5c4e40SEvgeny Pinchuk 1425b5c4e40SEvgeny Pinchuk return dev; 1435b5c4e40SEvgeny Pinchuk } 1445b5c4e40SEvgeny Pinchuk 1455b5c4e40SEvgeny Pinchuk 1465b5c4e40SEvgeny Pinchuk #define sysfs_show_gen_prop(buffer, fmt, ...) \ 1475b5c4e40SEvgeny Pinchuk snprintf(buffer, PAGE_SIZE, "%s"fmt, buffer, __VA_ARGS__) 1485b5c4e40SEvgeny Pinchuk #define sysfs_show_32bit_prop(buffer, name, value) \ 1495b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%s %u\n", name, value) 1505b5c4e40SEvgeny Pinchuk #define sysfs_show_64bit_prop(buffer, name, value) \ 1515b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%s %llu\n", name, value) 1525b5c4e40SEvgeny Pinchuk #define sysfs_show_32bit_val(buffer, value) \ 1535b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%u\n", value) 1545b5c4e40SEvgeny Pinchuk #define sysfs_show_str_val(buffer, value) \ 1555b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%s\n", value) 1565b5c4e40SEvgeny Pinchuk 1575b5c4e40SEvgeny Pinchuk static ssize_t sysprops_show(struct kobject *kobj, struct attribute *attr, 1585b5c4e40SEvgeny Pinchuk char *buffer) 1595b5c4e40SEvgeny Pinchuk { 1605b5c4e40SEvgeny Pinchuk ssize_t ret; 1615b5c4e40SEvgeny Pinchuk 1625b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 1635b5c4e40SEvgeny Pinchuk buffer[0] = 0; 1645b5c4e40SEvgeny Pinchuk 1655b5c4e40SEvgeny Pinchuk if (attr == &sys_props.attr_genid) { 1665b5c4e40SEvgeny Pinchuk ret = sysfs_show_32bit_val(buffer, sys_props.generation_count); 1675b5c4e40SEvgeny Pinchuk } else if (attr == &sys_props.attr_props) { 1685b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "platform_oem", 1695b5c4e40SEvgeny Pinchuk sys_props.platform_oem); 1705b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "platform_id", 1715b5c4e40SEvgeny Pinchuk sys_props.platform_id); 1725b5c4e40SEvgeny Pinchuk ret = sysfs_show_64bit_prop(buffer, "platform_rev", 1735b5c4e40SEvgeny Pinchuk sys_props.platform_rev); 1745b5c4e40SEvgeny Pinchuk } else { 1755b5c4e40SEvgeny Pinchuk ret = -EINVAL; 1765b5c4e40SEvgeny Pinchuk } 1775b5c4e40SEvgeny Pinchuk 1785b5c4e40SEvgeny Pinchuk return ret; 1795b5c4e40SEvgeny Pinchuk } 1805b5c4e40SEvgeny Pinchuk 1815108d768SYong Zhao static void kfd_topology_kobj_release(struct kobject *kobj) 1825108d768SYong Zhao { 1835108d768SYong Zhao kfree(kobj); 1845108d768SYong Zhao } 1855108d768SYong Zhao 1865b5c4e40SEvgeny Pinchuk static const struct sysfs_ops sysprops_ops = { 1875b5c4e40SEvgeny Pinchuk .show = sysprops_show, 1885b5c4e40SEvgeny Pinchuk }; 1895b5c4e40SEvgeny Pinchuk 1905b5c4e40SEvgeny Pinchuk static struct kobj_type sysprops_type = { 1915108d768SYong Zhao .release = kfd_topology_kobj_release, 1925b5c4e40SEvgeny Pinchuk .sysfs_ops = &sysprops_ops, 1935b5c4e40SEvgeny Pinchuk }; 1945b5c4e40SEvgeny Pinchuk 1955b5c4e40SEvgeny Pinchuk static ssize_t iolink_show(struct kobject *kobj, struct attribute *attr, 1965b5c4e40SEvgeny Pinchuk char *buffer) 1975b5c4e40SEvgeny Pinchuk { 1985b5c4e40SEvgeny Pinchuk ssize_t ret; 1995b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 2005b5c4e40SEvgeny Pinchuk 2015b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2025b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2035b5c4e40SEvgeny Pinchuk 2045b5c4e40SEvgeny Pinchuk iolink = container_of(attr, struct kfd_iolink_properties, attr); 2055b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "type", iolink->iolink_type); 2065b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "version_major", iolink->ver_maj); 2075b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "version_minor", iolink->ver_min); 2085b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "node_from", iolink->node_from); 2095b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "node_to", iolink->node_to); 2105b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "weight", iolink->weight); 2115b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "min_latency", iolink->min_latency); 2125b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_latency", iolink->max_latency); 2135b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "min_bandwidth", iolink->min_bandwidth); 2145b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_bandwidth", iolink->max_bandwidth); 2155b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "recommended_transfer_size", 2165b5c4e40SEvgeny Pinchuk iolink->rec_transfer_size); 2175b5c4e40SEvgeny Pinchuk ret = sysfs_show_32bit_prop(buffer, "flags", iolink->flags); 2185b5c4e40SEvgeny Pinchuk 2195b5c4e40SEvgeny Pinchuk return ret; 2205b5c4e40SEvgeny Pinchuk } 2215b5c4e40SEvgeny Pinchuk 2225b5c4e40SEvgeny Pinchuk static const struct sysfs_ops iolink_ops = { 2235b5c4e40SEvgeny Pinchuk .show = iolink_show, 2245b5c4e40SEvgeny Pinchuk }; 2255b5c4e40SEvgeny Pinchuk 2265b5c4e40SEvgeny Pinchuk static struct kobj_type iolink_type = { 2275108d768SYong Zhao .release = kfd_topology_kobj_release, 2285b5c4e40SEvgeny Pinchuk .sysfs_ops = &iolink_ops, 2295b5c4e40SEvgeny Pinchuk }; 2305b5c4e40SEvgeny Pinchuk 2315b5c4e40SEvgeny Pinchuk static ssize_t mem_show(struct kobject *kobj, struct attribute *attr, 2325b5c4e40SEvgeny Pinchuk char *buffer) 2335b5c4e40SEvgeny Pinchuk { 2345b5c4e40SEvgeny Pinchuk ssize_t ret; 2355b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 2365b5c4e40SEvgeny Pinchuk 2375b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2385b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2395b5c4e40SEvgeny Pinchuk 2405b5c4e40SEvgeny Pinchuk mem = container_of(attr, struct kfd_mem_properties, attr); 2415b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "heap_type", mem->heap_type); 2425b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "size_in_bytes", mem->size_in_bytes); 2435b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "flags", mem->flags); 2445b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "width", mem->width); 2455b5c4e40SEvgeny Pinchuk ret = sysfs_show_32bit_prop(buffer, "mem_clk_max", mem->mem_clk_max); 2465b5c4e40SEvgeny Pinchuk 2475b5c4e40SEvgeny Pinchuk return ret; 2485b5c4e40SEvgeny Pinchuk } 2495b5c4e40SEvgeny Pinchuk 2505b5c4e40SEvgeny Pinchuk static const struct sysfs_ops mem_ops = { 2515b5c4e40SEvgeny Pinchuk .show = mem_show, 2525b5c4e40SEvgeny Pinchuk }; 2535b5c4e40SEvgeny Pinchuk 2545b5c4e40SEvgeny Pinchuk static struct kobj_type mem_type = { 2555108d768SYong Zhao .release = kfd_topology_kobj_release, 2565b5c4e40SEvgeny Pinchuk .sysfs_ops = &mem_ops, 2575b5c4e40SEvgeny Pinchuk }; 2585b5c4e40SEvgeny Pinchuk 2595b5c4e40SEvgeny Pinchuk static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr, 2605b5c4e40SEvgeny Pinchuk char *buffer) 2615b5c4e40SEvgeny Pinchuk { 2625b5c4e40SEvgeny Pinchuk ssize_t ret; 2635b5c4e40SEvgeny Pinchuk uint32_t i; 2645b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 2655b5c4e40SEvgeny Pinchuk 2665b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2675b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2685b5c4e40SEvgeny Pinchuk 2695b5c4e40SEvgeny Pinchuk cache = container_of(attr, struct kfd_cache_properties, attr); 2705b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "processor_id_low", 2715b5c4e40SEvgeny Pinchuk cache->processor_id_low); 2725b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "level", cache->cache_level); 2735b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "size", cache->cache_size); 2745b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cache_line_size", cache->cacheline_size); 2755b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cache_lines_per_tag", 2765b5c4e40SEvgeny Pinchuk cache->cachelines_per_tag); 2775b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "association", cache->cache_assoc); 2785b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "latency", cache->cache_latency); 2795b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "type", cache->cache_type); 2805b5c4e40SEvgeny Pinchuk snprintf(buffer, PAGE_SIZE, "%ssibling_map ", buffer); 2815b5c4e40SEvgeny Pinchuk for (i = 0; i < KFD_TOPOLOGY_CPU_SIBLINGS; i++) 2825b5c4e40SEvgeny Pinchuk ret = snprintf(buffer, PAGE_SIZE, "%s%d%s", 2835b5c4e40SEvgeny Pinchuk buffer, cache->sibling_map[i], 2845b5c4e40SEvgeny Pinchuk (i == KFD_TOPOLOGY_CPU_SIBLINGS-1) ? 2855b5c4e40SEvgeny Pinchuk "\n" : ","); 2865b5c4e40SEvgeny Pinchuk 2875b5c4e40SEvgeny Pinchuk return ret; 2885b5c4e40SEvgeny Pinchuk } 2895b5c4e40SEvgeny Pinchuk 2905b5c4e40SEvgeny Pinchuk static const struct sysfs_ops cache_ops = { 2915b5c4e40SEvgeny Pinchuk .show = kfd_cache_show, 2925b5c4e40SEvgeny Pinchuk }; 2935b5c4e40SEvgeny Pinchuk 2945b5c4e40SEvgeny Pinchuk static struct kobj_type cache_type = { 2955108d768SYong Zhao .release = kfd_topology_kobj_release, 2965b5c4e40SEvgeny Pinchuk .sysfs_ops = &cache_ops, 2975b5c4e40SEvgeny Pinchuk }; 2985b5c4e40SEvgeny Pinchuk 2995b5c4e40SEvgeny Pinchuk static ssize_t node_show(struct kobject *kobj, struct attribute *attr, 3005b5c4e40SEvgeny Pinchuk char *buffer) 3015b5c4e40SEvgeny Pinchuk { 3025b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 3035b5c4e40SEvgeny Pinchuk char public_name[KFD_TOPOLOGY_PUBLIC_NAME_SIZE]; 3045b5c4e40SEvgeny Pinchuk uint32_t i; 305f7c826adSAlexey Skidanov uint32_t log_max_watch_addr; 3065b5c4e40SEvgeny Pinchuk 3075b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 3085b5c4e40SEvgeny Pinchuk buffer[0] = 0; 3095b5c4e40SEvgeny Pinchuk 3105b5c4e40SEvgeny Pinchuk if (strcmp(attr->name, "gpu_id") == 0) { 3115b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 3125b5c4e40SEvgeny Pinchuk attr_gpuid); 313f7c826adSAlexey Skidanov return sysfs_show_32bit_val(buffer, dev->gpu_id); 314f7c826adSAlexey Skidanov } 315f7c826adSAlexey Skidanov 316f7c826adSAlexey Skidanov if (strcmp(attr->name, "name") == 0) { 3175b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 3185b5c4e40SEvgeny Pinchuk attr_name); 3195b5c4e40SEvgeny Pinchuk for (i = 0; i < KFD_TOPOLOGY_PUBLIC_NAME_SIZE; i++) { 3205b5c4e40SEvgeny Pinchuk public_name[i] = 3215b5c4e40SEvgeny Pinchuk (char)dev->node_props.marketing_name[i]; 3225b5c4e40SEvgeny Pinchuk if (dev->node_props.marketing_name[i] == 0) 3235b5c4e40SEvgeny Pinchuk break; 3245b5c4e40SEvgeny Pinchuk } 3255b5c4e40SEvgeny Pinchuk public_name[KFD_TOPOLOGY_PUBLIC_NAME_SIZE-1] = 0x0; 326f7c826adSAlexey Skidanov return sysfs_show_str_val(buffer, public_name); 327f7c826adSAlexey Skidanov } 328f7c826adSAlexey Skidanov 3295b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 3305b5c4e40SEvgeny Pinchuk attr_props); 3315b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cpu_cores_count", 3325b5c4e40SEvgeny Pinchuk dev->node_props.cpu_cores_count); 3335b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_count", 3345b5c4e40SEvgeny Pinchuk dev->node_props.simd_count); 3355b5c4e40SEvgeny Pinchuk 3365b5c4e40SEvgeny Pinchuk if (dev->mem_bank_count < dev->node_props.mem_banks_count) { 33779775b62SKent Russell pr_info_once("mem_banks_count truncated from %d to %d\n", 3385b5c4e40SEvgeny Pinchuk dev->node_props.mem_banks_count, 3395b5c4e40SEvgeny Pinchuk dev->mem_bank_count); 3405b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "mem_banks_count", 3415b5c4e40SEvgeny Pinchuk dev->mem_bank_count); 3425b5c4e40SEvgeny Pinchuk } else { 3435b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "mem_banks_count", 3445b5c4e40SEvgeny Pinchuk dev->node_props.mem_banks_count); 3455b5c4e40SEvgeny Pinchuk } 3465b5c4e40SEvgeny Pinchuk 3475b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "caches_count", 3485b5c4e40SEvgeny Pinchuk dev->node_props.caches_count); 3495b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "io_links_count", 3505b5c4e40SEvgeny Pinchuk dev->node_props.io_links_count); 3515b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cpu_core_id_base", 3525b5c4e40SEvgeny Pinchuk dev->node_props.cpu_core_id_base); 3535b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_id_base", 3545b5c4e40SEvgeny Pinchuk dev->node_props.simd_id_base); 3555b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_waves_per_simd", 3565b5c4e40SEvgeny Pinchuk dev->node_props.max_waves_per_simd); 3575b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "lds_size_in_kb", 3585b5c4e40SEvgeny Pinchuk dev->node_props.lds_size_in_kb); 3595b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "gds_size_in_kb", 3605b5c4e40SEvgeny Pinchuk dev->node_props.gds_size_in_kb); 3615b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "wave_front_size", 3625b5c4e40SEvgeny Pinchuk dev->node_props.wave_front_size); 3635b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "array_count", 3645b5c4e40SEvgeny Pinchuk dev->node_props.array_count); 3655b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_arrays_per_engine", 3665b5c4e40SEvgeny Pinchuk dev->node_props.simd_arrays_per_engine); 3675b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cu_per_simd_array", 3685b5c4e40SEvgeny Pinchuk dev->node_props.cu_per_simd_array); 3695b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_per_cu", 3705b5c4e40SEvgeny Pinchuk dev->node_props.simd_per_cu); 3715b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_slots_scratch_cu", 3725b5c4e40SEvgeny Pinchuk dev->node_props.max_slots_scratch_cu); 3735b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "vendor_id", 3745b5c4e40SEvgeny Pinchuk dev->node_props.vendor_id); 3755b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "device_id", 3765b5c4e40SEvgeny Pinchuk dev->node_props.device_id); 3775b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "location_id", 3785b5c4e40SEvgeny Pinchuk dev->node_props.location_id); 3795b5c4e40SEvgeny Pinchuk 3805b5c4e40SEvgeny Pinchuk if (dev->gpu) { 381f7c826adSAlexey Skidanov log_max_watch_addr = 382f7c826adSAlexey Skidanov __ilog2_u32(dev->gpu->device_info->num_of_watch_points); 383f7c826adSAlexey Skidanov 384f7c826adSAlexey Skidanov if (log_max_watch_addr) { 385f7c826adSAlexey Skidanov dev->node_props.capability |= 386f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_SUPPORTED; 387f7c826adSAlexey Skidanov 388f7c826adSAlexey Skidanov dev->node_props.capability |= 389f7c826adSAlexey Skidanov ((log_max_watch_addr << 390f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_TOTALBITS_SHIFT) & 391f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_TOTALBITS_MASK); 392f7c826adSAlexey Skidanov } 393f7c826adSAlexey Skidanov 3945b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_engine_clk_fcompute", 395cea405b1SXihan Zhang dev->gpu->kfd2kgd->get_max_engine_clock_in_mhz( 3965b5c4e40SEvgeny Pinchuk dev->gpu->kgd)); 39742e08c78SOded Gabbay 3985b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "local_mem_size", 39942e08c78SOded Gabbay (unsigned long long int) 0); 400f1386fbcSOded Gabbay 401f1386fbcSOded Gabbay sysfs_show_32bit_prop(buffer, "fw_version", 402cea405b1SXihan Zhang dev->gpu->kfd2kgd->get_fw_version( 403f1386fbcSOded Gabbay dev->gpu->kgd, 404f1386fbcSOded Gabbay KGD_ENGINE_MEC1)); 405826f5de8SAlexey Skidanov sysfs_show_32bit_prop(buffer, "capability", 406826f5de8SAlexey Skidanov dev->node_props.capability); 4075b5c4e40SEvgeny Pinchuk } 4085b5c4e40SEvgeny Pinchuk 409f7c826adSAlexey Skidanov return sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute", 4105b5c4e40SEvgeny Pinchuk cpufreq_quick_get_max(0)/1000); 4115b5c4e40SEvgeny Pinchuk } 4125b5c4e40SEvgeny Pinchuk 4135b5c4e40SEvgeny Pinchuk static const struct sysfs_ops node_ops = { 4145b5c4e40SEvgeny Pinchuk .show = node_show, 4155b5c4e40SEvgeny Pinchuk }; 4165b5c4e40SEvgeny Pinchuk 4175b5c4e40SEvgeny Pinchuk static struct kobj_type node_type = { 4185108d768SYong Zhao .release = kfd_topology_kobj_release, 4195b5c4e40SEvgeny Pinchuk .sysfs_ops = &node_ops, 4205b5c4e40SEvgeny Pinchuk }; 4215b5c4e40SEvgeny Pinchuk 4225b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_file(struct kobject *kobj, struct attribute *attr) 4235b5c4e40SEvgeny Pinchuk { 4245b5c4e40SEvgeny Pinchuk sysfs_remove_file(kobj, attr); 4255b5c4e40SEvgeny Pinchuk kobject_del(kobj); 4265b5c4e40SEvgeny Pinchuk kobject_put(kobj); 4275b5c4e40SEvgeny Pinchuk } 4285b5c4e40SEvgeny Pinchuk 4295b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_node_entry(struct kfd_topology_device *dev) 4305b5c4e40SEvgeny Pinchuk { 4315b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 4325b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 4335b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 4345b5c4e40SEvgeny Pinchuk 4355b5c4e40SEvgeny Pinchuk if (dev->kobj_iolink) { 4365b5c4e40SEvgeny Pinchuk list_for_each_entry(iolink, &dev->io_link_props, list) 4375b5c4e40SEvgeny Pinchuk if (iolink->kobj) { 4385b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(iolink->kobj, 4395b5c4e40SEvgeny Pinchuk &iolink->attr); 44016b9201cSOded Gabbay iolink->kobj = NULL; 4415b5c4e40SEvgeny Pinchuk } 4425b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_iolink); 4435b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_iolink); 44416b9201cSOded Gabbay dev->kobj_iolink = NULL; 4455b5c4e40SEvgeny Pinchuk } 4465b5c4e40SEvgeny Pinchuk 4475b5c4e40SEvgeny Pinchuk if (dev->kobj_cache) { 4485b5c4e40SEvgeny Pinchuk list_for_each_entry(cache, &dev->cache_props, list) 4495b5c4e40SEvgeny Pinchuk if (cache->kobj) { 4505b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(cache->kobj, 4515b5c4e40SEvgeny Pinchuk &cache->attr); 45216b9201cSOded Gabbay cache->kobj = NULL; 4535b5c4e40SEvgeny Pinchuk } 4545b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_cache); 4555b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_cache); 45616b9201cSOded Gabbay dev->kobj_cache = NULL; 4575b5c4e40SEvgeny Pinchuk } 4585b5c4e40SEvgeny Pinchuk 4595b5c4e40SEvgeny Pinchuk if (dev->kobj_mem) { 4605b5c4e40SEvgeny Pinchuk list_for_each_entry(mem, &dev->mem_props, list) 4615b5c4e40SEvgeny Pinchuk if (mem->kobj) { 4625b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(mem->kobj, &mem->attr); 46316b9201cSOded Gabbay mem->kobj = NULL; 4645b5c4e40SEvgeny Pinchuk } 4655b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_mem); 4665b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_mem); 46716b9201cSOded Gabbay dev->kobj_mem = NULL; 4685b5c4e40SEvgeny Pinchuk } 4695b5c4e40SEvgeny Pinchuk 4705b5c4e40SEvgeny Pinchuk if (dev->kobj_node) { 4715b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_gpuid); 4725b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_name); 4735b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_props); 4745b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_node); 4755b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_node); 47616b9201cSOded Gabbay dev->kobj_node = NULL; 4775b5c4e40SEvgeny Pinchuk } 4785b5c4e40SEvgeny Pinchuk } 4795b5c4e40SEvgeny Pinchuk 4805b5c4e40SEvgeny Pinchuk static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev, 4815b5c4e40SEvgeny Pinchuk uint32_t id) 4825b5c4e40SEvgeny Pinchuk { 4835b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 4845b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 4855b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 4865b5c4e40SEvgeny Pinchuk int ret; 4875b5c4e40SEvgeny Pinchuk uint32_t i; 4885b5c4e40SEvgeny Pinchuk 48932fa8219SFelix Kuehling if (WARN_ON(dev->kobj_node)) 49032fa8219SFelix Kuehling return -EEXIST; 49132fa8219SFelix Kuehling 4925b5c4e40SEvgeny Pinchuk /* 4935b5c4e40SEvgeny Pinchuk * Creating the sysfs folders 4945b5c4e40SEvgeny Pinchuk */ 4955b5c4e40SEvgeny Pinchuk dev->kobj_node = kfd_alloc_struct(dev->kobj_node); 4965b5c4e40SEvgeny Pinchuk if (!dev->kobj_node) 4975b5c4e40SEvgeny Pinchuk return -ENOMEM; 4985b5c4e40SEvgeny Pinchuk 4995b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(dev->kobj_node, &node_type, 5005b5c4e40SEvgeny Pinchuk sys_props.kobj_nodes, "%d", id); 5015b5c4e40SEvgeny Pinchuk if (ret < 0) 5025b5c4e40SEvgeny Pinchuk return ret; 5035b5c4e40SEvgeny Pinchuk 5045b5c4e40SEvgeny Pinchuk dev->kobj_mem = kobject_create_and_add("mem_banks", dev->kobj_node); 5055b5c4e40SEvgeny Pinchuk if (!dev->kobj_mem) 5065b5c4e40SEvgeny Pinchuk return -ENOMEM; 5075b5c4e40SEvgeny Pinchuk 5085b5c4e40SEvgeny Pinchuk dev->kobj_cache = kobject_create_and_add("caches", dev->kobj_node); 5095b5c4e40SEvgeny Pinchuk if (!dev->kobj_cache) 5105b5c4e40SEvgeny Pinchuk return -ENOMEM; 5115b5c4e40SEvgeny Pinchuk 5125b5c4e40SEvgeny Pinchuk dev->kobj_iolink = kobject_create_and_add("io_links", dev->kobj_node); 5135b5c4e40SEvgeny Pinchuk if (!dev->kobj_iolink) 5145b5c4e40SEvgeny Pinchuk return -ENOMEM; 5155b5c4e40SEvgeny Pinchuk 5165b5c4e40SEvgeny Pinchuk /* 5175b5c4e40SEvgeny Pinchuk * Creating sysfs files for node properties 5185b5c4e40SEvgeny Pinchuk */ 5195b5c4e40SEvgeny Pinchuk dev->attr_gpuid.name = "gpu_id"; 5205b5c4e40SEvgeny Pinchuk dev->attr_gpuid.mode = KFD_SYSFS_FILE_MODE; 5215b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_gpuid); 5225b5c4e40SEvgeny Pinchuk dev->attr_name.name = "name"; 5235b5c4e40SEvgeny Pinchuk dev->attr_name.mode = KFD_SYSFS_FILE_MODE; 5245b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_name); 5255b5c4e40SEvgeny Pinchuk dev->attr_props.name = "properties"; 5265b5c4e40SEvgeny Pinchuk dev->attr_props.mode = KFD_SYSFS_FILE_MODE; 5275b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_props); 5285b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_gpuid); 5295b5c4e40SEvgeny Pinchuk if (ret < 0) 5305b5c4e40SEvgeny Pinchuk return ret; 5315b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_name); 5325b5c4e40SEvgeny Pinchuk if (ret < 0) 5335b5c4e40SEvgeny Pinchuk return ret; 5345b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_props); 5355b5c4e40SEvgeny Pinchuk if (ret < 0) 5365b5c4e40SEvgeny Pinchuk return ret; 5375b5c4e40SEvgeny Pinchuk 5385b5c4e40SEvgeny Pinchuk i = 0; 5395b5c4e40SEvgeny Pinchuk list_for_each_entry(mem, &dev->mem_props, list) { 5405b5c4e40SEvgeny Pinchuk mem->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 5415b5c4e40SEvgeny Pinchuk if (!mem->kobj) 5425b5c4e40SEvgeny Pinchuk return -ENOMEM; 5435b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(mem->kobj, &mem_type, 5445b5c4e40SEvgeny Pinchuk dev->kobj_mem, "%d", i); 5455b5c4e40SEvgeny Pinchuk if (ret < 0) 5465b5c4e40SEvgeny Pinchuk return ret; 5475b5c4e40SEvgeny Pinchuk 5485b5c4e40SEvgeny Pinchuk mem->attr.name = "properties"; 5495b5c4e40SEvgeny Pinchuk mem->attr.mode = KFD_SYSFS_FILE_MODE; 5505b5c4e40SEvgeny Pinchuk sysfs_attr_init(&mem->attr); 5515b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(mem->kobj, &mem->attr); 5525b5c4e40SEvgeny Pinchuk if (ret < 0) 5535b5c4e40SEvgeny Pinchuk return ret; 5545b5c4e40SEvgeny Pinchuk i++; 5555b5c4e40SEvgeny Pinchuk } 5565b5c4e40SEvgeny Pinchuk 5575b5c4e40SEvgeny Pinchuk i = 0; 5585b5c4e40SEvgeny Pinchuk list_for_each_entry(cache, &dev->cache_props, list) { 5595b5c4e40SEvgeny Pinchuk cache->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 5605b5c4e40SEvgeny Pinchuk if (!cache->kobj) 5615b5c4e40SEvgeny Pinchuk return -ENOMEM; 5625b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(cache->kobj, &cache_type, 5635b5c4e40SEvgeny Pinchuk dev->kobj_cache, "%d", i); 5645b5c4e40SEvgeny Pinchuk if (ret < 0) 5655b5c4e40SEvgeny Pinchuk return ret; 5665b5c4e40SEvgeny Pinchuk 5675b5c4e40SEvgeny Pinchuk cache->attr.name = "properties"; 5685b5c4e40SEvgeny Pinchuk cache->attr.mode = KFD_SYSFS_FILE_MODE; 5695b5c4e40SEvgeny Pinchuk sysfs_attr_init(&cache->attr); 5705b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(cache->kobj, &cache->attr); 5715b5c4e40SEvgeny Pinchuk if (ret < 0) 5725b5c4e40SEvgeny Pinchuk return ret; 5735b5c4e40SEvgeny Pinchuk i++; 5745b5c4e40SEvgeny Pinchuk } 5755b5c4e40SEvgeny Pinchuk 5765b5c4e40SEvgeny Pinchuk i = 0; 5775b5c4e40SEvgeny Pinchuk list_for_each_entry(iolink, &dev->io_link_props, list) { 5785b5c4e40SEvgeny Pinchuk iolink->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 5795b5c4e40SEvgeny Pinchuk if (!iolink->kobj) 5805b5c4e40SEvgeny Pinchuk return -ENOMEM; 5815b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(iolink->kobj, &iolink_type, 5825b5c4e40SEvgeny Pinchuk dev->kobj_iolink, "%d", i); 5835b5c4e40SEvgeny Pinchuk if (ret < 0) 5845b5c4e40SEvgeny Pinchuk return ret; 5855b5c4e40SEvgeny Pinchuk 5865b5c4e40SEvgeny Pinchuk iolink->attr.name = "properties"; 5875b5c4e40SEvgeny Pinchuk iolink->attr.mode = KFD_SYSFS_FILE_MODE; 5885b5c4e40SEvgeny Pinchuk sysfs_attr_init(&iolink->attr); 5895b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(iolink->kobj, &iolink->attr); 5905b5c4e40SEvgeny Pinchuk if (ret < 0) 5915b5c4e40SEvgeny Pinchuk return ret; 5925b5c4e40SEvgeny Pinchuk i++; 5935b5c4e40SEvgeny Pinchuk } 5945b5c4e40SEvgeny Pinchuk 5955b5c4e40SEvgeny Pinchuk return 0; 5965b5c4e40SEvgeny Pinchuk } 5975b5c4e40SEvgeny Pinchuk 5985b5c4e40SEvgeny Pinchuk static int kfd_build_sysfs_node_tree(void) 5995b5c4e40SEvgeny Pinchuk { 6005b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 6015b5c4e40SEvgeny Pinchuk int ret; 6025b5c4e40SEvgeny Pinchuk uint32_t i = 0; 6035b5c4e40SEvgeny Pinchuk 6045b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) { 6058dfead6cSBen Goz ret = kfd_build_sysfs_node_entry(dev, i); 6065b5c4e40SEvgeny Pinchuk if (ret < 0) 6075b5c4e40SEvgeny Pinchuk return ret; 6085b5c4e40SEvgeny Pinchuk i++; 6095b5c4e40SEvgeny Pinchuk } 6105b5c4e40SEvgeny Pinchuk 6115b5c4e40SEvgeny Pinchuk return 0; 6125b5c4e40SEvgeny Pinchuk } 6135b5c4e40SEvgeny Pinchuk 6145b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_node_tree(void) 6155b5c4e40SEvgeny Pinchuk { 6165b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 6175b5c4e40SEvgeny Pinchuk 6185b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) 6195b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_entry(dev); 6205b5c4e40SEvgeny Pinchuk } 6215b5c4e40SEvgeny Pinchuk 6225b5c4e40SEvgeny Pinchuk static int kfd_topology_update_sysfs(void) 6235b5c4e40SEvgeny Pinchuk { 6245b5c4e40SEvgeny Pinchuk int ret; 6255b5c4e40SEvgeny Pinchuk 6265b5c4e40SEvgeny Pinchuk pr_info("Creating topology SYSFS entries\n"); 6274eacc26bSKent Russell if (!sys_props.kobj_topology) { 6285b5c4e40SEvgeny Pinchuk sys_props.kobj_topology = 6295b5c4e40SEvgeny Pinchuk kfd_alloc_struct(sys_props.kobj_topology); 6305b5c4e40SEvgeny Pinchuk if (!sys_props.kobj_topology) 6315b5c4e40SEvgeny Pinchuk return -ENOMEM; 6325b5c4e40SEvgeny Pinchuk 6335b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(sys_props.kobj_topology, 6345b5c4e40SEvgeny Pinchuk &sysprops_type, &kfd_device->kobj, 6355b5c4e40SEvgeny Pinchuk "topology"); 6365b5c4e40SEvgeny Pinchuk if (ret < 0) 6375b5c4e40SEvgeny Pinchuk return ret; 6385b5c4e40SEvgeny Pinchuk 6395b5c4e40SEvgeny Pinchuk sys_props.kobj_nodes = kobject_create_and_add("nodes", 6405b5c4e40SEvgeny Pinchuk sys_props.kobj_topology); 6415b5c4e40SEvgeny Pinchuk if (!sys_props.kobj_nodes) 6425b5c4e40SEvgeny Pinchuk return -ENOMEM; 6435b5c4e40SEvgeny Pinchuk 6445b5c4e40SEvgeny Pinchuk sys_props.attr_genid.name = "generation_id"; 6455b5c4e40SEvgeny Pinchuk sys_props.attr_genid.mode = KFD_SYSFS_FILE_MODE; 6465b5c4e40SEvgeny Pinchuk sysfs_attr_init(&sys_props.attr_genid); 6475b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(sys_props.kobj_topology, 6485b5c4e40SEvgeny Pinchuk &sys_props.attr_genid); 6495b5c4e40SEvgeny Pinchuk if (ret < 0) 6505b5c4e40SEvgeny Pinchuk return ret; 6515b5c4e40SEvgeny Pinchuk 6525b5c4e40SEvgeny Pinchuk sys_props.attr_props.name = "system_properties"; 6535b5c4e40SEvgeny Pinchuk sys_props.attr_props.mode = KFD_SYSFS_FILE_MODE; 6545b5c4e40SEvgeny Pinchuk sysfs_attr_init(&sys_props.attr_props); 6555b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(sys_props.kobj_topology, 6565b5c4e40SEvgeny Pinchuk &sys_props.attr_props); 6575b5c4e40SEvgeny Pinchuk if (ret < 0) 6585b5c4e40SEvgeny Pinchuk return ret; 6595b5c4e40SEvgeny Pinchuk } 6605b5c4e40SEvgeny Pinchuk 6615b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_tree(); 6625b5c4e40SEvgeny Pinchuk 6635b5c4e40SEvgeny Pinchuk return kfd_build_sysfs_node_tree(); 6645b5c4e40SEvgeny Pinchuk } 6655b5c4e40SEvgeny Pinchuk 6665b5c4e40SEvgeny Pinchuk static void kfd_topology_release_sysfs(void) 6675b5c4e40SEvgeny Pinchuk { 6685b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_tree(); 6695b5c4e40SEvgeny Pinchuk if (sys_props.kobj_topology) { 6705b5c4e40SEvgeny Pinchuk sysfs_remove_file(sys_props.kobj_topology, 6715b5c4e40SEvgeny Pinchuk &sys_props.attr_genid); 6725b5c4e40SEvgeny Pinchuk sysfs_remove_file(sys_props.kobj_topology, 6735b5c4e40SEvgeny Pinchuk &sys_props.attr_props); 6745b5c4e40SEvgeny Pinchuk if (sys_props.kobj_nodes) { 6755b5c4e40SEvgeny Pinchuk kobject_del(sys_props.kobj_nodes); 6765b5c4e40SEvgeny Pinchuk kobject_put(sys_props.kobj_nodes); 67716b9201cSOded Gabbay sys_props.kobj_nodes = NULL; 6785b5c4e40SEvgeny Pinchuk } 6795b5c4e40SEvgeny Pinchuk kobject_del(sys_props.kobj_topology); 6805b5c4e40SEvgeny Pinchuk kobject_put(sys_props.kobj_topology); 68116b9201cSOded Gabbay sys_props.kobj_topology = NULL; 6825b5c4e40SEvgeny Pinchuk } 6835b5c4e40SEvgeny Pinchuk } 6845b5c4e40SEvgeny Pinchuk 6855b5c4e40SEvgeny Pinchuk int kfd_topology_init(void) 6865b5c4e40SEvgeny Pinchuk { 68716b9201cSOded Gabbay void *crat_image = NULL; 6885b5c4e40SEvgeny Pinchuk size_t image_size = 0; 6895b5c4e40SEvgeny Pinchuk int ret; 6905b5c4e40SEvgeny Pinchuk 6915b5c4e40SEvgeny Pinchuk /* 6925b5c4e40SEvgeny Pinchuk * Initialize the head for the topology device list 6935b5c4e40SEvgeny Pinchuk */ 6945b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&topology_device_list); 6955b5c4e40SEvgeny Pinchuk init_rwsem(&topology_lock); 6965b5c4e40SEvgeny Pinchuk 6975b5c4e40SEvgeny Pinchuk memset(&sys_props, 0, sizeof(sys_props)); 6985b5c4e40SEvgeny Pinchuk 6995b5c4e40SEvgeny Pinchuk /* 7005b5c4e40SEvgeny Pinchuk * Get the CRAT image from the ACPI 7015b5c4e40SEvgeny Pinchuk */ 7028e05247dSHarish Kasiviswanathan ret = kfd_create_crat_image_acpi(&crat_image, &image_size); 7038e05247dSHarish Kasiviswanathan if (!ret) { 7048e05247dSHarish Kasiviswanathan ret = kfd_parse_crat_table(crat_image); 7058e05247dSHarish Kasiviswanathan if (ret) 7068e05247dSHarish Kasiviswanathan goto err; 7078e05247dSHarish Kasiviswanathan } else if (ret == -ENODATA) { 7088e05247dSHarish Kasiviswanathan /* TODO: Create fake CRAT table */ 7098e05247dSHarish Kasiviswanathan ret = 0; 7108e05247dSHarish Kasiviswanathan goto err; 7118e05247dSHarish Kasiviswanathan } else { 7128e05247dSHarish Kasiviswanathan pr_err("Couldn't get CRAT table size from ACPI\n"); 7135b5c4e40SEvgeny Pinchuk goto err; 7145b5c4e40SEvgeny Pinchuk } 7155b5c4e40SEvgeny Pinchuk 7165b5c4e40SEvgeny Pinchuk down_write(&topology_lock); 7175b5c4e40SEvgeny Pinchuk ret = kfd_topology_update_sysfs(); 7185b5c4e40SEvgeny Pinchuk up_write(&topology_lock); 7198e05247dSHarish Kasiviswanathan 7208e05247dSHarish Kasiviswanathan if (!ret) 7218e05247dSHarish Kasiviswanathan pr_info("Finished initializing topology\n"); 7228e05247dSHarish Kasiviswanathan else 7238e05247dSHarish Kasiviswanathan pr_err("Failed to update topology in sysfs ret=%d\n", ret); 7245b5c4e40SEvgeny Pinchuk 7255b5c4e40SEvgeny Pinchuk err: 7268e05247dSHarish Kasiviswanathan kfd_destroy_crat_image(crat_image); 7275b5c4e40SEvgeny Pinchuk return ret; 7285b5c4e40SEvgeny Pinchuk } 7295b5c4e40SEvgeny Pinchuk 7305b5c4e40SEvgeny Pinchuk void kfd_topology_shutdown(void) 7315b5c4e40SEvgeny Pinchuk { 7325b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 7335b5c4e40SEvgeny Pinchuk kfd_release_live_view(); 7345b5c4e40SEvgeny Pinchuk } 7355b5c4e40SEvgeny Pinchuk 7365b5c4e40SEvgeny Pinchuk static void kfd_debug_print_topology(void) 7375b5c4e40SEvgeny Pinchuk { 7385b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 7395b5c4e40SEvgeny Pinchuk uint32_t i = 0; 7405b5c4e40SEvgeny Pinchuk 7415b5c4e40SEvgeny Pinchuk pr_info("DEBUG PRINT OF TOPOLOGY:"); 7425b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) { 7435b5c4e40SEvgeny Pinchuk pr_info("Node: %d\n", i); 7445b5c4e40SEvgeny Pinchuk pr_info("\tGPU assigned: %s\n", (dev->gpu ? "yes" : "no")); 7455b5c4e40SEvgeny Pinchuk pr_info("\tCPU count: %d\n", dev->node_props.cpu_cores_count); 7468e05247dSHarish Kasiviswanathan pr_info("\tSIMD count: %d\n", dev->node_props.simd_count); 7475b5c4e40SEvgeny Pinchuk i++; 7485b5c4e40SEvgeny Pinchuk } 7495b5c4e40SEvgeny Pinchuk } 7505b5c4e40SEvgeny Pinchuk 7515b5c4e40SEvgeny Pinchuk static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu) 7525b5c4e40SEvgeny Pinchuk { 7535b5c4e40SEvgeny Pinchuk uint32_t hashout; 7545b5c4e40SEvgeny Pinchuk uint32_t buf[7]; 755585f0e6cSEdward O'Callaghan uint64_t local_mem_size; 7565b5c4e40SEvgeny Pinchuk int i; 7570504cccfSHarish Kasiviswanathan struct kfd_local_mem_info local_mem_info; 7585b5c4e40SEvgeny Pinchuk 7595b5c4e40SEvgeny Pinchuk if (!gpu) 7605b5c4e40SEvgeny Pinchuk return 0; 7615b5c4e40SEvgeny Pinchuk 7620504cccfSHarish Kasiviswanathan gpu->kfd2kgd->get_local_mem_info(gpu->kgd, &local_mem_info); 7630504cccfSHarish Kasiviswanathan 7640504cccfSHarish Kasiviswanathan local_mem_size = local_mem_info.local_mem_size_private + 7650504cccfSHarish Kasiviswanathan local_mem_info.local_mem_size_public; 766585f0e6cSEdward O'Callaghan 7675b5c4e40SEvgeny Pinchuk buf[0] = gpu->pdev->devfn; 7685b5c4e40SEvgeny Pinchuk buf[1] = gpu->pdev->subsystem_vendor; 7695b5c4e40SEvgeny Pinchuk buf[2] = gpu->pdev->subsystem_device; 7705b5c4e40SEvgeny Pinchuk buf[3] = gpu->pdev->device; 7715b5c4e40SEvgeny Pinchuk buf[4] = gpu->pdev->bus->number; 772585f0e6cSEdward O'Callaghan buf[5] = lower_32_bits(local_mem_size); 773585f0e6cSEdward O'Callaghan buf[6] = upper_32_bits(local_mem_size); 7745b5c4e40SEvgeny Pinchuk 7755b5c4e40SEvgeny Pinchuk for (i = 0, hashout = 0; i < 7; i++) 7765b5c4e40SEvgeny Pinchuk hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH); 7775b5c4e40SEvgeny Pinchuk 7785b5c4e40SEvgeny Pinchuk return hashout; 7795b5c4e40SEvgeny Pinchuk } 7805b5c4e40SEvgeny Pinchuk 7815b5c4e40SEvgeny Pinchuk static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) 7825b5c4e40SEvgeny Pinchuk { 7835b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 78416b9201cSOded Gabbay struct kfd_topology_device *out_dev = NULL; 7855b5c4e40SEvgeny Pinchuk 7865b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) 7874eacc26bSKent Russell if (!dev->gpu && (dev->node_props.simd_count > 0)) { 7885b5c4e40SEvgeny Pinchuk dev->gpu = gpu; 7895b5c4e40SEvgeny Pinchuk out_dev = dev; 7905b5c4e40SEvgeny Pinchuk break; 7915b5c4e40SEvgeny Pinchuk } 7925b5c4e40SEvgeny Pinchuk 7935b5c4e40SEvgeny Pinchuk return out_dev; 7945b5c4e40SEvgeny Pinchuk } 7955b5c4e40SEvgeny Pinchuk 7965b5c4e40SEvgeny Pinchuk static void kfd_notify_gpu_change(uint32_t gpu_id, int arrival) 7975b5c4e40SEvgeny Pinchuk { 7985b5c4e40SEvgeny Pinchuk /* 7995b5c4e40SEvgeny Pinchuk * TODO: Generate an event for thunk about the arrival/removal 8005b5c4e40SEvgeny Pinchuk * of the GPU 8015b5c4e40SEvgeny Pinchuk */ 8025b5c4e40SEvgeny Pinchuk } 8035b5c4e40SEvgeny Pinchuk 8045b5c4e40SEvgeny Pinchuk int kfd_topology_add_device(struct kfd_dev *gpu) 8055b5c4e40SEvgeny Pinchuk { 8065b5c4e40SEvgeny Pinchuk uint32_t gpu_id; 8075b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 808f7ce2fadSFlora Cui struct kfd_cu_info cu_info; 8095b5c4e40SEvgeny Pinchuk int res; 8105b5c4e40SEvgeny Pinchuk 8115b5c4e40SEvgeny Pinchuk gpu_id = kfd_generate_gpu_id(gpu); 8125b5c4e40SEvgeny Pinchuk 81379775b62SKent Russell pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id); 8145b5c4e40SEvgeny Pinchuk 8155b5c4e40SEvgeny Pinchuk down_write(&topology_lock); 8165b5c4e40SEvgeny Pinchuk /* 8175b5c4e40SEvgeny Pinchuk * Try to assign the GPU to existing topology device (generated from 8185b5c4e40SEvgeny Pinchuk * CRAT table 8195b5c4e40SEvgeny Pinchuk */ 8205b5c4e40SEvgeny Pinchuk dev = kfd_assign_gpu(gpu); 8215b5c4e40SEvgeny Pinchuk if (!dev) { 8225b5c4e40SEvgeny Pinchuk pr_info("GPU was not found in the current topology. Extending.\n"); 8235b5c4e40SEvgeny Pinchuk kfd_debug_print_topology(); 8245b5c4e40SEvgeny Pinchuk dev = kfd_create_topology_device(); 8255b5c4e40SEvgeny Pinchuk if (!dev) { 8265b5c4e40SEvgeny Pinchuk res = -ENOMEM; 8275b5c4e40SEvgeny Pinchuk goto err; 8285b5c4e40SEvgeny Pinchuk } 8295b5c4e40SEvgeny Pinchuk dev->gpu = gpu; 8305b5c4e40SEvgeny Pinchuk 8315b5c4e40SEvgeny Pinchuk /* 8325b5c4e40SEvgeny Pinchuk * TODO: Make a call to retrieve topology information from the 8335b5c4e40SEvgeny Pinchuk * GPU vBIOS 8345b5c4e40SEvgeny Pinchuk */ 8355b5c4e40SEvgeny Pinchuk 8368eabaf54SKent Russell /* Update the SYSFS tree, since we added another topology 8378eabaf54SKent Russell * device 8385b5c4e40SEvgeny Pinchuk */ 8395b5c4e40SEvgeny Pinchuk if (kfd_topology_update_sysfs() < 0) 8405b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 8415b5c4e40SEvgeny Pinchuk 8425b5c4e40SEvgeny Pinchuk } 8435b5c4e40SEvgeny Pinchuk 8445b5c4e40SEvgeny Pinchuk dev->gpu_id = gpu_id; 8455b5c4e40SEvgeny Pinchuk gpu->id = gpu_id; 846f7ce2fadSFlora Cui dev->gpu->kfd2kgd->get_cu_info(dev->gpu->kgd, &cu_info); 847f7ce2fadSFlora Cui dev->node_props.simd_count = dev->node_props.simd_per_cu * 848f7ce2fadSFlora Cui cu_info.cu_active_number; 8495b5c4e40SEvgeny Pinchuk dev->node_props.vendor_id = gpu->pdev->vendor; 8505b5c4e40SEvgeny Pinchuk dev->node_props.device_id = gpu->pdev->device; 851d63f0ba2SHarish Kasiviswanathan dev->node_props.location_id = PCI_DEVID(gpu->pdev->bus->number, 852d63f0ba2SHarish Kasiviswanathan gpu->pdev->devfn); 8535b5c4e40SEvgeny Pinchuk /* 8545b5c4e40SEvgeny Pinchuk * TODO: Retrieve max engine clock values from KGD 8555b5c4e40SEvgeny Pinchuk */ 8565b5c4e40SEvgeny Pinchuk 8577639a8c4SBen Goz if (dev->gpu->device_info->asic_family == CHIP_CARRIZO) { 8587639a8c4SBen Goz dev->node_props.capability |= HSA_CAP_DOORBELL_PACKET_TYPE; 85979775b62SKent Russell pr_info("Adding doorbell packet type capability\n"); 8607639a8c4SBen Goz } 8617639a8c4SBen Goz 8625b5c4e40SEvgeny Pinchuk res = 0; 8635b5c4e40SEvgeny Pinchuk 8645b5c4e40SEvgeny Pinchuk err: 8655b5c4e40SEvgeny Pinchuk up_write(&topology_lock); 8665b5c4e40SEvgeny Pinchuk 8675b5c4e40SEvgeny Pinchuk if (res == 0) 8685b5c4e40SEvgeny Pinchuk kfd_notify_gpu_change(gpu_id, 1); 8695b5c4e40SEvgeny Pinchuk 8705b5c4e40SEvgeny Pinchuk return res; 8715b5c4e40SEvgeny Pinchuk } 8725b5c4e40SEvgeny Pinchuk 8735b5c4e40SEvgeny Pinchuk int kfd_topology_remove_device(struct kfd_dev *gpu) 8745b5c4e40SEvgeny Pinchuk { 8755b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 8765b5c4e40SEvgeny Pinchuk uint32_t gpu_id; 8775b5c4e40SEvgeny Pinchuk int res = -ENODEV; 8785b5c4e40SEvgeny Pinchuk 8795b5c4e40SEvgeny Pinchuk down_write(&topology_lock); 8805b5c4e40SEvgeny Pinchuk 8815b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) 8825b5c4e40SEvgeny Pinchuk if (dev->gpu == gpu) { 8835b5c4e40SEvgeny Pinchuk gpu_id = dev->gpu_id; 8845b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_entry(dev); 8855b5c4e40SEvgeny Pinchuk kfd_release_topology_device(dev); 8865b5c4e40SEvgeny Pinchuk res = 0; 8875b5c4e40SEvgeny Pinchuk if (kfd_topology_update_sysfs() < 0) 8885b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 8895b5c4e40SEvgeny Pinchuk break; 8905b5c4e40SEvgeny Pinchuk } 8915b5c4e40SEvgeny Pinchuk 8925b5c4e40SEvgeny Pinchuk up_write(&topology_lock); 8935b5c4e40SEvgeny Pinchuk 894174de876SFelix Kuehling if (!res) 8955b5c4e40SEvgeny Pinchuk kfd_notify_gpu_change(gpu_id, 0); 8965b5c4e40SEvgeny Pinchuk 8975b5c4e40SEvgeny Pinchuk return res; 8985b5c4e40SEvgeny Pinchuk } 8995b5c4e40SEvgeny Pinchuk 9005b5c4e40SEvgeny Pinchuk /* 9015b5c4e40SEvgeny Pinchuk * When idx is out of bounds, the function will return NULL 9025b5c4e40SEvgeny Pinchuk */ 9035b5c4e40SEvgeny Pinchuk struct kfd_dev *kfd_topology_enum_kfd_devices(uint8_t idx) 9045b5c4e40SEvgeny Pinchuk { 9055b5c4e40SEvgeny Pinchuk 9065b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 9075b5c4e40SEvgeny Pinchuk struct kfd_dev *device = NULL; 9085b5c4e40SEvgeny Pinchuk uint8_t device_idx = 0; 9095b5c4e40SEvgeny Pinchuk 9105b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 9115b5c4e40SEvgeny Pinchuk 9125b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) { 9135b5c4e40SEvgeny Pinchuk if (device_idx == idx) { 9145b5c4e40SEvgeny Pinchuk device = top_dev->gpu; 9155b5c4e40SEvgeny Pinchuk break; 9165b5c4e40SEvgeny Pinchuk } 9175b5c4e40SEvgeny Pinchuk 9185b5c4e40SEvgeny Pinchuk device_idx++; 9195b5c4e40SEvgeny Pinchuk } 9205b5c4e40SEvgeny Pinchuk 9215b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 9225b5c4e40SEvgeny Pinchuk 9235b5c4e40SEvgeny Pinchuk return device; 9245b5c4e40SEvgeny Pinchuk 9255b5c4e40SEvgeny Pinchuk } 926851a645eSFelix Kuehling 927851a645eSFelix Kuehling #if defined(CONFIG_DEBUG_FS) 928851a645eSFelix Kuehling 929851a645eSFelix Kuehling int kfd_debugfs_hqds_by_device(struct seq_file *m, void *data) 930851a645eSFelix Kuehling { 931851a645eSFelix Kuehling struct kfd_topology_device *dev; 932851a645eSFelix Kuehling unsigned int i = 0; 933851a645eSFelix Kuehling int r = 0; 934851a645eSFelix Kuehling 935851a645eSFelix Kuehling down_read(&topology_lock); 936851a645eSFelix Kuehling 937851a645eSFelix Kuehling list_for_each_entry(dev, &topology_device_list, list) { 938851a645eSFelix Kuehling if (!dev->gpu) { 939851a645eSFelix Kuehling i++; 940851a645eSFelix Kuehling continue; 941851a645eSFelix Kuehling } 942851a645eSFelix Kuehling 943851a645eSFelix Kuehling seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); 944851a645eSFelix Kuehling r = dqm_debugfs_hqds(m, dev->gpu->dqm); 945851a645eSFelix Kuehling if (r) 946851a645eSFelix Kuehling break; 947851a645eSFelix Kuehling } 948851a645eSFelix Kuehling 949851a645eSFelix Kuehling up_read(&topology_lock); 950851a645eSFelix Kuehling 951851a645eSFelix Kuehling return r; 952851a645eSFelix Kuehling } 953851a645eSFelix Kuehling 954851a645eSFelix Kuehling int kfd_debugfs_rls_by_device(struct seq_file *m, void *data) 955851a645eSFelix Kuehling { 956851a645eSFelix Kuehling struct kfd_topology_device *dev; 957851a645eSFelix Kuehling unsigned int i = 0; 958851a645eSFelix Kuehling int r = 0; 959851a645eSFelix Kuehling 960851a645eSFelix Kuehling down_read(&topology_lock); 961851a645eSFelix Kuehling 962851a645eSFelix Kuehling list_for_each_entry(dev, &topology_device_list, list) { 963851a645eSFelix Kuehling if (!dev->gpu) { 964851a645eSFelix Kuehling i++; 965851a645eSFelix Kuehling continue; 966851a645eSFelix Kuehling } 967851a645eSFelix Kuehling 968851a645eSFelix Kuehling seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); 969851a645eSFelix Kuehling r = pm_debugfs_runlist(m, &dev->gpu->dqm->packets); 970851a645eSFelix Kuehling if (r) 971851a645eSFelix Kuehling break; 972851a645eSFelix Kuehling } 973851a645eSFelix Kuehling 974851a645eSFelix Kuehling up_read(&topology_lock); 975851a645eSFelix Kuehling 976851a645eSFelix Kuehling return r; 977851a645eSFelix Kuehling } 978851a645eSFelix Kuehling 979851a645eSFelix Kuehling #endif 980