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 374f449311SHarish Kasiviswanathan /* topology_device_list - Master list of all topology devices */ 384f449311SHarish Kasiviswanathan static struct list_head topology_device_list; 39174de876SFelix Kuehling struct kfd_system_properties sys_props; 405b5c4e40SEvgeny Pinchuk 415b5c4e40SEvgeny Pinchuk static DECLARE_RWSEM(topology_lock); 425b5c4e40SEvgeny Pinchuk 435b5c4e40SEvgeny Pinchuk struct kfd_dev *kfd_device_by_id(uint32_t gpu_id) 445b5c4e40SEvgeny Pinchuk { 455b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 465b5c4e40SEvgeny Pinchuk struct kfd_dev *device = NULL; 475b5c4e40SEvgeny Pinchuk 485b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 495b5c4e40SEvgeny Pinchuk 505b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) 515b5c4e40SEvgeny Pinchuk if (top_dev->gpu_id == gpu_id) { 525b5c4e40SEvgeny Pinchuk device = top_dev->gpu; 535b5c4e40SEvgeny Pinchuk break; 545b5c4e40SEvgeny Pinchuk } 555b5c4e40SEvgeny Pinchuk 565b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 575b5c4e40SEvgeny Pinchuk 585b5c4e40SEvgeny Pinchuk return device; 595b5c4e40SEvgeny Pinchuk } 605b5c4e40SEvgeny Pinchuk 615b5c4e40SEvgeny Pinchuk struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev) 625b5c4e40SEvgeny Pinchuk { 635b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 645b5c4e40SEvgeny Pinchuk struct kfd_dev *device = NULL; 655b5c4e40SEvgeny Pinchuk 665b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 675b5c4e40SEvgeny Pinchuk 685b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) 695b5c4e40SEvgeny Pinchuk if (top_dev->gpu->pdev == pdev) { 705b5c4e40SEvgeny Pinchuk device = top_dev->gpu; 715b5c4e40SEvgeny Pinchuk break; 725b5c4e40SEvgeny Pinchuk } 735b5c4e40SEvgeny Pinchuk 745b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 755b5c4e40SEvgeny Pinchuk 765b5c4e40SEvgeny Pinchuk return device; 775b5c4e40SEvgeny Pinchuk } 785b5c4e40SEvgeny Pinchuk 795b5c4e40SEvgeny Pinchuk static void kfd_release_topology_device(struct kfd_topology_device *dev) 805b5c4e40SEvgeny Pinchuk { 815b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 825b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 835b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 845b5c4e40SEvgeny Pinchuk 855b5c4e40SEvgeny Pinchuk list_del(&dev->list); 865b5c4e40SEvgeny Pinchuk 875b5c4e40SEvgeny Pinchuk while (dev->mem_props.next != &dev->mem_props) { 885b5c4e40SEvgeny Pinchuk mem = container_of(dev->mem_props.next, 895b5c4e40SEvgeny Pinchuk struct kfd_mem_properties, list); 905b5c4e40SEvgeny Pinchuk list_del(&mem->list); 915b5c4e40SEvgeny Pinchuk kfree(mem); 925b5c4e40SEvgeny Pinchuk } 935b5c4e40SEvgeny Pinchuk 945b5c4e40SEvgeny Pinchuk while (dev->cache_props.next != &dev->cache_props) { 955b5c4e40SEvgeny Pinchuk cache = container_of(dev->cache_props.next, 965b5c4e40SEvgeny Pinchuk struct kfd_cache_properties, list); 975b5c4e40SEvgeny Pinchuk list_del(&cache->list); 985b5c4e40SEvgeny Pinchuk kfree(cache); 995b5c4e40SEvgeny Pinchuk } 1005b5c4e40SEvgeny Pinchuk 1015b5c4e40SEvgeny Pinchuk while (dev->io_link_props.next != &dev->io_link_props) { 1025b5c4e40SEvgeny Pinchuk iolink = container_of(dev->io_link_props.next, 1035b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties, list); 1045b5c4e40SEvgeny Pinchuk list_del(&iolink->list); 1055b5c4e40SEvgeny Pinchuk kfree(iolink); 1065b5c4e40SEvgeny Pinchuk } 1075b5c4e40SEvgeny Pinchuk 1085b5c4e40SEvgeny Pinchuk kfree(dev); 1095b5c4e40SEvgeny Pinchuk } 1105b5c4e40SEvgeny Pinchuk 1114f449311SHarish Kasiviswanathan void kfd_release_topology_device_list(struct list_head *device_list) 1125b5c4e40SEvgeny Pinchuk { 1135b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 1145b5c4e40SEvgeny Pinchuk 1154f449311SHarish Kasiviswanathan while (!list_empty(device_list)) { 1164f449311SHarish Kasiviswanathan dev = list_first_entry(device_list, 1175b5c4e40SEvgeny Pinchuk struct kfd_topology_device, list); 1185b5c4e40SEvgeny Pinchuk kfd_release_topology_device(dev); 1195b5c4e40SEvgeny Pinchuk } 1204f449311SHarish Kasiviswanathan } 1215b5c4e40SEvgeny Pinchuk 1224f449311SHarish Kasiviswanathan static void kfd_release_live_view(void) 1234f449311SHarish Kasiviswanathan { 1244f449311SHarish Kasiviswanathan kfd_release_topology_device_list(&topology_device_list); 1255b5c4e40SEvgeny Pinchuk memset(&sys_props, 0, sizeof(sys_props)); 1265b5c4e40SEvgeny Pinchuk } 1275b5c4e40SEvgeny Pinchuk 1284f449311SHarish Kasiviswanathan struct kfd_topology_device *kfd_create_topology_device( 1294f449311SHarish Kasiviswanathan struct list_head *device_list) 1305b5c4e40SEvgeny Pinchuk { 1315b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 1325b5c4e40SEvgeny Pinchuk 1335b5c4e40SEvgeny Pinchuk dev = kfd_alloc_struct(dev); 1344eacc26bSKent Russell if (!dev) { 1355b5c4e40SEvgeny Pinchuk pr_err("No memory to allocate a topology device"); 13616b9201cSOded Gabbay return NULL; 1375b5c4e40SEvgeny Pinchuk } 1385b5c4e40SEvgeny Pinchuk 1395b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->mem_props); 1405b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->cache_props); 1415b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->io_link_props); 1425b5c4e40SEvgeny Pinchuk 1434f449311SHarish Kasiviswanathan list_add_tail(&dev->list, device_list); 1445b5c4e40SEvgeny Pinchuk 1455b5c4e40SEvgeny Pinchuk return dev; 1465b5c4e40SEvgeny Pinchuk } 1475b5c4e40SEvgeny Pinchuk 1485b5c4e40SEvgeny Pinchuk 1495b5c4e40SEvgeny Pinchuk #define sysfs_show_gen_prop(buffer, fmt, ...) \ 1505b5c4e40SEvgeny Pinchuk snprintf(buffer, PAGE_SIZE, "%s"fmt, buffer, __VA_ARGS__) 1515b5c4e40SEvgeny Pinchuk #define sysfs_show_32bit_prop(buffer, name, value) \ 1525b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%s %u\n", name, value) 1535b5c4e40SEvgeny Pinchuk #define sysfs_show_64bit_prop(buffer, name, value) \ 1545b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%s %llu\n", name, value) 1555b5c4e40SEvgeny Pinchuk #define sysfs_show_32bit_val(buffer, value) \ 1565b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%u\n", value) 1575b5c4e40SEvgeny Pinchuk #define sysfs_show_str_val(buffer, value) \ 1585b5c4e40SEvgeny Pinchuk sysfs_show_gen_prop(buffer, "%s\n", value) 1595b5c4e40SEvgeny Pinchuk 1605b5c4e40SEvgeny Pinchuk static ssize_t sysprops_show(struct kobject *kobj, struct attribute *attr, 1615b5c4e40SEvgeny Pinchuk char *buffer) 1625b5c4e40SEvgeny Pinchuk { 1635b5c4e40SEvgeny Pinchuk ssize_t ret; 1645b5c4e40SEvgeny Pinchuk 1655b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 1665b5c4e40SEvgeny Pinchuk buffer[0] = 0; 1675b5c4e40SEvgeny Pinchuk 1685b5c4e40SEvgeny Pinchuk if (attr == &sys_props.attr_genid) { 1695b5c4e40SEvgeny Pinchuk ret = sysfs_show_32bit_val(buffer, sys_props.generation_count); 1705b5c4e40SEvgeny Pinchuk } else if (attr == &sys_props.attr_props) { 1715b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "platform_oem", 1725b5c4e40SEvgeny Pinchuk sys_props.platform_oem); 1735b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "platform_id", 1745b5c4e40SEvgeny Pinchuk sys_props.platform_id); 1755b5c4e40SEvgeny Pinchuk ret = sysfs_show_64bit_prop(buffer, "platform_rev", 1765b5c4e40SEvgeny Pinchuk sys_props.platform_rev); 1775b5c4e40SEvgeny Pinchuk } else { 1785b5c4e40SEvgeny Pinchuk ret = -EINVAL; 1795b5c4e40SEvgeny Pinchuk } 1805b5c4e40SEvgeny Pinchuk 1815b5c4e40SEvgeny Pinchuk return ret; 1825b5c4e40SEvgeny Pinchuk } 1835b5c4e40SEvgeny Pinchuk 1845108d768SYong Zhao static void kfd_topology_kobj_release(struct kobject *kobj) 1855108d768SYong Zhao { 1865108d768SYong Zhao kfree(kobj); 1875108d768SYong Zhao } 1885108d768SYong Zhao 1895b5c4e40SEvgeny Pinchuk static const struct sysfs_ops sysprops_ops = { 1905b5c4e40SEvgeny Pinchuk .show = sysprops_show, 1915b5c4e40SEvgeny Pinchuk }; 1925b5c4e40SEvgeny Pinchuk 1935b5c4e40SEvgeny Pinchuk static struct kobj_type sysprops_type = { 1945108d768SYong Zhao .release = kfd_topology_kobj_release, 1955b5c4e40SEvgeny Pinchuk .sysfs_ops = &sysprops_ops, 1965b5c4e40SEvgeny Pinchuk }; 1975b5c4e40SEvgeny Pinchuk 1985b5c4e40SEvgeny Pinchuk static ssize_t iolink_show(struct kobject *kobj, struct attribute *attr, 1995b5c4e40SEvgeny Pinchuk char *buffer) 2005b5c4e40SEvgeny Pinchuk { 2015b5c4e40SEvgeny Pinchuk ssize_t ret; 2025b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 2035b5c4e40SEvgeny Pinchuk 2045b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2055b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2065b5c4e40SEvgeny Pinchuk 2075b5c4e40SEvgeny Pinchuk iolink = container_of(attr, struct kfd_iolink_properties, attr); 2085b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "type", iolink->iolink_type); 2095b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "version_major", iolink->ver_maj); 2105b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "version_minor", iolink->ver_min); 2115b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "node_from", iolink->node_from); 2125b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "node_to", iolink->node_to); 2135b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "weight", iolink->weight); 2145b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "min_latency", iolink->min_latency); 2155b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_latency", iolink->max_latency); 2165b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "min_bandwidth", iolink->min_bandwidth); 2175b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_bandwidth", iolink->max_bandwidth); 2185b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "recommended_transfer_size", 2195b5c4e40SEvgeny Pinchuk iolink->rec_transfer_size); 2205b5c4e40SEvgeny Pinchuk ret = sysfs_show_32bit_prop(buffer, "flags", iolink->flags); 2215b5c4e40SEvgeny Pinchuk 2225b5c4e40SEvgeny Pinchuk return ret; 2235b5c4e40SEvgeny Pinchuk } 2245b5c4e40SEvgeny Pinchuk 2255b5c4e40SEvgeny Pinchuk static const struct sysfs_ops iolink_ops = { 2265b5c4e40SEvgeny Pinchuk .show = iolink_show, 2275b5c4e40SEvgeny Pinchuk }; 2285b5c4e40SEvgeny Pinchuk 2295b5c4e40SEvgeny Pinchuk static struct kobj_type iolink_type = { 2305108d768SYong Zhao .release = kfd_topology_kobj_release, 2315b5c4e40SEvgeny Pinchuk .sysfs_ops = &iolink_ops, 2325b5c4e40SEvgeny Pinchuk }; 2335b5c4e40SEvgeny Pinchuk 2345b5c4e40SEvgeny Pinchuk static ssize_t mem_show(struct kobject *kobj, struct attribute *attr, 2355b5c4e40SEvgeny Pinchuk char *buffer) 2365b5c4e40SEvgeny Pinchuk { 2375b5c4e40SEvgeny Pinchuk ssize_t ret; 2385b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 2395b5c4e40SEvgeny Pinchuk 2405b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2415b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2425b5c4e40SEvgeny Pinchuk 2435b5c4e40SEvgeny Pinchuk mem = container_of(attr, struct kfd_mem_properties, attr); 2445b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "heap_type", mem->heap_type); 2455b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "size_in_bytes", mem->size_in_bytes); 2465b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "flags", mem->flags); 2475b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "width", mem->width); 2485b5c4e40SEvgeny Pinchuk ret = sysfs_show_32bit_prop(buffer, "mem_clk_max", mem->mem_clk_max); 2495b5c4e40SEvgeny Pinchuk 2505b5c4e40SEvgeny Pinchuk return ret; 2515b5c4e40SEvgeny Pinchuk } 2525b5c4e40SEvgeny Pinchuk 2535b5c4e40SEvgeny Pinchuk static const struct sysfs_ops mem_ops = { 2545b5c4e40SEvgeny Pinchuk .show = mem_show, 2555b5c4e40SEvgeny Pinchuk }; 2565b5c4e40SEvgeny Pinchuk 2575b5c4e40SEvgeny Pinchuk static struct kobj_type mem_type = { 2585108d768SYong Zhao .release = kfd_topology_kobj_release, 2595b5c4e40SEvgeny Pinchuk .sysfs_ops = &mem_ops, 2605b5c4e40SEvgeny Pinchuk }; 2615b5c4e40SEvgeny Pinchuk 2625b5c4e40SEvgeny Pinchuk static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr, 2635b5c4e40SEvgeny Pinchuk char *buffer) 2645b5c4e40SEvgeny Pinchuk { 2655b5c4e40SEvgeny Pinchuk ssize_t ret; 2665b5c4e40SEvgeny Pinchuk uint32_t i; 2675b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 2685b5c4e40SEvgeny Pinchuk 2695b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2705b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2715b5c4e40SEvgeny Pinchuk 2725b5c4e40SEvgeny Pinchuk cache = container_of(attr, struct kfd_cache_properties, attr); 2735b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "processor_id_low", 2745b5c4e40SEvgeny Pinchuk cache->processor_id_low); 2755b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "level", cache->cache_level); 2765b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "size", cache->cache_size); 2775b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cache_line_size", cache->cacheline_size); 2785b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cache_lines_per_tag", 2795b5c4e40SEvgeny Pinchuk cache->cachelines_per_tag); 2805b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "association", cache->cache_assoc); 2815b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "latency", cache->cache_latency); 2825b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "type", cache->cache_type); 2835b5c4e40SEvgeny Pinchuk snprintf(buffer, PAGE_SIZE, "%ssibling_map ", buffer); 2845b5c4e40SEvgeny Pinchuk for (i = 0; i < KFD_TOPOLOGY_CPU_SIBLINGS; i++) 2855b5c4e40SEvgeny Pinchuk ret = snprintf(buffer, PAGE_SIZE, "%s%d%s", 2865b5c4e40SEvgeny Pinchuk buffer, cache->sibling_map[i], 2875b5c4e40SEvgeny Pinchuk (i == KFD_TOPOLOGY_CPU_SIBLINGS-1) ? 2885b5c4e40SEvgeny Pinchuk "\n" : ","); 2895b5c4e40SEvgeny Pinchuk 2905b5c4e40SEvgeny Pinchuk return ret; 2915b5c4e40SEvgeny Pinchuk } 2925b5c4e40SEvgeny Pinchuk 2935b5c4e40SEvgeny Pinchuk static const struct sysfs_ops cache_ops = { 2945b5c4e40SEvgeny Pinchuk .show = kfd_cache_show, 2955b5c4e40SEvgeny Pinchuk }; 2965b5c4e40SEvgeny Pinchuk 2975b5c4e40SEvgeny Pinchuk static struct kobj_type cache_type = { 2985108d768SYong Zhao .release = kfd_topology_kobj_release, 2995b5c4e40SEvgeny Pinchuk .sysfs_ops = &cache_ops, 3005b5c4e40SEvgeny Pinchuk }; 3015b5c4e40SEvgeny Pinchuk 3025b5c4e40SEvgeny Pinchuk static ssize_t node_show(struct kobject *kobj, struct attribute *attr, 3035b5c4e40SEvgeny Pinchuk char *buffer) 3045b5c4e40SEvgeny Pinchuk { 3055b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 3065b5c4e40SEvgeny Pinchuk char public_name[KFD_TOPOLOGY_PUBLIC_NAME_SIZE]; 3075b5c4e40SEvgeny Pinchuk uint32_t i; 308f7c826adSAlexey Skidanov uint32_t log_max_watch_addr; 3095b5c4e40SEvgeny Pinchuk 3105b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 3115b5c4e40SEvgeny Pinchuk buffer[0] = 0; 3125b5c4e40SEvgeny Pinchuk 3135b5c4e40SEvgeny Pinchuk if (strcmp(attr->name, "gpu_id") == 0) { 3145b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 3155b5c4e40SEvgeny Pinchuk attr_gpuid); 316f7c826adSAlexey Skidanov return sysfs_show_32bit_val(buffer, dev->gpu_id); 317f7c826adSAlexey Skidanov } 318f7c826adSAlexey Skidanov 319f7c826adSAlexey Skidanov if (strcmp(attr->name, "name") == 0) { 3205b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 3215b5c4e40SEvgeny Pinchuk attr_name); 3225b5c4e40SEvgeny Pinchuk for (i = 0; i < KFD_TOPOLOGY_PUBLIC_NAME_SIZE; i++) { 3235b5c4e40SEvgeny Pinchuk public_name[i] = 3245b5c4e40SEvgeny Pinchuk (char)dev->node_props.marketing_name[i]; 3255b5c4e40SEvgeny Pinchuk if (dev->node_props.marketing_name[i] == 0) 3265b5c4e40SEvgeny Pinchuk break; 3275b5c4e40SEvgeny Pinchuk } 3285b5c4e40SEvgeny Pinchuk public_name[KFD_TOPOLOGY_PUBLIC_NAME_SIZE-1] = 0x0; 329f7c826adSAlexey Skidanov return sysfs_show_str_val(buffer, public_name); 330f7c826adSAlexey Skidanov } 331f7c826adSAlexey Skidanov 3325b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 3335b5c4e40SEvgeny Pinchuk attr_props); 3345b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cpu_cores_count", 3355b5c4e40SEvgeny Pinchuk dev->node_props.cpu_cores_count); 3365b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_count", 3375b5c4e40SEvgeny Pinchuk dev->node_props.simd_count); 3385b5c4e40SEvgeny Pinchuk 3395b5c4e40SEvgeny Pinchuk if (dev->mem_bank_count < dev->node_props.mem_banks_count) { 34079775b62SKent Russell pr_info_once("mem_banks_count truncated from %d to %d\n", 3415b5c4e40SEvgeny Pinchuk dev->node_props.mem_banks_count, 3425b5c4e40SEvgeny Pinchuk dev->mem_bank_count); 3435b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "mem_banks_count", 3445b5c4e40SEvgeny Pinchuk dev->mem_bank_count); 3455b5c4e40SEvgeny Pinchuk } else { 3465b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "mem_banks_count", 3475b5c4e40SEvgeny Pinchuk dev->node_props.mem_banks_count); 3485b5c4e40SEvgeny Pinchuk } 3495b5c4e40SEvgeny Pinchuk 3505b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "caches_count", 3515b5c4e40SEvgeny Pinchuk dev->node_props.caches_count); 3525b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "io_links_count", 3535b5c4e40SEvgeny Pinchuk dev->node_props.io_links_count); 3545b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cpu_core_id_base", 3555b5c4e40SEvgeny Pinchuk dev->node_props.cpu_core_id_base); 3565b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_id_base", 3575b5c4e40SEvgeny Pinchuk dev->node_props.simd_id_base); 3585b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_waves_per_simd", 3595b5c4e40SEvgeny Pinchuk dev->node_props.max_waves_per_simd); 3605b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "lds_size_in_kb", 3615b5c4e40SEvgeny Pinchuk dev->node_props.lds_size_in_kb); 3625b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "gds_size_in_kb", 3635b5c4e40SEvgeny Pinchuk dev->node_props.gds_size_in_kb); 3645b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "wave_front_size", 3655b5c4e40SEvgeny Pinchuk dev->node_props.wave_front_size); 3665b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "array_count", 3675b5c4e40SEvgeny Pinchuk dev->node_props.array_count); 3685b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_arrays_per_engine", 3695b5c4e40SEvgeny Pinchuk dev->node_props.simd_arrays_per_engine); 3705b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "cu_per_simd_array", 3715b5c4e40SEvgeny Pinchuk dev->node_props.cu_per_simd_array); 3725b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "simd_per_cu", 3735b5c4e40SEvgeny Pinchuk dev->node_props.simd_per_cu); 3745b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_slots_scratch_cu", 3755b5c4e40SEvgeny Pinchuk dev->node_props.max_slots_scratch_cu); 3765b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "vendor_id", 3775b5c4e40SEvgeny Pinchuk dev->node_props.vendor_id); 3785b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "device_id", 3795b5c4e40SEvgeny Pinchuk dev->node_props.device_id); 3805b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "location_id", 3815b5c4e40SEvgeny Pinchuk dev->node_props.location_id); 3825b5c4e40SEvgeny Pinchuk 3835b5c4e40SEvgeny Pinchuk if (dev->gpu) { 384f7c826adSAlexey Skidanov log_max_watch_addr = 385f7c826adSAlexey Skidanov __ilog2_u32(dev->gpu->device_info->num_of_watch_points); 386f7c826adSAlexey Skidanov 387f7c826adSAlexey Skidanov if (log_max_watch_addr) { 388f7c826adSAlexey Skidanov dev->node_props.capability |= 389f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_SUPPORTED; 390f7c826adSAlexey Skidanov 391f7c826adSAlexey Skidanov dev->node_props.capability |= 392f7c826adSAlexey Skidanov ((log_max_watch_addr << 393f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_TOTALBITS_SHIFT) & 394f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_TOTALBITS_MASK); 395f7c826adSAlexey Skidanov } 396f7c826adSAlexey Skidanov 3975b5c4e40SEvgeny Pinchuk sysfs_show_32bit_prop(buffer, "max_engine_clk_fcompute", 398cea405b1SXihan Zhang dev->gpu->kfd2kgd->get_max_engine_clock_in_mhz( 3995b5c4e40SEvgeny Pinchuk dev->gpu->kgd)); 40042e08c78SOded Gabbay 4015b5c4e40SEvgeny Pinchuk sysfs_show_64bit_prop(buffer, "local_mem_size", 40242e08c78SOded Gabbay (unsigned long long int) 0); 403f1386fbcSOded Gabbay 404f1386fbcSOded Gabbay sysfs_show_32bit_prop(buffer, "fw_version", 405cea405b1SXihan Zhang dev->gpu->kfd2kgd->get_fw_version( 406f1386fbcSOded Gabbay dev->gpu->kgd, 407f1386fbcSOded Gabbay KGD_ENGINE_MEC1)); 408826f5de8SAlexey Skidanov sysfs_show_32bit_prop(buffer, "capability", 409826f5de8SAlexey Skidanov dev->node_props.capability); 4105b5c4e40SEvgeny Pinchuk } 4115b5c4e40SEvgeny Pinchuk 412f7c826adSAlexey Skidanov return sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute", 4135b5c4e40SEvgeny Pinchuk cpufreq_quick_get_max(0)/1000); 4145b5c4e40SEvgeny Pinchuk } 4155b5c4e40SEvgeny Pinchuk 4165b5c4e40SEvgeny Pinchuk static const struct sysfs_ops node_ops = { 4175b5c4e40SEvgeny Pinchuk .show = node_show, 4185b5c4e40SEvgeny Pinchuk }; 4195b5c4e40SEvgeny Pinchuk 4205b5c4e40SEvgeny Pinchuk static struct kobj_type node_type = { 4215108d768SYong Zhao .release = kfd_topology_kobj_release, 4225b5c4e40SEvgeny Pinchuk .sysfs_ops = &node_ops, 4235b5c4e40SEvgeny Pinchuk }; 4245b5c4e40SEvgeny Pinchuk 4255b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_file(struct kobject *kobj, struct attribute *attr) 4265b5c4e40SEvgeny Pinchuk { 4275b5c4e40SEvgeny Pinchuk sysfs_remove_file(kobj, attr); 4285b5c4e40SEvgeny Pinchuk kobject_del(kobj); 4295b5c4e40SEvgeny Pinchuk kobject_put(kobj); 4305b5c4e40SEvgeny Pinchuk } 4315b5c4e40SEvgeny Pinchuk 4325b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_node_entry(struct kfd_topology_device *dev) 4335b5c4e40SEvgeny Pinchuk { 4345b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 4355b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 4365b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 4375b5c4e40SEvgeny Pinchuk 4385b5c4e40SEvgeny Pinchuk if (dev->kobj_iolink) { 4395b5c4e40SEvgeny Pinchuk list_for_each_entry(iolink, &dev->io_link_props, list) 4405b5c4e40SEvgeny Pinchuk if (iolink->kobj) { 4415b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(iolink->kobj, 4425b5c4e40SEvgeny Pinchuk &iolink->attr); 44316b9201cSOded Gabbay iolink->kobj = NULL; 4445b5c4e40SEvgeny Pinchuk } 4455b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_iolink); 4465b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_iolink); 44716b9201cSOded Gabbay dev->kobj_iolink = NULL; 4485b5c4e40SEvgeny Pinchuk } 4495b5c4e40SEvgeny Pinchuk 4505b5c4e40SEvgeny Pinchuk if (dev->kobj_cache) { 4515b5c4e40SEvgeny Pinchuk list_for_each_entry(cache, &dev->cache_props, list) 4525b5c4e40SEvgeny Pinchuk if (cache->kobj) { 4535b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(cache->kobj, 4545b5c4e40SEvgeny Pinchuk &cache->attr); 45516b9201cSOded Gabbay cache->kobj = NULL; 4565b5c4e40SEvgeny Pinchuk } 4575b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_cache); 4585b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_cache); 45916b9201cSOded Gabbay dev->kobj_cache = NULL; 4605b5c4e40SEvgeny Pinchuk } 4615b5c4e40SEvgeny Pinchuk 4625b5c4e40SEvgeny Pinchuk if (dev->kobj_mem) { 4635b5c4e40SEvgeny Pinchuk list_for_each_entry(mem, &dev->mem_props, list) 4645b5c4e40SEvgeny Pinchuk if (mem->kobj) { 4655b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(mem->kobj, &mem->attr); 46616b9201cSOded Gabbay mem->kobj = NULL; 4675b5c4e40SEvgeny Pinchuk } 4685b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_mem); 4695b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_mem); 47016b9201cSOded Gabbay dev->kobj_mem = NULL; 4715b5c4e40SEvgeny Pinchuk } 4725b5c4e40SEvgeny Pinchuk 4735b5c4e40SEvgeny Pinchuk if (dev->kobj_node) { 4745b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_gpuid); 4755b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_name); 4765b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_props); 4775b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_node); 4785b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_node); 47916b9201cSOded Gabbay dev->kobj_node = NULL; 4805b5c4e40SEvgeny Pinchuk } 4815b5c4e40SEvgeny Pinchuk } 4825b5c4e40SEvgeny Pinchuk 4835b5c4e40SEvgeny Pinchuk static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev, 4845b5c4e40SEvgeny Pinchuk uint32_t id) 4855b5c4e40SEvgeny Pinchuk { 4865b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 4875b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 4885b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 4895b5c4e40SEvgeny Pinchuk int ret; 4905b5c4e40SEvgeny Pinchuk uint32_t i; 4915b5c4e40SEvgeny Pinchuk 49232fa8219SFelix Kuehling if (WARN_ON(dev->kobj_node)) 49332fa8219SFelix Kuehling return -EEXIST; 49432fa8219SFelix Kuehling 4955b5c4e40SEvgeny Pinchuk /* 4965b5c4e40SEvgeny Pinchuk * Creating the sysfs folders 4975b5c4e40SEvgeny Pinchuk */ 4985b5c4e40SEvgeny Pinchuk dev->kobj_node = kfd_alloc_struct(dev->kobj_node); 4995b5c4e40SEvgeny Pinchuk if (!dev->kobj_node) 5005b5c4e40SEvgeny Pinchuk return -ENOMEM; 5015b5c4e40SEvgeny Pinchuk 5025b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(dev->kobj_node, &node_type, 5035b5c4e40SEvgeny Pinchuk sys_props.kobj_nodes, "%d", id); 5045b5c4e40SEvgeny Pinchuk if (ret < 0) 5055b5c4e40SEvgeny Pinchuk return ret; 5065b5c4e40SEvgeny Pinchuk 5075b5c4e40SEvgeny Pinchuk dev->kobj_mem = kobject_create_and_add("mem_banks", dev->kobj_node); 5085b5c4e40SEvgeny Pinchuk if (!dev->kobj_mem) 5095b5c4e40SEvgeny Pinchuk return -ENOMEM; 5105b5c4e40SEvgeny Pinchuk 5115b5c4e40SEvgeny Pinchuk dev->kobj_cache = kobject_create_and_add("caches", dev->kobj_node); 5125b5c4e40SEvgeny Pinchuk if (!dev->kobj_cache) 5135b5c4e40SEvgeny Pinchuk return -ENOMEM; 5145b5c4e40SEvgeny Pinchuk 5155b5c4e40SEvgeny Pinchuk dev->kobj_iolink = kobject_create_and_add("io_links", dev->kobj_node); 5165b5c4e40SEvgeny Pinchuk if (!dev->kobj_iolink) 5175b5c4e40SEvgeny Pinchuk return -ENOMEM; 5185b5c4e40SEvgeny Pinchuk 5195b5c4e40SEvgeny Pinchuk /* 5205b5c4e40SEvgeny Pinchuk * Creating sysfs files for node properties 5215b5c4e40SEvgeny Pinchuk */ 5225b5c4e40SEvgeny Pinchuk dev->attr_gpuid.name = "gpu_id"; 5235b5c4e40SEvgeny Pinchuk dev->attr_gpuid.mode = KFD_SYSFS_FILE_MODE; 5245b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_gpuid); 5255b5c4e40SEvgeny Pinchuk dev->attr_name.name = "name"; 5265b5c4e40SEvgeny Pinchuk dev->attr_name.mode = KFD_SYSFS_FILE_MODE; 5275b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_name); 5285b5c4e40SEvgeny Pinchuk dev->attr_props.name = "properties"; 5295b5c4e40SEvgeny Pinchuk dev->attr_props.mode = KFD_SYSFS_FILE_MODE; 5305b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_props); 5315b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_gpuid); 5325b5c4e40SEvgeny Pinchuk if (ret < 0) 5335b5c4e40SEvgeny Pinchuk return ret; 5345b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_name); 5355b5c4e40SEvgeny Pinchuk if (ret < 0) 5365b5c4e40SEvgeny Pinchuk return ret; 5375b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_props); 5385b5c4e40SEvgeny Pinchuk if (ret < 0) 5395b5c4e40SEvgeny Pinchuk return ret; 5405b5c4e40SEvgeny Pinchuk 5415b5c4e40SEvgeny Pinchuk i = 0; 5425b5c4e40SEvgeny Pinchuk list_for_each_entry(mem, &dev->mem_props, list) { 5435b5c4e40SEvgeny Pinchuk mem->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 5445b5c4e40SEvgeny Pinchuk if (!mem->kobj) 5455b5c4e40SEvgeny Pinchuk return -ENOMEM; 5465b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(mem->kobj, &mem_type, 5475b5c4e40SEvgeny Pinchuk dev->kobj_mem, "%d", i); 5485b5c4e40SEvgeny Pinchuk if (ret < 0) 5495b5c4e40SEvgeny Pinchuk return ret; 5505b5c4e40SEvgeny Pinchuk 5515b5c4e40SEvgeny Pinchuk mem->attr.name = "properties"; 5525b5c4e40SEvgeny Pinchuk mem->attr.mode = KFD_SYSFS_FILE_MODE; 5535b5c4e40SEvgeny Pinchuk sysfs_attr_init(&mem->attr); 5545b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(mem->kobj, &mem->attr); 5555b5c4e40SEvgeny Pinchuk if (ret < 0) 5565b5c4e40SEvgeny Pinchuk return ret; 5575b5c4e40SEvgeny Pinchuk i++; 5585b5c4e40SEvgeny Pinchuk } 5595b5c4e40SEvgeny Pinchuk 5605b5c4e40SEvgeny Pinchuk i = 0; 5615b5c4e40SEvgeny Pinchuk list_for_each_entry(cache, &dev->cache_props, list) { 5625b5c4e40SEvgeny Pinchuk cache->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 5635b5c4e40SEvgeny Pinchuk if (!cache->kobj) 5645b5c4e40SEvgeny Pinchuk return -ENOMEM; 5655b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(cache->kobj, &cache_type, 5665b5c4e40SEvgeny Pinchuk dev->kobj_cache, "%d", i); 5675b5c4e40SEvgeny Pinchuk if (ret < 0) 5685b5c4e40SEvgeny Pinchuk return ret; 5695b5c4e40SEvgeny Pinchuk 5705b5c4e40SEvgeny Pinchuk cache->attr.name = "properties"; 5715b5c4e40SEvgeny Pinchuk cache->attr.mode = KFD_SYSFS_FILE_MODE; 5725b5c4e40SEvgeny Pinchuk sysfs_attr_init(&cache->attr); 5735b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(cache->kobj, &cache->attr); 5745b5c4e40SEvgeny Pinchuk if (ret < 0) 5755b5c4e40SEvgeny Pinchuk return ret; 5765b5c4e40SEvgeny Pinchuk i++; 5775b5c4e40SEvgeny Pinchuk } 5785b5c4e40SEvgeny Pinchuk 5795b5c4e40SEvgeny Pinchuk i = 0; 5805b5c4e40SEvgeny Pinchuk list_for_each_entry(iolink, &dev->io_link_props, list) { 5815b5c4e40SEvgeny Pinchuk iolink->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 5825b5c4e40SEvgeny Pinchuk if (!iolink->kobj) 5835b5c4e40SEvgeny Pinchuk return -ENOMEM; 5845b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(iolink->kobj, &iolink_type, 5855b5c4e40SEvgeny Pinchuk dev->kobj_iolink, "%d", i); 5865b5c4e40SEvgeny Pinchuk if (ret < 0) 5875b5c4e40SEvgeny Pinchuk return ret; 5885b5c4e40SEvgeny Pinchuk 5895b5c4e40SEvgeny Pinchuk iolink->attr.name = "properties"; 5905b5c4e40SEvgeny Pinchuk iolink->attr.mode = KFD_SYSFS_FILE_MODE; 5915b5c4e40SEvgeny Pinchuk sysfs_attr_init(&iolink->attr); 5925b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(iolink->kobj, &iolink->attr); 5935b5c4e40SEvgeny Pinchuk if (ret < 0) 5945b5c4e40SEvgeny Pinchuk return ret; 5955b5c4e40SEvgeny Pinchuk i++; 5965b5c4e40SEvgeny Pinchuk } 5975b5c4e40SEvgeny Pinchuk 5985b5c4e40SEvgeny Pinchuk return 0; 5995b5c4e40SEvgeny Pinchuk } 6005b5c4e40SEvgeny Pinchuk 6015b5c4e40SEvgeny Pinchuk static int kfd_build_sysfs_node_tree(void) 6025b5c4e40SEvgeny Pinchuk { 6035b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 6045b5c4e40SEvgeny Pinchuk int ret; 6055b5c4e40SEvgeny Pinchuk uint32_t i = 0; 6065b5c4e40SEvgeny Pinchuk 6075b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) { 6088dfead6cSBen Goz ret = kfd_build_sysfs_node_entry(dev, i); 6095b5c4e40SEvgeny Pinchuk if (ret < 0) 6105b5c4e40SEvgeny Pinchuk return ret; 6115b5c4e40SEvgeny Pinchuk i++; 6125b5c4e40SEvgeny Pinchuk } 6135b5c4e40SEvgeny Pinchuk 6145b5c4e40SEvgeny Pinchuk return 0; 6155b5c4e40SEvgeny Pinchuk } 6165b5c4e40SEvgeny Pinchuk 6175b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_node_tree(void) 6185b5c4e40SEvgeny Pinchuk { 6195b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 6205b5c4e40SEvgeny Pinchuk 6215b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) 6225b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_entry(dev); 6235b5c4e40SEvgeny Pinchuk } 6245b5c4e40SEvgeny Pinchuk 6255b5c4e40SEvgeny Pinchuk static int kfd_topology_update_sysfs(void) 6265b5c4e40SEvgeny Pinchuk { 6275b5c4e40SEvgeny Pinchuk int ret; 6285b5c4e40SEvgeny Pinchuk 6295b5c4e40SEvgeny Pinchuk pr_info("Creating topology SYSFS entries\n"); 6304eacc26bSKent Russell if (!sys_props.kobj_topology) { 6315b5c4e40SEvgeny Pinchuk sys_props.kobj_topology = 6325b5c4e40SEvgeny Pinchuk kfd_alloc_struct(sys_props.kobj_topology); 6335b5c4e40SEvgeny Pinchuk if (!sys_props.kobj_topology) 6345b5c4e40SEvgeny Pinchuk return -ENOMEM; 6355b5c4e40SEvgeny Pinchuk 6365b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(sys_props.kobj_topology, 6375b5c4e40SEvgeny Pinchuk &sysprops_type, &kfd_device->kobj, 6385b5c4e40SEvgeny Pinchuk "topology"); 6395b5c4e40SEvgeny Pinchuk if (ret < 0) 6405b5c4e40SEvgeny Pinchuk return ret; 6415b5c4e40SEvgeny Pinchuk 6425b5c4e40SEvgeny Pinchuk sys_props.kobj_nodes = kobject_create_and_add("nodes", 6435b5c4e40SEvgeny Pinchuk sys_props.kobj_topology); 6445b5c4e40SEvgeny Pinchuk if (!sys_props.kobj_nodes) 6455b5c4e40SEvgeny Pinchuk return -ENOMEM; 6465b5c4e40SEvgeny Pinchuk 6475b5c4e40SEvgeny Pinchuk sys_props.attr_genid.name = "generation_id"; 6485b5c4e40SEvgeny Pinchuk sys_props.attr_genid.mode = KFD_SYSFS_FILE_MODE; 6495b5c4e40SEvgeny Pinchuk sysfs_attr_init(&sys_props.attr_genid); 6505b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(sys_props.kobj_topology, 6515b5c4e40SEvgeny Pinchuk &sys_props.attr_genid); 6525b5c4e40SEvgeny Pinchuk if (ret < 0) 6535b5c4e40SEvgeny Pinchuk return ret; 6545b5c4e40SEvgeny Pinchuk 6555b5c4e40SEvgeny Pinchuk sys_props.attr_props.name = "system_properties"; 6565b5c4e40SEvgeny Pinchuk sys_props.attr_props.mode = KFD_SYSFS_FILE_MODE; 6575b5c4e40SEvgeny Pinchuk sysfs_attr_init(&sys_props.attr_props); 6585b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(sys_props.kobj_topology, 6595b5c4e40SEvgeny Pinchuk &sys_props.attr_props); 6605b5c4e40SEvgeny Pinchuk if (ret < 0) 6615b5c4e40SEvgeny Pinchuk return ret; 6625b5c4e40SEvgeny Pinchuk } 6635b5c4e40SEvgeny Pinchuk 6645b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_tree(); 6655b5c4e40SEvgeny Pinchuk 6665b5c4e40SEvgeny Pinchuk return kfd_build_sysfs_node_tree(); 6675b5c4e40SEvgeny Pinchuk } 6685b5c4e40SEvgeny Pinchuk 6695b5c4e40SEvgeny Pinchuk static void kfd_topology_release_sysfs(void) 6705b5c4e40SEvgeny Pinchuk { 6715b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_tree(); 6725b5c4e40SEvgeny Pinchuk if (sys_props.kobj_topology) { 6735b5c4e40SEvgeny Pinchuk sysfs_remove_file(sys_props.kobj_topology, 6745b5c4e40SEvgeny Pinchuk &sys_props.attr_genid); 6755b5c4e40SEvgeny Pinchuk sysfs_remove_file(sys_props.kobj_topology, 6765b5c4e40SEvgeny Pinchuk &sys_props.attr_props); 6775b5c4e40SEvgeny Pinchuk if (sys_props.kobj_nodes) { 6785b5c4e40SEvgeny Pinchuk kobject_del(sys_props.kobj_nodes); 6795b5c4e40SEvgeny Pinchuk kobject_put(sys_props.kobj_nodes); 68016b9201cSOded Gabbay sys_props.kobj_nodes = NULL; 6815b5c4e40SEvgeny Pinchuk } 6825b5c4e40SEvgeny Pinchuk kobject_del(sys_props.kobj_topology); 6835b5c4e40SEvgeny Pinchuk kobject_put(sys_props.kobj_topology); 68416b9201cSOded Gabbay sys_props.kobj_topology = NULL; 6855b5c4e40SEvgeny Pinchuk } 6865b5c4e40SEvgeny Pinchuk } 6875b5c4e40SEvgeny Pinchuk 6884f449311SHarish Kasiviswanathan /* Called with write topology_lock acquired */ 6894f449311SHarish Kasiviswanathan static void kfd_topology_update_device_list(struct list_head *temp_list, 6904f449311SHarish Kasiviswanathan struct list_head *master_list) 6914f449311SHarish Kasiviswanathan { 6924f449311SHarish Kasiviswanathan while (!list_empty(temp_list)) { 6934f449311SHarish Kasiviswanathan list_move_tail(temp_list->next, master_list); 6944f449311SHarish Kasiviswanathan sys_props.num_devices++; 6954f449311SHarish Kasiviswanathan } 6964f449311SHarish Kasiviswanathan } 6974f449311SHarish Kasiviswanathan 6985b5c4e40SEvgeny Pinchuk int kfd_topology_init(void) 6995b5c4e40SEvgeny Pinchuk { 70016b9201cSOded Gabbay void *crat_image = NULL; 7015b5c4e40SEvgeny Pinchuk size_t image_size = 0; 7025b5c4e40SEvgeny Pinchuk int ret; 7034f449311SHarish Kasiviswanathan struct list_head temp_topology_device_list; 7045b5c4e40SEvgeny Pinchuk 7054f449311SHarish Kasiviswanathan /* topology_device_list - Master list of all topology devices 7064f449311SHarish Kasiviswanathan * temp_topology_device_list - temporary list created while parsing CRAT 7074f449311SHarish Kasiviswanathan * or VCRAT. Once parsing is complete the contents of list is moved to 7084f449311SHarish Kasiviswanathan * topology_device_list 7095b5c4e40SEvgeny Pinchuk */ 7104f449311SHarish Kasiviswanathan 7114f449311SHarish Kasiviswanathan /* Initialize the head for the both the lists */ 7125b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&topology_device_list); 7134f449311SHarish Kasiviswanathan INIT_LIST_HEAD(&temp_topology_device_list); 7145b5c4e40SEvgeny Pinchuk init_rwsem(&topology_lock); 7155b5c4e40SEvgeny Pinchuk 7165b5c4e40SEvgeny Pinchuk memset(&sys_props, 0, sizeof(sys_props)); 7175b5c4e40SEvgeny Pinchuk 7185b5c4e40SEvgeny Pinchuk /* 7195b5c4e40SEvgeny Pinchuk * Get the CRAT image from the ACPI 7205b5c4e40SEvgeny Pinchuk */ 7218e05247dSHarish Kasiviswanathan ret = kfd_create_crat_image_acpi(&crat_image, &image_size); 7228e05247dSHarish Kasiviswanathan if (!ret) { 7234f449311SHarish Kasiviswanathan ret = kfd_parse_crat_table(crat_image, 7244f449311SHarish Kasiviswanathan &temp_topology_device_list, 0); 7258e05247dSHarish Kasiviswanathan if (ret) 7268e05247dSHarish Kasiviswanathan goto err; 7278e05247dSHarish Kasiviswanathan } else if (ret == -ENODATA) { 7288e05247dSHarish Kasiviswanathan /* TODO: Create fake CRAT table */ 7298e05247dSHarish Kasiviswanathan ret = 0; 7308e05247dSHarish Kasiviswanathan goto err; 7318e05247dSHarish Kasiviswanathan } else { 7328e05247dSHarish Kasiviswanathan pr_err("Couldn't get CRAT table size from ACPI\n"); 7335b5c4e40SEvgeny Pinchuk goto err; 7345b5c4e40SEvgeny Pinchuk } 7355b5c4e40SEvgeny Pinchuk 7365b5c4e40SEvgeny Pinchuk down_write(&topology_lock); 7374f449311SHarish Kasiviswanathan kfd_topology_update_device_list(&temp_topology_device_list, 7384f449311SHarish Kasiviswanathan &topology_device_list); 7395b5c4e40SEvgeny Pinchuk ret = kfd_topology_update_sysfs(); 7405b5c4e40SEvgeny Pinchuk up_write(&topology_lock); 7418e05247dSHarish Kasiviswanathan 7424f449311SHarish Kasiviswanathan if (!ret) { 7434f449311SHarish Kasiviswanathan sys_props.generation_count++; 7448e05247dSHarish Kasiviswanathan pr_info("Finished initializing topology\n"); 7454f449311SHarish Kasiviswanathan } else 7468e05247dSHarish Kasiviswanathan pr_err("Failed to update topology in sysfs ret=%d\n", ret); 7475b5c4e40SEvgeny Pinchuk 7485b5c4e40SEvgeny Pinchuk err: 7498e05247dSHarish Kasiviswanathan kfd_destroy_crat_image(crat_image); 7505b5c4e40SEvgeny Pinchuk return ret; 7515b5c4e40SEvgeny Pinchuk } 7525b5c4e40SEvgeny Pinchuk 7535b5c4e40SEvgeny Pinchuk void kfd_topology_shutdown(void) 7545b5c4e40SEvgeny Pinchuk { 7554f449311SHarish Kasiviswanathan down_write(&topology_lock); 7565b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 7575b5c4e40SEvgeny Pinchuk kfd_release_live_view(); 7584f449311SHarish Kasiviswanathan up_write(&topology_lock); 7595b5c4e40SEvgeny Pinchuk } 7605b5c4e40SEvgeny Pinchuk 7615b5c4e40SEvgeny Pinchuk static void kfd_debug_print_topology(void) 7625b5c4e40SEvgeny Pinchuk { 7635b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 7645b5c4e40SEvgeny Pinchuk uint32_t i = 0; 7655b5c4e40SEvgeny Pinchuk 7665b5c4e40SEvgeny Pinchuk pr_info("DEBUG PRINT OF TOPOLOGY:"); 7675b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) { 7685b5c4e40SEvgeny Pinchuk pr_info("Node: %d\n", i); 7695b5c4e40SEvgeny Pinchuk pr_info("\tGPU assigned: %s\n", (dev->gpu ? "yes" : "no")); 7705b5c4e40SEvgeny Pinchuk pr_info("\tCPU count: %d\n", dev->node_props.cpu_cores_count); 7718e05247dSHarish Kasiviswanathan pr_info("\tSIMD count: %d\n", dev->node_props.simd_count); 7725b5c4e40SEvgeny Pinchuk i++; 7735b5c4e40SEvgeny Pinchuk } 7745b5c4e40SEvgeny Pinchuk } 7755b5c4e40SEvgeny Pinchuk 7765b5c4e40SEvgeny Pinchuk static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu) 7775b5c4e40SEvgeny Pinchuk { 7785b5c4e40SEvgeny Pinchuk uint32_t hashout; 7795b5c4e40SEvgeny Pinchuk uint32_t buf[7]; 780585f0e6cSEdward O'Callaghan uint64_t local_mem_size; 7815b5c4e40SEvgeny Pinchuk int i; 7820504cccfSHarish Kasiviswanathan struct kfd_local_mem_info local_mem_info; 7835b5c4e40SEvgeny Pinchuk 7845b5c4e40SEvgeny Pinchuk if (!gpu) 7855b5c4e40SEvgeny Pinchuk return 0; 7865b5c4e40SEvgeny Pinchuk 7870504cccfSHarish Kasiviswanathan gpu->kfd2kgd->get_local_mem_info(gpu->kgd, &local_mem_info); 7880504cccfSHarish Kasiviswanathan 7890504cccfSHarish Kasiviswanathan local_mem_size = local_mem_info.local_mem_size_private + 7900504cccfSHarish Kasiviswanathan local_mem_info.local_mem_size_public; 791585f0e6cSEdward O'Callaghan 7925b5c4e40SEvgeny Pinchuk buf[0] = gpu->pdev->devfn; 7935b5c4e40SEvgeny Pinchuk buf[1] = gpu->pdev->subsystem_vendor; 7945b5c4e40SEvgeny Pinchuk buf[2] = gpu->pdev->subsystem_device; 7955b5c4e40SEvgeny Pinchuk buf[3] = gpu->pdev->device; 7965b5c4e40SEvgeny Pinchuk buf[4] = gpu->pdev->bus->number; 797585f0e6cSEdward O'Callaghan buf[5] = lower_32_bits(local_mem_size); 798585f0e6cSEdward O'Callaghan buf[6] = upper_32_bits(local_mem_size); 7995b5c4e40SEvgeny Pinchuk 8005b5c4e40SEvgeny Pinchuk for (i = 0, hashout = 0; i < 7; i++) 8015b5c4e40SEvgeny Pinchuk hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH); 8025b5c4e40SEvgeny Pinchuk 8035b5c4e40SEvgeny Pinchuk return hashout; 8045b5c4e40SEvgeny Pinchuk } 8055b5c4e40SEvgeny Pinchuk 8065b5c4e40SEvgeny Pinchuk static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) 8075b5c4e40SEvgeny Pinchuk { 8085b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 80916b9201cSOded Gabbay struct kfd_topology_device *out_dev = NULL; 8105b5c4e40SEvgeny Pinchuk 8115b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) 8124eacc26bSKent Russell if (!dev->gpu && (dev->node_props.simd_count > 0)) { 8135b5c4e40SEvgeny Pinchuk dev->gpu = gpu; 8145b5c4e40SEvgeny Pinchuk out_dev = dev; 8155b5c4e40SEvgeny Pinchuk break; 8165b5c4e40SEvgeny Pinchuk } 8175b5c4e40SEvgeny Pinchuk 8185b5c4e40SEvgeny Pinchuk return out_dev; 8195b5c4e40SEvgeny Pinchuk } 8205b5c4e40SEvgeny Pinchuk 8215b5c4e40SEvgeny Pinchuk static void kfd_notify_gpu_change(uint32_t gpu_id, int arrival) 8225b5c4e40SEvgeny Pinchuk { 8235b5c4e40SEvgeny Pinchuk /* 8245b5c4e40SEvgeny Pinchuk * TODO: Generate an event for thunk about the arrival/removal 8255b5c4e40SEvgeny Pinchuk * of the GPU 8265b5c4e40SEvgeny Pinchuk */ 8275b5c4e40SEvgeny Pinchuk } 8285b5c4e40SEvgeny Pinchuk 8295b5c4e40SEvgeny Pinchuk int kfd_topology_add_device(struct kfd_dev *gpu) 8305b5c4e40SEvgeny Pinchuk { 8315b5c4e40SEvgeny Pinchuk uint32_t gpu_id; 8325b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 833f7ce2fadSFlora Cui struct kfd_cu_info cu_info; 8344f449311SHarish Kasiviswanathan int res = 0; 8354f449311SHarish Kasiviswanathan struct list_head temp_topology_device_list; 8364f449311SHarish Kasiviswanathan 8374f449311SHarish Kasiviswanathan INIT_LIST_HEAD(&temp_topology_device_list); 8385b5c4e40SEvgeny Pinchuk 8395b5c4e40SEvgeny Pinchuk gpu_id = kfd_generate_gpu_id(gpu); 8405b5c4e40SEvgeny Pinchuk 84179775b62SKent Russell pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id); 8425b5c4e40SEvgeny Pinchuk 8435b5c4e40SEvgeny Pinchuk /* 8445b5c4e40SEvgeny Pinchuk * Try to assign the GPU to existing topology device (generated from 8455b5c4e40SEvgeny Pinchuk * CRAT table 8465b5c4e40SEvgeny Pinchuk */ 8475b5c4e40SEvgeny Pinchuk dev = kfd_assign_gpu(gpu); 8485b5c4e40SEvgeny Pinchuk if (!dev) { 8495b5c4e40SEvgeny Pinchuk pr_info("GPU was not found in the current topology. Extending.\n"); 8505b5c4e40SEvgeny Pinchuk kfd_debug_print_topology(); 8514f449311SHarish Kasiviswanathan dev = kfd_create_topology_device(&temp_topology_device_list); 8525b5c4e40SEvgeny Pinchuk if (!dev) { 8535b5c4e40SEvgeny Pinchuk res = -ENOMEM; 8545b5c4e40SEvgeny Pinchuk goto err; 8555b5c4e40SEvgeny Pinchuk } 8564f449311SHarish Kasiviswanathan 8575b5c4e40SEvgeny Pinchuk dev->gpu = gpu; 8585b5c4e40SEvgeny Pinchuk 8595b5c4e40SEvgeny Pinchuk /* 8605b5c4e40SEvgeny Pinchuk * TODO: Make a call to retrieve topology information from the 8615b5c4e40SEvgeny Pinchuk * GPU vBIOS 8625b5c4e40SEvgeny Pinchuk */ 8635b5c4e40SEvgeny Pinchuk 8644f449311SHarish Kasiviswanathan down_write(&topology_lock); 8654f449311SHarish Kasiviswanathan kfd_topology_update_device_list(&temp_topology_device_list, 8664f449311SHarish Kasiviswanathan &topology_device_list); 8674f449311SHarish Kasiviswanathan 8688eabaf54SKent Russell /* Update the SYSFS tree, since we added another topology 8698eabaf54SKent Russell * device 8705b5c4e40SEvgeny Pinchuk */ 8715b5c4e40SEvgeny Pinchuk if (kfd_topology_update_sysfs() < 0) 8725b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 8735b5c4e40SEvgeny Pinchuk 8744f449311SHarish Kasiviswanathan up_write(&topology_lock); 8754f449311SHarish Kasiviswanathan 8765b5c4e40SEvgeny Pinchuk } 8775b5c4e40SEvgeny Pinchuk 8785b5c4e40SEvgeny Pinchuk dev->gpu_id = gpu_id; 8795b5c4e40SEvgeny Pinchuk gpu->id = gpu_id; 880f7ce2fadSFlora Cui dev->gpu->kfd2kgd->get_cu_info(dev->gpu->kgd, &cu_info); 881f7ce2fadSFlora Cui dev->node_props.simd_count = dev->node_props.simd_per_cu * 882f7ce2fadSFlora Cui cu_info.cu_active_number; 8835b5c4e40SEvgeny Pinchuk dev->node_props.vendor_id = gpu->pdev->vendor; 8845b5c4e40SEvgeny Pinchuk dev->node_props.device_id = gpu->pdev->device; 885d63f0ba2SHarish Kasiviswanathan dev->node_props.location_id = PCI_DEVID(gpu->pdev->bus->number, 886d63f0ba2SHarish Kasiviswanathan gpu->pdev->devfn); 8875b5c4e40SEvgeny Pinchuk /* 8885b5c4e40SEvgeny Pinchuk * TODO: Retrieve max engine clock values from KGD 8895b5c4e40SEvgeny Pinchuk */ 8905b5c4e40SEvgeny Pinchuk 8917639a8c4SBen Goz if (dev->gpu->device_info->asic_family == CHIP_CARRIZO) { 8927639a8c4SBen Goz dev->node_props.capability |= HSA_CAP_DOORBELL_PACKET_TYPE; 89379775b62SKent Russell pr_info("Adding doorbell packet type capability\n"); 8947639a8c4SBen Goz } 8957639a8c4SBen Goz 8964f449311SHarish Kasiviswanathan if (!res) 8975b5c4e40SEvgeny Pinchuk kfd_notify_gpu_change(gpu_id, 1); 8984f449311SHarish Kasiviswanathan err: 8995b5c4e40SEvgeny Pinchuk return res; 9005b5c4e40SEvgeny Pinchuk } 9015b5c4e40SEvgeny Pinchuk 9025b5c4e40SEvgeny Pinchuk int kfd_topology_remove_device(struct kfd_dev *gpu) 9035b5c4e40SEvgeny Pinchuk { 9044f449311SHarish Kasiviswanathan struct kfd_topology_device *dev, *tmp; 9055b5c4e40SEvgeny Pinchuk uint32_t gpu_id; 9065b5c4e40SEvgeny Pinchuk int res = -ENODEV; 9075b5c4e40SEvgeny Pinchuk 9085b5c4e40SEvgeny Pinchuk down_write(&topology_lock); 9095b5c4e40SEvgeny Pinchuk 9104f449311SHarish Kasiviswanathan list_for_each_entry_safe(dev, tmp, &topology_device_list, list) 9115b5c4e40SEvgeny Pinchuk if (dev->gpu == gpu) { 9125b5c4e40SEvgeny Pinchuk gpu_id = dev->gpu_id; 9135b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_entry(dev); 9145b5c4e40SEvgeny Pinchuk kfd_release_topology_device(dev); 9154f449311SHarish Kasiviswanathan sys_props.num_devices--; 9165b5c4e40SEvgeny Pinchuk res = 0; 9175b5c4e40SEvgeny Pinchuk if (kfd_topology_update_sysfs() < 0) 9185b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 9195b5c4e40SEvgeny Pinchuk break; 9205b5c4e40SEvgeny Pinchuk } 9215b5c4e40SEvgeny Pinchuk 9225b5c4e40SEvgeny Pinchuk up_write(&topology_lock); 9235b5c4e40SEvgeny Pinchuk 924174de876SFelix Kuehling if (!res) 9255b5c4e40SEvgeny Pinchuk kfd_notify_gpu_change(gpu_id, 0); 9265b5c4e40SEvgeny Pinchuk 9275b5c4e40SEvgeny Pinchuk return res; 9285b5c4e40SEvgeny Pinchuk } 9295b5c4e40SEvgeny Pinchuk 930*6d82eb0eSHarish Kasiviswanathan /* kfd_topology_enum_kfd_devices - Enumerate through all devices in KFD 931*6d82eb0eSHarish Kasiviswanathan * topology. If GPU device is found @idx, then valid kfd_dev pointer is 932*6d82eb0eSHarish Kasiviswanathan * returned through @kdev 933*6d82eb0eSHarish Kasiviswanathan * Return - 0: On success (@kdev will be NULL for non GPU nodes) 934*6d82eb0eSHarish Kasiviswanathan * -1: If end of list 9355b5c4e40SEvgeny Pinchuk */ 936*6d82eb0eSHarish Kasiviswanathan int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev) 9375b5c4e40SEvgeny Pinchuk { 9385b5c4e40SEvgeny Pinchuk 9395b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 9405b5c4e40SEvgeny Pinchuk uint8_t device_idx = 0; 9415b5c4e40SEvgeny Pinchuk 942*6d82eb0eSHarish Kasiviswanathan *kdev = NULL; 9435b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 9445b5c4e40SEvgeny Pinchuk 9455b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) { 9465b5c4e40SEvgeny Pinchuk if (device_idx == idx) { 947*6d82eb0eSHarish Kasiviswanathan *kdev = top_dev->gpu; 948*6d82eb0eSHarish Kasiviswanathan up_read(&topology_lock); 949*6d82eb0eSHarish Kasiviswanathan return 0; 9505b5c4e40SEvgeny Pinchuk } 9515b5c4e40SEvgeny Pinchuk 9525b5c4e40SEvgeny Pinchuk device_idx++; 9535b5c4e40SEvgeny Pinchuk } 9545b5c4e40SEvgeny Pinchuk 9555b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 9565b5c4e40SEvgeny Pinchuk 957*6d82eb0eSHarish Kasiviswanathan return -1; 9585b5c4e40SEvgeny Pinchuk 9595b5c4e40SEvgeny Pinchuk } 960851a645eSFelix Kuehling 961851a645eSFelix Kuehling #if defined(CONFIG_DEBUG_FS) 962851a645eSFelix Kuehling 963851a645eSFelix Kuehling int kfd_debugfs_hqds_by_device(struct seq_file *m, void *data) 964851a645eSFelix Kuehling { 965851a645eSFelix Kuehling struct kfd_topology_device *dev; 966851a645eSFelix Kuehling unsigned int i = 0; 967851a645eSFelix Kuehling int r = 0; 968851a645eSFelix Kuehling 969851a645eSFelix Kuehling down_read(&topology_lock); 970851a645eSFelix Kuehling 971851a645eSFelix Kuehling list_for_each_entry(dev, &topology_device_list, list) { 972851a645eSFelix Kuehling if (!dev->gpu) { 973851a645eSFelix Kuehling i++; 974851a645eSFelix Kuehling continue; 975851a645eSFelix Kuehling } 976851a645eSFelix Kuehling 977851a645eSFelix Kuehling seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); 978851a645eSFelix Kuehling r = dqm_debugfs_hqds(m, dev->gpu->dqm); 979851a645eSFelix Kuehling if (r) 980851a645eSFelix Kuehling break; 981851a645eSFelix Kuehling } 982851a645eSFelix Kuehling 983851a645eSFelix Kuehling up_read(&topology_lock); 984851a645eSFelix Kuehling 985851a645eSFelix Kuehling return r; 986851a645eSFelix Kuehling } 987851a645eSFelix Kuehling 988851a645eSFelix Kuehling int kfd_debugfs_rls_by_device(struct seq_file *m, void *data) 989851a645eSFelix Kuehling { 990851a645eSFelix Kuehling struct kfd_topology_device *dev; 991851a645eSFelix Kuehling unsigned int i = 0; 992851a645eSFelix Kuehling int r = 0; 993851a645eSFelix Kuehling 994851a645eSFelix Kuehling down_read(&topology_lock); 995851a645eSFelix Kuehling 996851a645eSFelix Kuehling list_for_each_entry(dev, &topology_device_list, list) { 997851a645eSFelix Kuehling if (!dev->gpu) { 998851a645eSFelix Kuehling i++; 999851a645eSFelix Kuehling continue; 1000851a645eSFelix Kuehling } 1001851a645eSFelix Kuehling 1002851a645eSFelix Kuehling seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); 1003851a645eSFelix Kuehling r = pm_debugfs_runlist(m, &dev->gpu->dqm->packets); 1004851a645eSFelix Kuehling if (r) 1005851a645eSFelix Kuehling break; 1006851a645eSFelix Kuehling } 1007851a645eSFelix Kuehling 1008851a645eSFelix Kuehling up_read(&topology_lock); 1009851a645eSFelix Kuehling 1010851a645eSFelix Kuehling return r; 1011851a645eSFelix Kuehling } 1012851a645eSFelix Kuehling 1013851a645eSFelix Kuehling #endif 1014