1d87f36a0SRajneesh Bhardwaj // SPDX-License-Identifier: GPL-2.0 OR MIT 25b5c4e40SEvgeny Pinchuk /* 3d87f36a0SRajneesh Bhardwaj * Copyright 2014-2022 Advanced Micro Devices, Inc. 45b5c4e40SEvgeny Pinchuk * 55b5c4e40SEvgeny Pinchuk * Permission is hereby granted, free of charge, to any person obtaining a 65b5c4e40SEvgeny Pinchuk * copy of this software and associated documentation files (the "Software"), 75b5c4e40SEvgeny Pinchuk * to deal in the Software without restriction, including without limitation 85b5c4e40SEvgeny Pinchuk * the rights to use, copy, modify, merge, publish, distribute, sublicense, 95b5c4e40SEvgeny Pinchuk * and/or sell copies of the Software, and to permit persons to whom the 105b5c4e40SEvgeny Pinchuk * Software is furnished to do so, subject to the following conditions: 115b5c4e40SEvgeny Pinchuk * 125b5c4e40SEvgeny Pinchuk * The above copyright notice and this permission notice shall be included in 135b5c4e40SEvgeny Pinchuk * all copies or substantial portions of the Software. 145b5c4e40SEvgeny Pinchuk * 155b5c4e40SEvgeny Pinchuk * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 165b5c4e40SEvgeny Pinchuk * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 175b5c4e40SEvgeny Pinchuk * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 185b5c4e40SEvgeny Pinchuk * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 195b5c4e40SEvgeny Pinchuk * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 205b5c4e40SEvgeny Pinchuk * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 215b5c4e40SEvgeny Pinchuk * OTHER DEALINGS IN THE SOFTWARE. 225b5c4e40SEvgeny Pinchuk */ 235b5c4e40SEvgeny Pinchuk 245b5c4e40SEvgeny Pinchuk #include <linux/types.h> 255b5c4e40SEvgeny Pinchuk #include <linux/kernel.h> 265b5c4e40SEvgeny Pinchuk #include <linux/pci.h> 275b5c4e40SEvgeny Pinchuk #include <linux/errno.h> 285b5c4e40SEvgeny Pinchuk #include <linux/acpi.h> 295b5c4e40SEvgeny Pinchuk #include <linux/hash.h> 305b5c4e40SEvgeny Pinchuk #include <linux/cpufreq.h> 31f7c826adSAlexey Skidanov #include <linux/log2.h> 32520b8fb7SFelix Kuehling #include <linux/dmi.h> 33520b8fb7SFelix Kuehling #include <linux/atomic.h> 345b5c4e40SEvgeny Pinchuk 355b5c4e40SEvgeny Pinchuk #include "kfd_priv.h" 365b5c4e40SEvgeny Pinchuk #include "kfd_crat.h" 375b5c4e40SEvgeny Pinchuk #include "kfd_topology.h" 38851a645eSFelix Kuehling #include "kfd_device_queue_manager.h" 3964d1c3a4SFelix Kuehling #include "kfd_iommu.h" 405a75ea56SFelix Kuehling #include "kfd_svm.h" 415b87245fSAmber Lin #include "amdgpu_amdkfd.h" 420dee45a2SEric Huang #include "amdgpu_ras.h" 435b5c4e40SEvgeny Pinchuk 444f449311SHarish Kasiviswanathan /* topology_device_list - Master list of all topology devices */ 454f449311SHarish Kasiviswanathan static struct list_head topology_device_list; 46520b8fb7SFelix Kuehling static struct kfd_system_properties sys_props; 475b5c4e40SEvgeny Pinchuk 485b5c4e40SEvgeny Pinchuk static DECLARE_RWSEM(topology_lock); 49*46d18d51SMukul Joshi static uint32_t topology_crat_proximity_domain; 505b5c4e40SEvgeny Pinchuk 51*46d18d51SMukul Joshi struct kfd_topology_device *kfd_topology_device_by_proximity_domain_no_lock( 523a87177eSHarish Kasiviswanathan uint32_t proximity_domain) 533a87177eSHarish Kasiviswanathan { 543a87177eSHarish Kasiviswanathan struct kfd_topology_device *top_dev; 553a87177eSHarish Kasiviswanathan struct kfd_topology_device *device = NULL; 563a87177eSHarish Kasiviswanathan 573a87177eSHarish Kasiviswanathan list_for_each_entry(top_dev, &topology_device_list, list) 583a87177eSHarish Kasiviswanathan if (top_dev->proximity_domain == proximity_domain) { 593a87177eSHarish Kasiviswanathan device = top_dev; 603a87177eSHarish Kasiviswanathan break; 613a87177eSHarish Kasiviswanathan } 623a87177eSHarish Kasiviswanathan 63*46d18d51SMukul Joshi return device; 64*46d18d51SMukul Joshi } 65*46d18d51SMukul Joshi 66*46d18d51SMukul Joshi struct kfd_topology_device *kfd_topology_device_by_proximity_domain( 67*46d18d51SMukul Joshi uint32_t proximity_domain) 68*46d18d51SMukul Joshi { 69*46d18d51SMukul Joshi struct kfd_topology_device *device = NULL; 70*46d18d51SMukul Joshi 71*46d18d51SMukul Joshi down_read(&topology_lock); 72*46d18d51SMukul Joshi 73*46d18d51SMukul Joshi device = kfd_topology_device_by_proximity_domain_no_lock( 74*46d18d51SMukul Joshi proximity_domain); 753a87177eSHarish Kasiviswanathan up_read(&topology_lock); 763a87177eSHarish Kasiviswanathan 773a87177eSHarish Kasiviswanathan return device; 783a87177eSHarish Kasiviswanathan } 793a87177eSHarish Kasiviswanathan 8044d8cc6fSYong Zhao struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id) 815b5c4e40SEvgeny Pinchuk { 8244d8cc6fSYong Zhao struct kfd_topology_device *top_dev = NULL; 8344d8cc6fSYong Zhao struct kfd_topology_device *ret = NULL; 845b5c4e40SEvgeny Pinchuk 855b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 865b5c4e40SEvgeny Pinchuk 875b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) 885b5c4e40SEvgeny Pinchuk if (top_dev->gpu_id == gpu_id) { 8944d8cc6fSYong Zhao ret = top_dev; 905b5c4e40SEvgeny Pinchuk break; 915b5c4e40SEvgeny Pinchuk } 925b5c4e40SEvgeny Pinchuk 935b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 945b5c4e40SEvgeny Pinchuk 9544d8cc6fSYong Zhao return ret; 9644d8cc6fSYong Zhao } 9744d8cc6fSYong Zhao 9844d8cc6fSYong Zhao struct kfd_dev *kfd_device_by_id(uint32_t gpu_id) 9944d8cc6fSYong Zhao { 10044d8cc6fSYong Zhao struct kfd_topology_device *top_dev; 10144d8cc6fSYong Zhao 10244d8cc6fSYong Zhao top_dev = kfd_topology_device_by_id(gpu_id); 10344d8cc6fSYong Zhao if (!top_dev) 10444d8cc6fSYong Zhao return NULL; 10544d8cc6fSYong Zhao 10644d8cc6fSYong Zhao return top_dev->gpu; 1075b5c4e40SEvgeny Pinchuk } 1085b5c4e40SEvgeny Pinchuk 1095b5c4e40SEvgeny Pinchuk struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev) 1105b5c4e40SEvgeny Pinchuk { 1115b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 1125b5c4e40SEvgeny Pinchuk struct kfd_dev *device = NULL; 1135b5c4e40SEvgeny Pinchuk 1145b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 1155b5c4e40SEvgeny Pinchuk 1165b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) 1173704d56eSFelix Kuehling if (top_dev->gpu && top_dev->gpu->pdev == pdev) { 1185b5c4e40SEvgeny Pinchuk device = top_dev->gpu; 1195b5c4e40SEvgeny Pinchuk break; 1205b5c4e40SEvgeny Pinchuk } 1215b5c4e40SEvgeny Pinchuk 1225b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 1235b5c4e40SEvgeny Pinchuk 1245b5c4e40SEvgeny Pinchuk return device; 1255b5c4e40SEvgeny Pinchuk } 1265b5c4e40SEvgeny Pinchuk 127574c4183SGraham Sider struct kfd_dev *kfd_device_by_adev(const struct amdgpu_device *adev) 1281dde0ea9SFelix Kuehling { 1291dde0ea9SFelix Kuehling struct kfd_topology_device *top_dev; 1301dde0ea9SFelix Kuehling struct kfd_dev *device = NULL; 1311dde0ea9SFelix Kuehling 1321dde0ea9SFelix Kuehling down_read(&topology_lock); 1331dde0ea9SFelix Kuehling 1341dde0ea9SFelix Kuehling list_for_each_entry(top_dev, &topology_device_list, list) 135574c4183SGraham Sider if (top_dev->gpu && top_dev->gpu->adev == adev) { 1361dde0ea9SFelix Kuehling device = top_dev->gpu; 1371dde0ea9SFelix Kuehling break; 1381dde0ea9SFelix Kuehling } 1391dde0ea9SFelix Kuehling 1401dde0ea9SFelix Kuehling up_read(&topology_lock); 1411dde0ea9SFelix Kuehling 1421dde0ea9SFelix Kuehling return device; 1431dde0ea9SFelix Kuehling } 1441dde0ea9SFelix Kuehling 1453a87177eSHarish Kasiviswanathan /* Called with write topology_lock acquired */ 1465b5c4e40SEvgeny Pinchuk static void kfd_release_topology_device(struct kfd_topology_device *dev) 1475b5c4e40SEvgeny Pinchuk { 1485b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 1495b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 1505b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 151f4757347SAmber Lin struct kfd_perf_properties *perf; 1525b5c4e40SEvgeny Pinchuk 1535b5c4e40SEvgeny Pinchuk list_del(&dev->list); 1545b5c4e40SEvgeny Pinchuk 1555b5c4e40SEvgeny Pinchuk while (dev->mem_props.next != &dev->mem_props) { 1565b5c4e40SEvgeny Pinchuk mem = container_of(dev->mem_props.next, 1575b5c4e40SEvgeny Pinchuk struct kfd_mem_properties, list); 1585b5c4e40SEvgeny Pinchuk list_del(&mem->list); 1595b5c4e40SEvgeny Pinchuk kfree(mem); 1605b5c4e40SEvgeny Pinchuk } 1615b5c4e40SEvgeny Pinchuk 1625b5c4e40SEvgeny Pinchuk while (dev->cache_props.next != &dev->cache_props) { 1635b5c4e40SEvgeny Pinchuk cache = container_of(dev->cache_props.next, 1645b5c4e40SEvgeny Pinchuk struct kfd_cache_properties, list); 1655b5c4e40SEvgeny Pinchuk list_del(&cache->list); 1665b5c4e40SEvgeny Pinchuk kfree(cache); 1675b5c4e40SEvgeny Pinchuk } 1685b5c4e40SEvgeny Pinchuk 1695b5c4e40SEvgeny Pinchuk while (dev->io_link_props.next != &dev->io_link_props) { 1705b5c4e40SEvgeny Pinchuk iolink = container_of(dev->io_link_props.next, 1715b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties, list); 1725b5c4e40SEvgeny Pinchuk list_del(&iolink->list); 1735b5c4e40SEvgeny Pinchuk kfree(iolink); 1745b5c4e40SEvgeny Pinchuk } 1755b5c4e40SEvgeny Pinchuk 176f4757347SAmber Lin while (dev->perf_props.next != &dev->perf_props) { 177f4757347SAmber Lin perf = container_of(dev->perf_props.next, 178f4757347SAmber Lin struct kfd_perf_properties, list); 179f4757347SAmber Lin list_del(&perf->list); 180f4757347SAmber Lin kfree(perf); 181f4757347SAmber Lin } 182f4757347SAmber Lin 1835b5c4e40SEvgeny Pinchuk kfree(dev); 1845b5c4e40SEvgeny Pinchuk } 1855b5c4e40SEvgeny Pinchuk 1864f449311SHarish Kasiviswanathan void kfd_release_topology_device_list(struct list_head *device_list) 1875b5c4e40SEvgeny Pinchuk { 1885b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 1895b5c4e40SEvgeny Pinchuk 1904f449311SHarish Kasiviswanathan while (!list_empty(device_list)) { 1914f449311SHarish Kasiviswanathan dev = list_first_entry(device_list, 1925b5c4e40SEvgeny Pinchuk struct kfd_topology_device, list); 1935b5c4e40SEvgeny Pinchuk kfd_release_topology_device(dev); 1945b5c4e40SEvgeny Pinchuk } 1954f449311SHarish Kasiviswanathan } 1965b5c4e40SEvgeny Pinchuk 1974f449311SHarish Kasiviswanathan static void kfd_release_live_view(void) 1984f449311SHarish Kasiviswanathan { 1994f449311SHarish Kasiviswanathan kfd_release_topology_device_list(&topology_device_list); 2005b5c4e40SEvgeny Pinchuk memset(&sys_props, 0, sizeof(sys_props)); 2015b5c4e40SEvgeny Pinchuk } 2025b5c4e40SEvgeny Pinchuk 2034f449311SHarish Kasiviswanathan struct kfd_topology_device *kfd_create_topology_device( 2044f449311SHarish Kasiviswanathan struct list_head *device_list) 2055b5c4e40SEvgeny Pinchuk { 2065b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 2075b5c4e40SEvgeny Pinchuk 2085b5c4e40SEvgeny Pinchuk dev = kfd_alloc_struct(dev); 2094eacc26bSKent Russell if (!dev) { 2105b5c4e40SEvgeny Pinchuk pr_err("No memory to allocate a topology device"); 21116b9201cSOded Gabbay return NULL; 2125b5c4e40SEvgeny Pinchuk } 2135b5c4e40SEvgeny Pinchuk 2145b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->mem_props); 2155b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->cache_props); 2165b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&dev->io_link_props); 217f4757347SAmber Lin INIT_LIST_HEAD(&dev->perf_props); 2185b5c4e40SEvgeny Pinchuk 2194f449311SHarish Kasiviswanathan list_add_tail(&dev->list, device_list); 2205b5c4e40SEvgeny Pinchuk 2215b5c4e40SEvgeny Pinchuk return dev; 2225b5c4e40SEvgeny Pinchuk } 2235b5c4e40SEvgeny Pinchuk 2245b5c4e40SEvgeny Pinchuk 22583a13ef5SFelix Kuehling #define sysfs_show_gen_prop(buffer, offs, fmt, ...) \ 22683a13ef5SFelix Kuehling (offs += snprintf(buffer+offs, PAGE_SIZE-offs, \ 22783a13ef5SFelix Kuehling fmt, __VA_ARGS__)) 22883a13ef5SFelix Kuehling #define sysfs_show_32bit_prop(buffer, offs, name, value) \ 22983a13ef5SFelix Kuehling sysfs_show_gen_prop(buffer, offs, "%s %u\n", name, value) 23083a13ef5SFelix Kuehling #define sysfs_show_64bit_prop(buffer, offs, name, value) \ 23183a13ef5SFelix Kuehling sysfs_show_gen_prop(buffer, offs, "%s %llu\n", name, value) 23283a13ef5SFelix Kuehling #define sysfs_show_32bit_val(buffer, offs, value) \ 23383a13ef5SFelix Kuehling sysfs_show_gen_prop(buffer, offs, "%u\n", value) 23483a13ef5SFelix Kuehling #define sysfs_show_str_val(buffer, offs, value) \ 23583a13ef5SFelix Kuehling sysfs_show_gen_prop(buffer, offs, "%s\n", value) 2365b5c4e40SEvgeny Pinchuk 2375b5c4e40SEvgeny Pinchuk static ssize_t sysprops_show(struct kobject *kobj, struct attribute *attr, 2385b5c4e40SEvgeny Pinchuk char *buffer) 2395b5c4e40SEvgeny Pinchuk { 24083a13ef5SFelix Kuehling int offs = 0; 2415b5c4e40SEvgeny Pinchuk 2425b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2435b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2445b5c4e40SEvgeny Pinchuk 2455b5c4e40SEvgeny Pinchuk if (attr == &sys_props.attr_genid) { 24683a13ef5SFelix Kuehling sysfs_show_32bit_val(buffer, offs, 24783a13ef5SFelix Kuehling sys_props.generation_count); 2485b5c4e40SEvgeny Pinchuk } else if (attr == &sys_props.attr_props) { 24983a13ef5SFelix Kuehling sysfs_show_64bit_prop(buffer, offs, "platform_oem", 2505b5c4e40SEvgeny Pinchuk sys_props.platform_oem); 25183a13ef5SFelix Kuehling sysfs_show_64bit_prop(buffer, offs, "platform_id", 2525b5c4e40SEvgeny Pinchuk sys_props.platform_id); 25383a13ef5SFelix Kuehling sysfs_show_64bit_prop(buffer, offs, "platform_rev", 2545b5c4e40SEvgeny Pinchuk sys_props.platform_rev); 2555b5c4e40SEvgeny Pinchuk } else { 25683a13ef5SFelix Kuehling offs = -EINVAL; 2575b5c4e40SEvgeny Pinchuk } 2585b5c4e40SEvgeny Pinchuk 25983a13ef5SFelix Kuehling return offs; 2605b5c4e40SEvgeny Pinchuk } 2615b5c4e40SEvgeny Pinchuk 2625108d768SYong Zhao static void kfd_topology_kobj_release(struct kobject *kobj) 2635108d768SYong Zhao { 2645108d768SYong Zhao kfree(kobj); 2655108d768SYong Zhao } 2665108d768SYong Zhao 2675b5c4e40SEvgeny Pinchuk static const struct sysfs_ops sysprops_ops = { 2685b5c4e40SEvgeny Pinchuk .show = sysprops_show, 2695b5c4e40SEvgeny Pinchuk }; 2705b5c4e40SEvgeny Pinchuk 2715b5c4e40SEvgeny Pinchuk static struct kobj_type sysprops_type = { 2725108d768SYong Zhao .release = kfd_topology_kobj_release, 2735b5c4e40SEvgeny Pinchuk .sysfs_ops = &sysprops_ops, 2745b5c4e40SEvgeny Pinchuk }; 2755b5c4e40SEvgeny Pinchuk 2765b5c4e40SEvgeny Pinchuk static ssize_t iolink_show(struct kobject *kobj, struct attribute *attr, 2775b5c4e40SEvgeny Pinchuk char *buffer) 2785b5c4e40SEvgeny Pinchuk { 27983a13ef5SFelix Kuehling int offs = 0; 2805b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 2815b5c4e40SEvgeny Pinchuk 2825b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 2835b5c4e40SEvgeny Pinchuk buffer[0] = 0; 2845b5c4e40SEvgeny Pinchuk 2855b5c4e40SEvgeny Pinchuk iolink = container_of(attr, struct kfd_iolink_properties, attr); 2866b855f7bSHarish Kasiviswanathan if (iolink->gpu && kfd_devcgroup_check_permission(iolink->gpu)) 2876b855f7bSHarish Kasiviswanathan return -EPERM; 28883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "type", iolink->iolink_type); 28983a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "version_major", iolink->ver_maj); 29083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "version_minor", iolink->ver_min); 29183a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "node_from", iolink->node_from); 29283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "node_to", iolink->node_to); 29383a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "weight", iolink->weight); 29483a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "min_latency", iolink->min_latency); 29583a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "max_latency", iolink->max_latency); 29683a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "min_bandwidth", 29783a13ef5SFelix Kuehling iolink->min_bandwidth); 29883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "max_bandwidth", 29983a13ef5SFelix Kuehling iolink->max_bandwidth); 30083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "recommended_transfer_size", 3015b5c4e40SEvgeny Pinchuk iolink->rec_transfer_size); 30283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "flags", iolink->flags); 3035b5c4e40SEvgeny Pinchuk 30483a13ef5SFelix Kuehling return offs; 3055b5c4e40SEvgeny Pinchuk } 3065b5c4e40SEvgeny Pinchuk 3075b5c4e40SEvgeny Pinchuk static const struct sysfs_ops iolink_ops = { 3085b5c4e40SEvgeny Pinchuk .show = iolink_show, 3095b5c4e40SEvgeny Pinchuk }; 3105b5c4e40SEvgeny Pinchuk 3115b5c4e40SEvgeny Pinchuk static struct kobj_type iolink_type = { 3125108d768SYong Zhao .release = kfd_topology_kobj_release, 3135b5c4e40SEvgeny Pinchuk .sysfs_ops = &iolink_ops, 3145b5c4e40SEvgeny Pinchuk }; 3155b5c4e40SEvgeny Pinchuk 3165b5c4e40SEvgeny Pinchuk static ssize_t mem_show(struct kobject *kobj, struct attribute *attr, 3175b5c4e40SEvgeny Pinchuk char *buffer) 3185b5c4e40SEvgeny Pinchuk { 31983a13ef5SFelix Kuehling int offs = 0; 3205b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 3215b5c4e40SEvgeny Pinchuk 3225b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 3235b5c4e40SEvgeny Pinchuk buffer[0] = 0; 3245b5c4e40SEvgeny Pinchuk 3255b5c4e40SEvgeny Pinchuk mem = container_of(attr, struct kfd_mem_properties, attr); 3266b855f7bSHarish Kasiviswanathan if (mem->gpu && kfd_devcgroup_check_permission(mem->gpu)) 3276b855f7bSHarish Kasiviswanathan return -EPERM; 32883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "heap_type", mem->heap_type); 32983a13ef5SFelix Kuehling sysfs_show_64bit_prop(buffer, offs, "size_in_bytes", 33083a13ef5SFelix Kuehling mem->size_in_bytes); 33183a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "flags", mem->flags); 33283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "width", mem->width); 33383a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "mem_clk_max", 33483a13ef5SFelix Kuehling mem->mem_clk_max); 3355b5c4e40SEvgeny Pinchuk 33683a13ef5SFelix Kuehling return offs; 3375b5c4e40SEvgeny Pinchuk } 3385b5c4e40SEvgeny Pinchuk 3395b5c4e40SEvgeny Pinchuk static const struct sysfs_ops mem_ops = { 3405b5c4e40SEvgeny Pinchuk .show = mem_show, 3415b5c4e40SEvgeny Pinchuk }; 3425b5c4e40SEvgeny Pinchuk 3435b5c4e40SEvgeny Pinchuk static struct kobj_type mem_type = { 3445108d768SYong Zhao .release = kfd_topology_kobj_release, 3455b5c4e40SEvgeny Pinchuk .sysfs_ops = &mem_ops, 3465b5c4e40SEvgeny Pinchuk }; 3475b5c4e40SEvgeny Pinchuk 3485b5c4e40SEvgeny Pinchuk static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr, 3495b5c4e40SEvgeny Pinchuk char *buffer) 3505b5c4e40SEvgeny Pinchuk { 35183a13ef5SFelix Kuehling int offs = 0; 352bc0c75a3SHarish Kasiviswanathan uint32_t i, j; 3535b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 3545b5c4e40SEvgeny Pinchuk 3555b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 3565b5c4e40SEvgeny Pinchuk buffer[0] = 0; 3575b5c4e40SEvgeny Pinchuk 3585b5c4e40SEvgeny Pinchuk cache = container_of(attr, struct kfd_cache_properties, attr); 3596b855f7bSHarish Kasiviswanathan if (cache->gpu && kfd_devcgroup_check_permission(cache->gpu)) 3606b855f7bSHarish Kasiviswanathan return -EPERM; 36183a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "processor_id_low", 3625b5c4e40SEvgeny Pinchuk cache->processor_id_low); 36383a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "level", cache->cache_level); 36483a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "size", cache->cache_size); 36583a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "cache_line_size", 36683a13ef5SFelix Kuehling cache->cacheline_size); 36783a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "cache_lines_per_tag", 3685b5c4e40SEvgeny Pinchuk cache->cachelines_per_tag); 36983a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "association", cache->cache_assoc); 37083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "latency", cache->cache_latency); 37183a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "type", cache->cache_type); 37283a13ef5SFelix Kuehling offs += snprintf(buffer+offs, PAGE_SIZE-offs, "sibling_map "); 373bc0c75a3SHarish Kasiviswanathan for (i = 0; i < CRAT_SIBLINGMAP_SIZE; i++) 37483a13ef5SFelix Kuehling for (j = 0; j < sizeof(cache->sibling_map[0])*8; j++) 375bc0c75a3SHarish Kasiviswanathan /* Check each bit */ 37683a13ef5SFelix Kuehling offs += snprintf(buffer+offs, PAGE_SIZE-offs, "%d,", 37783a13ef5SFelix Kuehling (cache->sibling_map[i] >> j) & 1); 37883a13ef5SFelix Kuehling 379bc0c75a3SHarish Kasiviswanathan /* Replace the last "," with end of line */ 38083a13ef5SFelix Kuehling buffer[offs-1] = '\n'; 38183a13ef5SFelix Kuehling return offs; 3825b5c4e40SEvgeny Pinchuk } 3835b5c4e40SEvgeny Pinchuk 3845b5c4e40SEvgeny Pinchuk static const struct sysfs_ops cache_ops = { 3855b5c4e40SEvgeny Pinchuk .show = kfd_cache_show, 3865b5c4e40SEvgeny Pinchuk }; 3875b5c4e40SEvgeny Pinchuk 3885b5c4e40SEvgeny Pinchuk static struct kobj_type cache_type = { 3895108d768SYong Zhao .release = kfd_topology_kobj_release, 3905b5c4e40SEvgeny Pinchuk .sysfs_ops = &cache_ops, 3915b5c4e40SEvgeny Pinchuk }; 3925b5c4e40SEvgeny Pinchuk 393f4757347SAmber Lin /****** Sysfs of Performance Counters ******/ 394f4757347SAmber Lin 395f4757347SAmber Lin struct kfd_perf_attr { 396f4757347SAmber Lin struct kobj_attribute attr; 397f4757347SAmber Lin uint32_t data; 398f4757347SAmber Lin }; 399f4757347SAmber Lin 400f4757347SAmber Lin static ssize_t perf_show(struct kobject *kobj, struct kobj_attribute *attrs, 401f4757347SAmber Lin char *buf) 402f4757347SAmber Lin { 40383a13ef5SFelix Kuehling int offs = 0; 404f4757347SAmber Lin struct kfd_perf_attr *attr; 405f4757347SAmber Lin 406f4757347SAmber Lin buf[0] = 0; 407f4757347SAmber Lin attr = container_of(attrs, struct kfd_perf_attr, attr); 408f4757347SAmber Lin if (!attr->data) /* invalid data for PMC */ 409f4757347SAmber Lin return 0; 410f4757347SAmber Lin else 41183a13ef5SFelix Kuehling return sysfs_show_32bit_val(buf, offs, attr->data); 412f4757347SAmber Lin } 413f4757347SAmber Lin 414f4757347SAmber Lin #define KFD_PERF_DESC(_name, _data) \ 415f4757347SAmber Lin { \ 416f4757347SAmber Lin .attr = __ATTR(_name, 0444, perf_show, NULL), \ 417f4757347SAmber Lin .data = _data, \ 418f4757347SAmber Lin } 419f4757347SAmber Lin 420f4757347SAmber Lin static struct kfd_perf_attr perf_attr_iommu[] = { 421f4757347SAmber Lin KFD_PERF_DESC(max_concurrent, 0), 422f4757347SAmber Lin KFD_PERF_DESC(num_counters, 0), 423f4757347SAmber Lin KFD_PERF_DESC(counter_ids, 0), 424f4757347SAmber Lin }; 425f4757347SAmber Lin /****************************************/ 426f4757347SAmber Lin 4275b5c4e40SEvgeny Pinchuk static ssize_t node_show(struct kobject *kobj, struct attribute *attr, 4285b5c4e40SEvgeny Pinchuk char *buffer) 4295b5c4e40SEvgeny Pinchuk { 43083a13ef5SFelix Kuehling int offs = 0; 4315b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 432f7c826adSAlexey Skidanov uint32_t log_max_watch_addr; 4335b5c4e40SEvgeny Pinchuk 4345b5c4e40SEvgeny Pinchuk /* Making sure that the buffer is an empty string */ 4355b5c4e40SEvgeny Pinchuk buffer[0] = 0; 4365b5c4e40SEvgeny Pinchuk 4375b5c4e40SEvgeny Pinchuk if (strcmp(attr->name, "gpu_id") == 0) { 4385b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 4395b5c4e40SEvgeny Pinchuk attr_gpuid); 4406b855f7bSHarish Kasiviswanathan if (dev->gpu && kfd_devcgroup_check_permission(dev->gpu)) 4416b855f7bSHarish Kasiviswanathan return -EPERM; 44283a13ef5SFelix Kuehling return sysfs_show_32bit_val(buffer, offs, dev->gpu_id); 443f7c826adSAlexey Skidanov } 444f7c826adSAlexey Skidanov 445f7c826adSAlexey Skidanov if (strcmp(attr->name, "name") == 0) { 4465b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 4475b5c4e40SEvgeny Pinchuk attr_name); 448c181159aSYong Zhao 4496b855f7bSHarish Kasiviswanathan if (dev->gpu && kfd_devcgroup_check_permission(dev->gpu)) 4506b855f7bSHarish Kasiviswanathan return -EPERM; 45183a13ef5SFelix Kuehling return sysfs_show_str_val(buffer, offs, dev->node_props.name); 452f7c826adSAlexey Skidanov } 453f7c826adSAlexey Skidanov 4545b5c4e40SEvgeny Pinchuk dev = container_of(attr, struct kfd_topology_device, 4555b5c4e40SEvgeny Pinchuk attr_props); 4566b855f7bSHarish Kasiviswanathan if (dev->gpu && kfd_devcgroup_check_permission(dev->gpu)) 4576b855f7bSHarish Kasiviswanathan return -EPERM; 45883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "cpu_cores_count", 4595b5c4e40SEvgeny Pinchuk dev->node_props.cpu_cores_count); 46083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "simd_count", 4616127896fSHuang Rui dev->gpu ? dev->node_props.simd_count : 0); 46283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "mem_banks_count", 4635b5c4e40SEvgeny Pinchuk dev->node_props.mem_banks_count); 46483a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "caches_count", 4655b5c4e40SEvgeny Pinchuk dev->node_props.caches_count); 46683a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "io_links_count", 4675b5c4e40SEvgeny Pinchuk dev->node_props.io_links_count); 46883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "cpu_core_id_base", 4695b5c4e40SEvgeny Pinchuk dev->node_props.cpu_core_id_base); 47083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "simd_id_base", 4715b5c4e40SEvgeny Pinchuk dev->node_props.simd_id_base); 47283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "max_waves_per_simd", 4735b5c4e40SEvgeny Pinchuk dev->node_props.max_waves_per_simd); 47483a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "lds_size_in_kb", 4755b5c4e40SEvgeny Pinchuk dev->node_props.lds_size_in_kb); 47683a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "gds_size_in_kb", 4775b5c4e40SEvgeny Pinchuk dev->node_props.gds_size_in_kb); 47883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "num_gws", 47929e76462SOak Zeng dev->node_props.num_gws); 48083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "wave_front_size", 4815b5c4e40SEvgeny Pinchuk dev->node_props.wave_front_size); 48283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "array_count", 4835b5c4e40SEvgeny Pinchuk dev->node_props.array_count); 48483a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "simd_arrays_per_engine", 4855b5c4e40SEvgeny Pinchuk dev->node_props.simd_arrays_per_engine); 48683a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "cu_per_simd_array", 4875b5c4e40SEvgeny Pinchuk dev->node_props.cu_per_simd_array); 48883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "simd_per_cu", 4895b5c4e40SEvgeny Pinchuk dev->node_props.simd_per_cu); 49083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "max_slots_scratch_cu", 4915b5c4e40SEvgeny Pinchuk dev->node_props.max_slots_scratch_cu); 4929d6fa9c7SGraham Sider sysfs_show_32bit_prop(buffer, offs, "gfx_target_version", 4939d6fa9c7SGraham Sider dev->node_props.gfx_target_version); 49483a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "vendor_id", 4955b5c4e40SEvgeny Pinchuk dev->node_props.vendor_id); 49683a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "device_id", 4975b5c4e40SEvgeny Pinchuk dev->node_props.device_id); 49883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "location_id", 4995b5c4e40SEvgeny Pinchuk dev->node_props.location_id); 50083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "domain", 5013e58e95aSOri Messinger dev->node_props.domain); 50283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "drm_render_minor", 5037c9b7171SOak Zeng dev->node_props.drm_render_minor); 50483a13ef5SFelix Kuehling sysfs_show_64bit_prop(buffer, offs, "hive_id", 5050c1690e3SShaoyun Liu dev->node_props.hive_id); 50683a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "num_sdma_engines", 50714568cf6SOak Zeng dev->node_props.num_sdma_engines); 50883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "num_sdma_xgmi_engines", 50914568cf6SOak Zeng dev->node_props.num_sdma_xgmi_engines); 51083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "num_sdma_queues_per_engine", 511bb71c74dSHuang Rui dev->node_props.num_sdma_queues_per_engine); 51283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "num_cp_queues", 513f4feb9faSHuang Rui dev->node_props.num_cp_queues); 5145b5c4e40SEvgeny Pinchuk 5155b5c4e40SEvgeny Pinchuk if (dev->gpu) { 516f7c826adSAlexey Skidanov log_max_watch_addr = 517f0dc99a6SGraham Sider __ilog2_u32(dev->gpu->device_info.num_of_watch_points); 518f7c826adSAlexey Skidanov 519f7c826adSAlexey Skidanov if (log_max_watch_addr) { 520f7c826adSAlexey Skidanov dev->node_props.capability |= 521f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_SUPPORTED; 522f7c826adSAlexey Skidanov 523f7c826adSAlexey Skidanov dev->node_props.capability |= 524f7c826adSAlexey Skidanov ((log_max_watch_addr << 525f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_TOTALBITS_SHIFT) & 526f7c826adSAlexey Skidanov HSA_CAP_WATCH_POINTS_TOTALBITS_MASK); 527f7c826adSAlexey Skidanov } 528f7c826adSAlexey Skidanov 5297eb0502aSGraham Sider if (dev->gpu->adev->asic_type == CHIP_TONGA) 530413e85d5SBen Goz dev->node_props.capability |= 531413e85d5SBen Goz HSA_CAP_AQL_QUEUE_DOUBLE_MAP; 532413e85d5SBen Goz 53383a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "max_engine_clk_fcompute", 5343a87177eSHarish Kasiviswanathan dev->node_props.max_engine_clk_fcompute); 53542e08c78SOded Gabbay 53683a13ef5SFelix Kuehling sysfs_show_64bit_prop(buffer, offs, "local_mem_size", 0ULL); 537f1386fbcSOded Gabbay 53883a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "fw_version", 5395ade6c9cSFelix Kuehling dev->gpu->mec_fw_version); 54083a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "capability", 541826f5de8SAlexey Skidanov dev->node_props.capability); 54283a13ef5SFelix Kuehling sysfs_show_32bit_prop(buffer, offs, "sdma_fw_version", 5435ade6c9cSFelix Kuehling dev->gpu->sdma_fw_version); 54411964258SKent Russell sysfs_show_64bit_prop(buffer, offs, "unique_id", 54502274fc0SGraham Sider dev->gpu->adev->unique_id); 54611964258SKent Russell 5475b5c4e40SEvgeny Pinchuk } 5485b5c4e40SEvgeny Pinchuk 54983a13ef5SFelix Kuehling return sysfs_show_32bit_prop(buffer, offs, "max_engine_clk_ccompute", 5505b5c4e40SEvgeny Pinchuk cpufreq_quick_get_max(0)/1000); 5515b5c4e40SEvgeny Pinchuk } 5525b5c4e40SEvgeny Pinchuk 5535b5c4e40SEvgeny Pinchuk static const struct sysfs_ops node_ops = { 5545b5c4e40SEvgeny Pinchuk .show = node_show, 5555b5c4e40SEvgeny Pinchuk }; 5565b5c4e40SEvgeny Pinchuk 5575b5c4e40SEvgeny Pinchuk static struct kobj_type node_type = { 5585108d768SYong Zhao .release = kfd_topology_kobj_release, 5595b5c4e40SEvgeny Pinchuk .sysfs_ops = &node_ops, 5605b5c4e40SEvgeny Pinchuk }; 5615b5c4e40SEvgeny Pinchuk 5625b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_file(struct kobject *kobj, struct attribute *attr) 5635b5c4e40SEvgeny Pinchuk { 5645b5c4e40SEvgeny Pinchuk sysfs_remove_file(kobj, attr); 5655b5c4e40SEvgeny Pinchuk kobject_del(kobj); 5665b5c4e40SEvgeny Pinchuk kobject_put(kobj); 5675b5c4e40SEvgeny Pinchuk } 5685b5c4e40SEvgeny Pinchuk 5695b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_node_entry(struct kfd_topology_device *dev) 5705b5c4e40SEvgeny Pinchuk { 5715b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 5725b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 5735b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 574f4757347SAmber Lin struct kfd_perf_properties *perf; 5755b5c4e40SEvgeny Pinchuk 5765b5c4e40SEvgeny Pinchuk if (dev->kobj_iolink) { 5775b5c4e40SEvgeny Pinchuk list_for_each_entry(iolink, &dev->io_link_props, list) 5785b5c4e40SEvgeny Pinchuk if (iolink->kobj) { 5795b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(iolink->kobj, 5805b5c4e40SEvgeny Pinchuk &iolink->attr); 58116b9201cSOded Gabbay iolink->kobj = NULL; 5825b5c4e40SEvgeny Pinchuk } 5835b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_iolink); 5845b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_iolink); 58516b9201cSOded Gabbay dev->kobj_iolink = NULL; 5865b5c4e40SEvgeny Pinchuk } 5875b5c4e40SEvgeny Pinchuk 5885b5c4e40SEvgeny Pinchuk if (dev->kobj_cache) { 5895b5c4e40SEvgeny Pinchuk list_for_each_entry(cache, &dev->cache_props, list) 5905b5c4e40SEvgeny Pinchuk if (cache->kobj) { 5915b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(cache->kobj, 5925b5c4e40SEvgeny Pinchuk &cache->attr); 59316b9201cSOded Gabbay cache->kobj = NULL; 5945b5c4e40SEvgeny Pinchuk } 5955b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_cache); 5965b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_cache); 59716b9201cSOded Gabbay dev->kobj_cache = NULL; 5985b5c4e40SEvgeny Pinchuk } 5995b5c4e40SEvgeny Pinchuk 6005b5c4e40SEvgeny Pinchuk if (dev->kobj_mem) { 6015b5c4e40SEvgeny Pinchuk list_for_each_entry(mem, &dev->mem_props, list) 6025b5c4e40SEvgeny Pinchuk if (mem->kobj) { 6035b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_file(mem->kobj, &mem->attr); 60416b9201cSOded Gabbay mem->kobj = NULL; 6055b5c4e40SEvgeny Pinchuk } 6065b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_mem); 6075b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_mem); 60816b9201cSOded Gabbay dev->kobj_mem = NULL; 6095b5c4e40SEvgeny Pinchuk } 6105b5c4e40SEvgeny Pinchuk 611f4757347SAmber Lin if (dev->kobj_perf) { 612f4757347SAmber Lin list_for_each_entry(perf, &dev->perf_props, list) { 613f4757347SAmber Lin kfree(perf->attr_group); 614f4757347SAmber Lin perf->attr_group = NULL; 615f4757347SAmber Lin } 616f4757347SAmber Lin kobject_del(dev->kobj_perf); 617f4757347SAmber Lin kobject_put(dev->kobj_perf); 618f4757347SAmber Lin dev->kobj_perf = NULL; 619f4757347SAmber Lin } 620f4757347SAmber Lin 6215b5c4e40SEvgeny Pinchuk if (dev->kobj_node) { 6225b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_gpuid); 6235b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_name); 6245b5c4e40SEvgeny Pinchuk sysfs_remove_file(dev->kobj_node, &dev->attr_props); 6255b5c4e40SEvgeny Pinchuk kobject_del(dev->kobj_node); 6265b5c4e40SEvgeny Pinchuk kobject_put(dev->kobj_node); 62716b9201cSOded Gabbay dev->kobj_node = NULL; 6285b5c4e40SEvgeny Pinchuk } 6295b5c4e40SEvgeny Pinchuk } 6305b5c4e40SEvgeny Pinchuk 6315b5c4e40SEvgeny Pinchuk static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev, 6325b5c4e40SEvgeny Pinchuk uint32_t id) 6335b5c4e40SEvgeny Pinchuk { 6345b5c4e40SEvgeny Pinchuk struct kfd_iolink_properties *iolink; 6355b5c4e40SEvgeny Pinchuk struct kfd_cache_properties *cache; 6365b5c4e40SEvgeny Pinchuk struct kfd_mem_properties *mem; 637f4757347SAmber Lin struct kfd_perf_properties *perf; 6385b5c4e40SEvgeny Pinchuk int ret; 639f4757347SAmber Lin uint32_t i, num_attrs; 640f4757347SAmber Lin struct attribute **attrs; 6415b5c4e40SEvgeny Pinchuk 64232fa8219SFelix Kuehling if (WARN_ON(dev->kobj_node)) 64332fa8219SFelix Kuehling return -EEXIST; 64432fa8219SFelix Kuehling 6455b5c4e40SEvgeny Pinchuk /* 6465b5c4e40SEvgeny Pinchuk * Creating the sysfs folders 6475b5c4e40SEvgeny Pinchuk */ 6485b5c4e40SEvgeny Pinchuk dev->kobj_node = kfd_alloc_struct(dev->kobj_node); 6495b5c4e40SEvgeny Pinchuk if (!dev->kobj_node) 6505b5c4e40SEvgeny Pinchuk return -ENOMEM; 6515b5c4e40SEvgeny Pinchuk 6525b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(dev->kobj_node, &node_type, 6535b5c4e40SEvgeny Pinchuk sys_props.kobj_nodes, "%d", id); 65420eca012SQiushi Wu if (ret < 0) { 65520eca012SQiushi Wu kobject_put(dev->kobj_node); 6565b5c4e40SEvgeny Pinchuk return ret; 65720eca012SQiushi Wu } 6585b5c4e40SEvgeny Pinchuk 6595b5c4e40SEvgeny Pinchuk dev->kobj_mem = kobject_create_and_add("mem_banks", dev->kobj_node); 6605b5c4e40SEvgeny Pinchuk if (!dev->kobj_mem) 6615b5c4e40SEvgeny Pinchuk return -ENOMEM; 6625b5c4e40SEvgeny Pinchuk 6635b5c4e40SEvgeny Pinchuk dev->kobj_cache = kobject_create_and_add("caches", dev->kobj_node); 6645b5c4e40SEvgeny Pinchuk if (!dev->kobj_cache) 6655b5c4e40SEvgeny Pinchuk return -ENOMEM; 6665b5c4e40SEvgeny Pinchuk 6675b5c4e40SEvgeny Pinchuk dev->kobj_iolink = kobject_create_and_add("io_links", dev->kobj_node); 6685b5c4e40SEvgeny Pinchuk if (!dev->kobj_iolink) 6695b5c4e40SEvgeny Pinchuk return -ENOMEM; 6705b5c4e40SEvgeny Pinchuk 671f4757347SAmber Lin dev->kobj_perf = kobject_create_and_add("perf", dev->kobj_node); 672f4757347SAmber Lin if (!dev->kobj_perf) 673f4757347SAmber Lin return -ENOMEM; 674f4757347SAmber Lin 6755b5c4e40SEvgeny Pinchuk /* 6765b5c4e40SEvgeny Pinchuk * Creating sysfs files for node properties 6775b5c4e40SEvgeny Pinchuk */ 6785b5c4e40SEvgeny Pinchuk dev->attr_gpuid.name = "gpu_id"; 6795b5c4e40SEvgeny Pinchuk dev->attr_gpuid.mode = KFD_SYSFS_FILE_MODE; 6805b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_gpuid); 6815b5c4e40SEvgeny Pinchuk dev->attr_name.name = "name"; 6825b5c4e40SEvgeny Pinchuk dev->attr_name.mode = KFD_SYSFS_FILE_MODE; 6835b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_name); 6845b5c4e40SEvgeny Pinchuk dev->attr_props.name = "properties"; 6855b5c4e40SEvgeny Pinchuk dev->attr_props.mode = KFD_SYSFS_FILE_MODE; 6865b5c4e40SEvgeny Pinchuk sysfs_attr_init(&dev->attr_props); 6875b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_gpuid); 6885b5c4e40SEvgeny Pinchuk if (ret < 0) 6895b5c4e40SEvgeny Pinchuk return ret; 6905b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_name); 6915b5c4e40SEvgeny Pinchuk if (ret < 0) 6925b5c4e40SEvgeny Pinchuk return ret; 6935b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(dev->kobj_node, &dev->attr_props); 6945b5c4e40SEvgeny Pinchuk if (ret < 0) 6955b5c4e40SEvgeny Pinchuk return ret; 6965b5c4e40SEvgeny Pinchuk 6975b5c4e40SEvgeny Pinchuk i = 0; 6985b5c4e40SEvgeny Pinchuk list_for_each_entry(mem, &dev->mem_props, list) { 6995b5c4e40SEvgeny Pinchuk mem->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 7005b5c4e40SEvgeny Pinchuk if (!mem->kobj) 7015b5c4e40SEvgeny Pinchuk return -ENOMEM; 7025b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(mem->kobj, &mem_type, 7035b5c4e40SEvgeny Pinchuk dev->kobj_mem, "%d", i); 70420eca012SQiushi Wu if (ret < 0) { 70520eca012SQiushi Wu kobject_put(mem->kobj); 7065b5c4e40SEvgeny Pinchuk return ret; 70720eca012SQiushi Wu } 7085b5c4e40SEvgeny Pinchuk 7095b5c4e40SEvgeny Pinchuk mem->attr.name = "properties"; 7105b5c4e40SEvgeny Pinchuk mem->attr.mode = KFD_SYSFS_FILE_MODE; 7115b5c4e40SEvgeny Pinchuk sysfs_attr_init(&mem->attr); 7125b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(mem->kobj, &mem->attr); 7135b5c4e40SEvgeny Pinchuk if (ret < 0) 7145b5c4e40SEvgeny Pinchuk return ret; 7155b5c4e40SEvgeny Pinchuk i++; 7165b5c4e40SEvgeny Pinchuk } 7175b5c4e40SEvgeny Pinchuk 7185b5c4e40SEvgeny Pinchuk i = 0; 7195b5c4e40SEvgeny Pinchuk list_for_each_entry(cache, &dev->cache_props, list) { 7205b5c4e40SEvgeny Pinchuk cache->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 7215b5c4e40SEvgeny Pinchuk if (!cache->kobj) 7225b5c4e40SEvgeny Pinchuk return -ENOMEM; 7235b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(cache->kobj, &cache_type, 7245b5c4e40SEvgeny Pinchuk dev->kobj_cache, "%d", i); 72520eca012SQiushi Wu if (ret < 0) { 72620eca012SQiushi Wu kobject_put(cache->kobj); 7275b5c4e40SEvgeny Pinchuk return ret; 72820eca012SQiushi Wu } 7295b5c4e40SEvgeny Pinchuk 7305b5c4e40SEvgeny Pinchuk cache->attr.name = "properties"; 7315b5c4e40SEvgeny Pinchuk cache->attr.mode = KFD_SYSFS_FILE_MODE; 7325b5c4e40SEvgeny Pinchuk sysfs_attr_init(&cache->attr); 7335b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(cache->kobj, &cache->attr); 7345b5c4e40SEvgeny Pinchuk if (ret < 0) 7355b5c4e40SEvgeny Pinchuk return ret; 7365b5c4e40SEvgeny Pinchuk i++; 7375b5c4e40SEvgeny Pinchuk } 7385b5c4e40SEvgeny Pinchuk 7395b5c4e40SEvgeny Pinchuk i = 0; 7405b5c4e40SEvgeny Pinchuk list_for_each_entry(iolink, &dev->io_link_props, list) { 7415b5c4e40SEvgeny Pinchuk iolink->kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); 7425b5c4e40SEvgeny Pinchuk if (!iolink->kobj) 7435b5c4e40SEvgeny Pinchuk return -ENOMEM; 7445b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(iolink->kobj, &iolink_type, 7455b5c4e40SEvgeny Pinchuk dev->kobj_iolink, "%d", i); 74620eca012SQiushi Wu if (ret < 0) { 74720eca012SQiushi Wu kobject_put(iolink->kobj); 7485b5c4e40SEvgeny Pinchuk return ret; 74920eca012SQiushi Wu } 7505b5c4e40SEvgeny Pinchuk 7515b5c4e40SEvgeny Pinchuk iolink->attr.name = "properties"; 7525b5c4e40SEvgeny Pinchuk iolink->attr.mode = KFD_SYSFS_FILE_MODE; 7535b5c4e40SEvgeny Pinchuk sysfs_attr_init(&iolink->attr); 7545b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(iolink->kobj, &iolink->attr); 7555b5c4e40SEvgeny Pinchuk if (ret < 0) 7565b5c4e40SEvgeny Pinchuk return ret; 7575b5c4e40SEvgeny Pinchuk i++; 7585b5c4e40SEvgeny Pinchuk } 7595b5c4e40SEvgeny Pinchuk 760f4757347SAmber Lin /* All hardware blocks have the same number of attributes. */ 7613f866f5fSGustavo A. R. Silva num_attrs = ARRAY_SIZE(perf_attr_iommu); 762f4757347SAmber Lin list_for_each_entry(perf, &dev->perf_props, list) { 763f4757347SAmber Lin perf->attr_group = kzalloc(sizeof(struct kfd_perf_attr) 764f4757347SAmber Lin * num_attrs + sizeof(struct attribute_group), 765f4757347SAmber Lin GFP_KERNEL); 766f4757347SAmber Lin if (!perf->attr_group) 767f4757347SAmber Lin return -ENOMEM; 768f4757347SAmber Lin 769f4757347SAmber Lin attrs = (struct attribute **)(perf->attr_group + 1); 770f4757347SAmber Lin if (!strcmp(perf->block_name, "iommu")) { 771f4757347SAmber Lin /* Information of IOMMU's num_counters and counter_ids is shown 772f4757347SAmber Lin * under /sys/bus/event_source/devices/amd_iommu. We don't 773f4757347SAmber Lin * duplicate here. 774f4757347SAmber Lin */ 775f4757347SAmber Lin perf_attr_iommu[0].data = perf->max_concurrent; 776f4757347SAmber Lin for (i = 0; i < num_attrs; i++) 777f4757347SAmber Lin attrs[i] = &perf_attr_iommu[i].attr.attr; 778f4757347SAmber Lin } 779f4757347SAmber Lin perf->attr_group->name = perf->block_name; 780f4757347SAmber Lin perf->attr_group->attrs = attrs; 781f4757347SAmber Lin ret = sysfs_create_group(dev->kobj_perf, perf->attr_group); 782f4757347SAmber Lin if (ret < 0) 783f4757347SAmber Lin return ret; 784f4757347SAmber Lin } 785f4757347SAmber Lin 7865b5c4e40SEvgeny Pinchuk return 0; 7875b5c4e40SEvgeny Pinchuk } 7885b5c4e40SEvgeny Pinchuk 7893a87177eSHarish Kasiviswanathan /* Called with write topology lock acquired */ 7905b5c4e40SEvgeny Pinchuk static int kfd_build_sysfs_node_tree(void) 7915b5c4e40SEvgeny Pinchuk { 7925b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 7935b5c4e40SEvgeny Pinchuk int ret; 7945b5c4e40SEvgeny Pinchuk uint32_t i = 0; 7955b5c4e40SEvgeny Pinchuk 7965b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) { 7978dfead6cSBen Goz ret = kfd_build_sysfs_node_entry(dev, i); 7985b5c4e40SEvgeny Pinchuk if (ret < 0) 7995b5c4e40SEvgeny Pinchuk return ret; 8005b5c4e40SEvgeny Pinchuk i++; 8015b5c4e40SEvgeny Pinchuk } 8025b5c4e40SEvgeny Pinchuk 8035b5c4e40SEvgeny Pinchuk return 0; 8045b5c4e40SEvgeny Pinchuk } 8055b5c4e40SEvgeny Pinchuk 8063a87177eSHarish Kasiviswanathan /* Called with write topology lock acquired */ 8075b5c4e40SEvgeny Pinchuk static void kfd_remove_sysfs_node_tree(void) 8085b5c4e40SEvgeny Pinchuk { 8095b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 8105b5c4e40SEvgeny Pinchuk 8115b5c4e40SEvgeny Pinchuk list_for_each_entry(dev, &topology_device_list, list) 8125b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_entry(dev); 8135b5c4e40SEvgeny Pinchuk } 8145b5c4e40SEvgeny Pinchuk 8155b5c4e40SEvgeny Pinchuk static int kfd_topology_update_sysfs(void) 8165b5c4e40SEvgeny Pinchuk { 8175b5c4e40SEvgeny Pinchuk int ret; 8185b5c4e40SEvgeny Pinchuk 8194eacc26bSKent Russell if (!sys_props.kobj_topology) { 8205b5c4e40SEvgeny Pinchuk sys_props.kobj_topology = 8215b5c4e40SEvgeny Pinchuk kfd_alloc_struct(sys_props.kobj_topology); 8225b5c4e40SEvgeny Pinchuk if (!sys_props.kobj_topology) 8235b5c4e40SEvgeny Pinchuk return -ENOMEM; 8245b5c4e40SEvgeny Pinchuk 8255b5c4e40SEvgeny Pinchuk ret = kobject_init_and_add(sys_props.kobj_topology, 8265b5c4e40SEvgeny Pinchuk &sysprops_type, &kfd_device->kobj, 8275b5c4e40SEvgeny Pinchuk "topology"); 82820eca012SQiushi Wu if (ret < 0) { 82920eca012SQiushi Wu kobject_put(sys_props.kobj_topology); 8305b5c4e40SEvgeny Pinchuk return ret; 83120eca012SQiushi Wu } 8325b5c4e40SEvgeny Pinchuk 8335b5c4e40SEvgeny Pinchuk sys_props.kobj_nodes = kobject_create_and_add("nodes", 8345b5c4e40SEvgeny Pinchuk sys_props.kobj_topology); 8355b5c4e40SEvgeny Pinchuk if (!sys_props.kobj_nodes) 8365b5c4e40SEvgeny Pinchuk return -ENOMEM; 8375b5c4e40SEvgeny Pinchuk 8385b5c4e40SEvgeny Pinchuk sys_props.attr_genid.name = "generation_id"; 8395b5c4e40SEvgeny Pinchuk sys_props.attr_genid.mode = KFD_SYSFS_FILE_MODE; 8405b5c4e40SEvgeny Pinchuk sysfs_attr_init(&sys_props.attr_genid); 8415b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(sys_props.kobj_topology, 8425b5c4e40SEvgeny Pinchuk &sys_props.attr_genid); 8435b5c4e40SEvgeny Pinchuk if (ret < 0) 8445b5c4e40SEvgeny Pinchuk return ret; 8455b5c4e40SEvgeny Pinchuk 8465b5c4e40SEvgeny Pinchuk sys_props.attr_props.name = "system_properties"; 8475b5c4e40SEvgeny Pinchuk sys_props.attr_props.mode = KFD_SYSFS_FILE_MODE; 8485b5c4e40SEvgeny Pinchuk sysfs_attr_init(&sys_props.attr_props); 8495b5c4e40SEvgeny Pinchuk ret = sysfs_create_file(sys_props.kobj_topology, 8505b5c4e40SEvgeny Pinchuk &sys_props.attr_props); 8515b5c4e40SEvgeny Pinchuk if (ret < 0) 8525b5c4e40SEvgeny Pinchuk return ret; 8535b5c4e40SEvgeny Pinchuk } 8545b5c4e40SEvgeny Pinchuk 8555b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_tree(); 8565b5c4e40SEvgeny Pinchuk 8575b5c4e40SEvgeny Pinchuk return kfd_build_sysfs_node_tree(); 8585b5c4e40SEvgeny Pinchuk } 8595b5c4e40SEvgeny Pinchuk 8605b5c4e40SEvgeny Pinchuk static void kfd_topology_release_sysfs(void) 8615b5c4e40SEvgeny Pinchuk { 8625b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_tree(); 8635b5c4e40SEvgeny Pinchuk if (sys_props.kobj_topology) { 8645b5c4e40SEvgeny Pinchuk sysfs_remove_file(sys_props.kobj_topology, 8655b5c4e40SEvgeny Pinchuk &sys_props.attr_genid); 8665b5c4e40SEvgeny Pinchuk sysfs_remove_file(sys_props.kobj_topology, 8675b5c4e40SEvgeny Pinchuk &sys_props.attr_props); 8685b5c4e40SEvgeny Pinchuk if (sys_props.kobj_nodes) { 8695b5c4e40SEvgeny Pinchuk kobject_del(sys_props.kobj_nodes); 8705b5c4e40SEvgeny Pinchuk kobject_put(sys_props.kobj_nodes); 87116b9201cSOded Gabbay sys_props.kobj_nodes = NULL; 8725b5c4e40SEvgeny Pinchuk } 8735b5c4e40SEvgeny Pinchuk kobject_del(sys_props.kobj_topology); 8745b5c4e40SEvgeny Pinchuk kobject_put(sys_props.kobj_topology); 87516b9201cSOded Gabbay sys_props.kobj_topology = NULL; 8765b5c4e40SEvgeny Pinchuk } 8775b5c4e40SEvgeny Pinchuk } 8785b5c4e40SEvgeny Pinchuk 8794f449311SHarish Kasiviswanathan /* Called with write topology_lock acquired */ 8804f449311SHarish Kasiviswanathan static void kfd_topology_update_device_list(struct list_head *temp_list, 8814f449311SHarish Kasiviswanathan struct list_head *master_list) 8824f449311SHarish Kasiviswanathan { 8834f449311SHarish Kasiviswanathan while (!list_empty(temp_list)) { 8844f449311SHarish Kasiviswanathan list_move_tail(temp_list->next, master_list); 8854f449311SHarish Kasiviswanathan sys_props.num_devices++; 8864f449311SHarish Kasiviswanathan } 8874f449311SHarish Kasiviswanathan } 8884f449311SHarish Kasiviswanathan 889520b8fb7SFelix Kuehling static void kfd_debug_print_topology(void) 890520b8fb7SFelix Kuehling { 891520b8fb7SFelix Kuehling struct kfd_topology_device *dev; 892520b8fb7SFelix Kuehling 893520b8fb7SFelix Kuehling down_read(&topology_lock); 894520b8fb7SFelix Kuehling 895520b8fb7SFelix Kuehling dev = list_last_entry(&topology_device_list, 896520b8fb7SFelix Kuehling struct kfd_topology_device, list); 897520b8fb7SFelix Kuehling if (dev) { 898520b8fb7SFelix Kuehling if (dev->node_props.cpu_cores_count && 899520b8fb7SFelix Kuehling dev->node_props.simd_count) { 900520b8fb7SFelix Kuehling pr_info("Topology: Add APU node [0x%0x:0x%0x]\n", 901520b8fb7SFelix Kuehling dev->node_props.device_id, 902520b8fb7SFelix Kuehling dev->node_props.vendor_id); 903520b8fb7SFelix Kuehling } else if (dev->node_props.cpu_cores_count) 904520b8fb7SFelix Kuehling pr_info("Topology: Add CPU node\n"); 905520b8fb7SFelix Kuehling else if (dev->node_props.simd_count) 906520b8fb7SFelix Kuehling pr_info("Topology: Add dGPU node [0x%0x:0x%0x]\n", 907520b8fb7SFelix Kuehling dev->node_props.device_id, 908520b8fb7SFelix Kuehling dev->node_props.vendor_id); 909520b8fb7SFelix Kuehling } 910520b8fb7SFelix Kuehling up_read(&topology_lock); 911520b8fb7SFelix Kuehling } 912520b8fb7SFelix Kuehling 913520b8fb7SFelix Kuehling /* Helper function for intializing platform_xx members of 914520b8fb7SFelix Kuehling * kfd_system_properties. Uses OEM info from the last CPU/APU node. 915520b8fb7SFelix Kuehling */ 916520b8fb7SFelix Kuehling static void kfd_update_system_properties(void) 917520b8fb7SFelix Kuehling { 918520b8fb7SFelix Kuehling struct kfd_topology_device *dev; 919520b8fb7SFelix Kuehling 920520b8fb7SFelix Kuehling down_read(&topology_lock); 921520b8fb7SFelix Kuehling dev = list_last_entry(&topology_device_list, 922520b8fb7SFelix Kuehling struct kfd_topology_device, list); 923520b8fb7SFelix Kuehling if (dev) { 924520b8fb7SFelix Kuehling sys_props.platform_id = 925520b8fb7SFelix Kuehling (*((uint64_t *)dev->oem_id)) & CRAT_OEMID_64BIT_MASK; 926520b8fb7SFelix Kuehling sys_props.platform_oem = *((uint64_t *)dev->oem_table_id); 927520b8fb7SFelix Kuehling sys_props.platform_rev = dev->oem_revision; 928520b8fb7SFelix Kuehling } 929520b8fb7SFelix Kuehling up_read(&topology_lock); 930520b8fb7SFelix Kuehling } 931520b8fb7SFelix Kuehling 932520b8fb7SFelix Kuehling static void find_system_memory(const struct dmi_header *dm, 933520b8fb7SFelix Kuehling void *private) 934520b8fb7SFelix Kuehling { 935520b8fb7SFelix Kuehling struct kfd_mem_properties *mem; 936520b8fb7SFelix Kuehling u16 mem_width, mem_clock; 937520b8fb7SFelix Kuehling struct kfd_topology_device *kdev = 938520b8fb7SFelix Kuehling (struct kfd_topology_device *)private; 939520b8fb7SFelix Kuehling const u8 *dmi_data = (const u8 *)(dm + 1); 940520b8fb7SFelix Kuehling 941520b8fb7SFelix Kuehling if (dm->type == DMI_ENTRY_MEM_DEVICE && dm->length >= 0x15) { 942520b8fb7SFelix Kuehling mem_width = (u16)(*(const u16 *)(dmi_data + 0x6)); 943520b8fb7SFelix Kuehling mem_clock = (u16)(*(const u16 *)(dmi_data + 0x11)); 944520b8fb7SFelix Kuehling list_for_each_entry(mem, &kdev->mem_props, list) { 945520b8fb7SFelix Kuehling if (mem_width != 0xFFFF && mem_width != 0) 946520b8fb7SFelix Kuehling mem->width = mem_width; 947520b8fb7SFelix Kuehling if (mem_clock != 0) 948520b8fb7SFelix Kuehling mem->mem_clk_max = mem_clock; 949520b8fb7SFelix Kuehling } 950520b8fb7SFelix Kuehling } 951520b8fb7SFelix Kuehling } 952f4757347SAmber Lin 953f4757347SAmber Lin /* 954f4757347SAmber Lin * Performance counters information is not part of CRAT but we would like to 955f4757347SAmber Lin * put them in the sysfs under topology directory for Thunk to get the data. 956f4757347SAmber Lin * This function is called before updating the sysfs. 957f4757347SAmber Lin */ 958f4757347SAmber Lin static int kfd_add_perf_to_topology(struct kfd_topology_device *kdev) 959f4757347SAmber Lin { 96064d1c3a4SFelix Kuehling /* These are the only counters supported so far */ 96164d1c3a4SFelix Kuehling return kfd_iommu_add_perf_counters(kdev); 962f4757347SAmber Lin } 963f4757347SAmber Lin 964520b8fb7SFelix Kuehling /* kfd_add_non_crat_information - Add information that is not currently 965520b8fb7SFelix Kuehling * defined in CRAT but is necessary for KFD topology 966520b8fb7SFelix Kuehling * @dev - topology device to which addition info is added 967520b8fb7SFelix Kuehling */ 968520b8fb7SFelix Kuehling static void kfd_add_non_crat_information(struct kfd_topology_device *kdev) 969520b8fb7SFelix Kuehling { 970520b8fb7SFelix Kuehling /* Check if CPU only node. */ 971520b8fb7SFelix Kuehling if (!kdev->gpu) { 972520b8fb7SFelix Kuehling /* Add system memory information */ 973520b8fb7SFelix Kuehling dmi_walk(find_system_memory, kdev); 974520b8fb7SFelix Kuehling } 975520b8fb7SFelix Kuehling /* TODO: For GPU node, rearrange code from kfd_topology_add_device */ 976520b8fb7SFelix Kuehling } 977520b8fb7SFelix Kuehling 978b441093eSHarish Kasiviswanathan /* kfd_is_acpi_crat_invalid - CRAT from ACPI is valid only for AMD APU devices. 979b441093eSHarish Kasiviswanathan * Ignore CRAT for all other devices. AMD APU is identified if both CPU 980b441093eSHarish Kasiviswanathan * and GPU cores are present. 981b441093eSHarish Kasiviswanathan * @device_list - topology device list created by parsing ACPI CRAT table. 982b441093eSHarish Kasiviswanathan * @return - TRUE if invalid, FALSE is valid. 983b441093eSHarish Kasiviswanathan */ 984b441093eSHarish Kasiviswanathan static bool kfd_is_acpi_crat_invalid(struct list_head *device_list) 985b441093eSHarish Kasiviswanathan { 986b441093eSHarish Kasiviswanathan struct kfd_topology_device *dev; 987b441093eSHarish Kasiviswanathan 988b441093eSHarish Kasiviswanathan list_for_each_entry(dev, device_list, list) { 989b441093eSHarish Kasiviswanathan if (dev->node_props.cpu_cores_count && 990b441093eSHarish Kasiviswanathan dev->node_props.simd_count) 991b441093eSHarish Kasiviswanathan return false; 992b441093eSHarish Kasiviswanathan } 993b441093eSHarish Kasiviswanathan pr_info("Ignoring ACPI CRAT on non-APU system\n"); 994b441093eSHarish Kasiviswanathan return true; 995b441093eSHarish Kasiviswanathan } 996b441093eSHarish Kasiviswanathan 9975b5c4e40SEvgeny Pinchuk int kfd_topology_init(void) 9985b5c4e40SEvgeny Pinchuk { 99916b9201cSOded Gabbay void *crat_image = NULL; 10005b5c4e40SEvgeny Pinchuk size_t image_size = 0; 10015b5c4e40SEvgeny Pinchuk int ret; 10024f449311SHarish Kasiviswanathan struct list_head temp_topology_device_list; 1003520b8fb7SFelix Kuehling int cpu_only_node = 0; 1004520b8fb7SFelix Kuehling struct kfd_topology_device *kdev; 1005520b8fb7SFelix Kuehling int proximity_domain; 10065b5c4e40SEvgeny Pinchuk 10074f449311SHarish Kasiviswanathan /* topology_device_list - Master list of all topology devices 10084f449311SHarish Kasiviswanathan * temp_topology_device_list - temporary list created while parsing CRAT 10094f449311SHarish Kasiviswanathan * or VCRAT. Once parsing is complete the contents of list is moved to 10104f449311SHarish Kasiviswanathan * topology_device_list 10115b5c4e40SEvgeny Pinchuk */ 10124f449311SHarish Kasiviswanathan 10134f449311SHarish Kasiviswanathan /* Initialize the head for the both the lists */ 10145b5c4e40SEvgeny Pinchuk INIT_LIST_HEAD(&topology_device_list); 10154f449311SHarish Kasiviswanathan INIT_LIST_HEAD(&temp_topology_device_list); 10165b5c4e40SEvgeny Pinchuk init_rwsem(&topology_lock); 10175b5c4e40SEvgeny Pinchuk 10185b5c4e40SEvgeny Pinchuk memset(&sys_props, 0, sizeof(sys_props)); 10195b5c4e40SEvgeny Pinchuk 1020520b8fb7SFelix Kuehling /* Proximity domains in ACPI CRAT tables start counting at 1021520b8fb7SFelix Kuehling * 0. The same should be true for virtual CRAT tables created 1022520b8fb7SFelix Kuehling * at this stage. GPUs added later in kfd_topology_add_device 1023520b8fb7SFelix Kuehling * use a counter. 1024520b8fb7SFelix Kuehling */ 1025520b8fb7SFelix Kuehling proximity_domain = 0; 1026520b8fb7SFelix Kuehling 10275b5c4e40SEvgeny Pinchuk /* 1028520b8fb7SFelix Kuehling * Get the CRAT image from the ACPI. If ACPI doesn't have one 1029b441093eSHarish Kasiviswanathan * or if ACPI CRAT is invalid create a virtual CRAT. 1030520b8fb7SFelix Kuehling * NOTE: The current implementation expects all AMD APUs to have 1031520b8fb7SFelix Kuehling * CRAT. If no CRAT is available, it is assumed to be a CPU 10325b5c4e40SEvgeny Pinchuk */ 10338e05247dSHarish Kasiviswanathan ret = kfd_create_crat_image_acpi(&crat_image, &image_size); 10348e05247dSHarish Kasiviswanathan if (!ret) { 10354f449311SHarish Kasiviswanathan ret = kfd_parse_crat_table(crat_image, 1036520b8fb7SFelix Kuehling &temp_topology_device_list, 1037520b8fb7SFelix Kuehling proximity_domain); 1038b441093eSHarish Kasiviswanathan if (ret || 1039b441093eSHarish Kasiviswanathan kfd_is_acpi_crat_invalid(&temp_topology_device_list)) { 1040520b8fb7SFelix Kuehling kfd_release_topology_device_list( 1041520b8fb7SFelix Kuehling &temp_topology_device_list); 1042520b8fb7SFelix Kuehling kfd_destroy_crat_image(crat_image); 1043520b8fb7SFelix Kuehling crat_image = NULL; 1044520b8fb7SFelix Kuehling } 1045520b8fb7SFelix Kuehling } 1046520b8fb7SFelix Kuehling 1047520b8fb7SFelix Kuehling if (!crat_image) { 1048520b8fb7SFelix Kuehling ret = kfd_create_crat_image_virtual(&crat_image, &image_size, 1049520b8fb7SFelix Kuehling COMPUTE_UNIT_CPU, NULL, 1050520b8fb7SFelix Kuehling proximity_domain); 1051520b8fb7SFelix Kuehling cpu_only_node = 1; 1052520b8fb7SFelix Kuehling if (ret) { 1053520b8fb7SFelix Kuehling pr_err("Error creating VCRAT table for CPU\n"); 1054520b8fb7SFelix Kuehling return ret; 1055520b8fb7SFelix Kuehling } 1056520b8fb7SFelix Kuehling 1057520b8fb7SFelix Kuehling ret = kfd_parse_crat_table(crat_image, 1058520b8fb7SFelix Kuehling &temp_topology_device_list, 1059520b8fb7SFelix Kuehling proximity_domain); 1060520b8fb7SFelix Kuehling if (ret) { 1061520b8fb7SFelix Kuehling pr_err("Error parsing VCRAT table for CPU\n"); 10628e05247dSHarish Kasiviswanathan goto err; 1063520b8fb7SFelix Kuehling } 10645b5c4e40SEvgeny Pinchuk } 10655b5c4e40SEvgeny Pinchuk 1066f4757347SAmber Lin kdev = list_first_entry(&temp_topology_device_list, 1067f4757347SAmber Lin struct kfd_topology_device, list); 1068f4757347SAmber Lin kfd_add_perf_to_topology(kdev); 1069f4757347SAmber Lin 10705b5c4e40SEvgeny Pinchuk down_write(&topology_lock); 10714f449311SHarish Kasiviswanathan kfd_topology_update_device_list(&temp_topology_device_list, 10724f449311SHarish Kasiviswanathan &topology_device_list); 1073*46d18d51SMukul Joshi topology_crat_proximity_domain = sys_props.num_devices-1; 10745b5c4e40SEvgeny Pinchuk ret = kfd_topology_update_sysfs(); 10755b5c4e40SEvgeny Pinchuk up_write(&topology_lock); 10768e05247dSHarish Kasiviswanathan 10774f449311SHarish Kasiviswanathan if (!ret) { 10784f449311SHarish Kasiviswanathan sys_props.generation_count++; 1079520b8fb7SFelix Kuehling kfd_update_system_properties(); 1080520b8fb7SFelix Kuehling kfd_debug_print_topology(); 10814f449311SHarish Kasiviswanathan } else 10828e05247dSHarish Kasiviswanathan pr_err("Failed to update topology in sysfs ret=%d\n", ret); 10835b5c4e40SEvgeny Pinchuk 1084520b8fb7SFelix Kuehling /* For nodes with GPU, this information gets added 1085520b8fb7SFelix Kuehling * when GPU is detected (kfd_topology_add_device). 1086520b8fb7SFelix Kuehling */ 1087520b8fb7SFelix Kuehling if (cpu_only_node) { 1088520b8fb7SFelix Kuehling /* Add additional information to CPU only node created above */ 1089520b8fb7SFelix Kuehling down_write(&topology_lock); 1090520b8fb7SFelix Kuehling kdev = list_first_entry(&topology_device_list, 1091520b8fb7SFelix Kuehling struct kfd_topology_device, list); 1092520b8fb7SFelix Kuehling up_write(&topology_lock); 1093520b8fb7SFelix Kuehling kfd_add_non_crat_information(kdev); 1094520b8fb7SFelix Kuehling } 1095520b8fb7SFelix Kuehling 10965b5c4e40SEvgeny Pinchuk err: 10978e05247dSHarish Kasiviswanathan kfd_destroy_crat_image(crat_image); 10985b5c4e40SEvgeny Pinchuk return ret; 10995b5c4e40SEvgeny Pinchuk } 11005b5c4e40SEvgeny Pinchuk 11015b5c4e40SEvgeny Pinchuk void kfd_topology_shutdown(void) 11025b5c4e40SEvgeny Pinchuk { 11034f449311SHarish Kasiviswanathan down_write(&topology_lock); 11045b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 11055b5c4e40SEvgeny Pinchuk kfd_release_live_view(); 11064f449311SHarish Kasiviswanathan up_write(&topology_lock); 11075b5c4e40SEvgeny Pinchuk } 11085b5c4e40SEvgeny Pinchuk 11095b5c4e40SEvgeny Pinchuk static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu) 11105b5c4e40SEvgeny Pinchuk { 11115b5c4e40SEvgeny Pinchuk uint32_t hashout; 11125b5c4e40SEvgeny Pinchuk uint32_t buf[7]; 1113585f0e6cSEdward O'Callaghan uint64_t local_mem_size; 11145b5c4e40SEvgeny Pinchuk int i; 11150504cccfSHarish Kasiviswanathan struct kfd_local_mem_info local_mem_info; 11165b5c4e40SEvgeny Pinchuk 11175b5c4e40SEvgeny Pinchuk if (!gpu) 11185b5c4e40SEvgeny Pinchuk return 0; 11195b5c4e40SEvgeny Pinchuk 1120574c4183SGraham Sider amdgpu_amdkfd_get_local_mem_info(gpu->adev, &local_mem_info); 11210504cccfSHarish Kasiviswanathan 11220504cccfSHarish Kasiviswanathan local_mem_size = local_mem_info.local_mem_size_private + 11230504cccfSHarish Kasiviswanathan local_mem_info.local_mem_size_public; 1124585f0e6cSEdward O'Callaghan 11255b5c4e40SEvgeny Pinchuk buf[0] = gpu->pdev->devfn; 112646096058SAmber Lin buf[1] = gpu->pdev->subsystem_vendor | 112746096058SAmber Lin (gpu->pdev->subsystem_device << 16); 112846096058SAmber Lin buf[2] = pci_domain_nr(gpu->pdev->bus); 11295b5c4e40SEvgeny Pinchuk buf[3] = gpu->pdev->device; 11305b5c4e40SEvgeny Pinchuk buf[4] = gpu->pdev->bus->number; 1131585f0e6cSEdward O'Callaghan buf[5] = lower_32_bits(local_mem_size); 1132585f0e6cSEdward O'Callaghan buf[6] = upper_32_bits(local_mem_size); 11335b5c4e40SEvgeny Pinchuk 11345b5c4e40SEvgeny Pinchuk for (i = 0, hashout = 0; i < 7; i++) 11355b5c4e40SEvgeny Pinchuk hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH); 11365b5c4e40SEvgeny Pinchuk 11375b5c4e40SEvgeny Pinchuk return hashout; 11385b5c4e40SEvgeny Pinchuk } 11393a87177eSHarish Kasiviswanathan /* kfd_assign_gpu - Attach @gpu to the correct kfd topology device. If 11403a87177eSHarish Kasiviswanathan * the GPU device is not already present in the topology device 11413a87177eSHarish Kasiviswanathan * list then return NULL. This means a new topology device has to 11423a87177eSHarish Kasiviswanathan * be created for this GPU. 11433a87177eSHarish Kasiviswanathan */ 11445b5c4e40SEvgeny Pinchuk static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) 11455b5c4e40SEvgeny Pinchuk { 11465b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 114716b9201cSOded Gabbay struct kfd_topology_device *out_dev = NULL; 1148171bc67eSHarish Kasiviswanathan struct kfd_mem_properties *mem; 1149171bc67eSHarish Kasiviswanathan struct kfd_cache_properties *cache; 1150171bc67eSHarish Kasiviswanathan struct kfd_iolink_properties *iolink; 11515b5c4e40SEvgeny Pinchuk 11523a87177eSHarish Kasiviswanathan down_write(&topology_lock); 1153b8fe0524SFelix Kuehling list_for_each_entry(dev, &topology_device_list, list) { 1154b8fe0524SFelix Kuehling /* Discrete GPUs need their own topology device list 1155b8fe0524SFelix Kuehling * entries. Don't assign them to CPU/APU nodes. 1156b8fe0524SFelix Kuehling */ 11576127896fSHuang Rui if (!gpu->use_iommu_v2 && 1158b8fe0524SFelix Kuehling dev->node_props.cpu_cores_count) 1159b8fe0524SFelix Kuehling continue; 1160b8fe0524SFelix Kuehling 11614eacc26bSKent Russell if (!dev->gpu && (dev->node_props.simd_count > 0)) { 11625b5c4e40SEvgeny Pinchuk dev->gpu = gpu; 11635b5c4e40SEvgeny Pinchuk out_dev = dev; 1164171bc67eSHarish Kasiviswanathan 1165171bc67eSHarish Kasiviswanathan list_for_each_entry(mem, &dev->mem_props, list) 1166171bc67eSHarish Kasiviswanathan mem->gpu = dev->gpu; 1167171bc67eSHarish Kasiviswanathan list_for_each_entry(cache, &dev->cache_props, list) 1168171bc67eSHarish Kasiviswanathan cache->gpu = dev->gpu; 1169171bc67eSHarish Kasiviswanathan list_for_each_entry(iolink, &dev->io_link_props, list) 1170171bc67eSHarish Kasiviswanathan iolink->gpu = dev->gpu; 11715b5c4e40SEvgeny Pinchuk break; 11725b5c4e40SEvgeny Pinchuk } 1173b8fe0524SFelix Kuehling } 11743a87177eSHarish Kasiviswanathan up_write(&topology_lock); 11755b5c4e40SEvgeny Pinchuk return out_dev; 11765b5c4e40SEvgeny Pinchuk } 11775b5c4e40SEvgeny Pinchuk 11785b5c4e40SEvgeny Pinchuk static void kfd_notify_gpu_change(uint32_t gpu_id, int arrival) 11795b5c4e40SEvgeny Pinchuk { 11805b5c4e40SEvgeny Pinchuk /* 11815b5c4e40SEvgeny Pinchuk * TODO: Generate an event for thunk about the arrival/removal 11825b5c4e40SEvgeny Pinchuk * of the GPU 11835b5c4e40SEvgeny Pinchuk */ 11845b5c4e40SEvgeny Pinchuk } 11855b5c4e40SEvgeny Pinchuk 11863a87177eSHarish Kasiviswanathan /* kfd_fill_mem_clk_max_info - Since CRAT doesn't have memory clock info, 11873a87177eSHarish Kasiviswanathan * patch this after CRAT parsing. 11883a87177eSHarish Kasiviswanathan */ 11893a87177eSHarish Kasiviswanathan static void kfd_fill_mem_clk_max_info(struct kfd_topology_device *dev) 11903a87177eSHarish Kasiviswanathan { 11913a87177eSHarish Kasiviswanathan struct kfd_mem_properties *mem; 11923a87177eSHarish Kasiviswanathan struct kfd_local_mem_info local_mem_info; 11933a87177eSHarish Kasiviswanathan 11943a87177eSHarish Kasiviswanathan if (!dev) 11953a87177eSHarish Kasiviswanathan return; 11963a87177eSHarish Kasiviswanathan 11973a87177eSHarish Kasiviswanathan /* Currently, amdgpu driver (amdgpu_mc) deals only with GPUs with 11983a87177eSHarish Kasiviswanathan * single bank of VRAM local memory. 11993a87177eSHarish Kasiviswanathan * for dGPUs - VCRAT reports only one bank of Local Memory 12003a87177eSHarish Kasiviswanathan * for APUs - If CRAT from ACPI reports more than one bank, then 12013a87177eSHarish Kasiviswanathan * all the banks will report the same mem_clk_max information 12023a87177eSHarish Kasiviswanathan */ 1203574c4183SGraham Sider amdgpu_amdkfd_get_local_mem_info(dev->gpu->adev, &local_mem_info); 12043a87177eSHarish Kasiviswanathan 12053a87177eSHarish Kasiviswanathan list_for_each_entry(mem, &dev->mem_props, list) 12063a87177eSHarish Kasiviswanathan mem->mem_clk_max = local_mem_info.mem_clk_max; 12073a87177eSHarish Kasiviswanathan } 12083a87177eSHarish Kasiviswanathan 1209bdd24657SJonathan Kim static void kfd_set_iolink_no_atomics(struct kfd_topology_device *dev, 1210bdd24657SJonathan Kim struct kfd_topology_device *target_gpu_dev, 1211bdd24657SJonathan Kim struct kfd_iolink_properties *link) 12123a87177eSHarish Kasiviswanathan { 1213bdd24657SJonathan Kim /* xgmi always supports atomics between links. */ 1214bdd24657SJonathan Kim if (link->iolink_type == CRAT_IOLINK_TYPE_XGMI) 12153a87177eSHarish Kasiviswanathan return; 12163a87177eSHarish Kasiviswanathan 1217bdd24657SJonathan Kim /* check pcie support to set cpu(dev) flags for target_gpu_dev link. */ 1218bdd24657SJonathan Kim if (target_gpu_dev) { 1219bdd24657SJonathan Kim uint32_t cap; 1220bdd24657SJonathan Kim 1221bdd24657SJonathan Kim pcie_capability_read_dword(target_gpu_dev->gpu->pdev, 1222d35f00d8SEric Huang PCI_EXP_DEVCAP2, &cap); 1223d35f00d8SEric Huang 1224d35f00d8SEric Huang if (!(cap & (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | 1225d35f00d8SEric Huang PCI_EXP_DEVCAP2_ATOMIC_COMP64))) 1226bdd24657SJonathan Kim link->flags |= CRAT_IOLINK_FLAGS_NO_ATOMICS_32_BIT | 12273a87177eSHarish Kasiviswanathan CRAT_IOLINK_FLAGS_NO_ATOMICS_64_BIT; 1228bdd24657SJonathan Kim /* set gpu (dev) flags. */ 1229bdd24657SJonathan Kim } else { 1230d35f00d8SEric Huang if (!dev->gpu->pci_atomic_requested || 12317eb0502aSGraham Sider dev->gpu->adev->asic_type == CHIP_HAWAII) 1232bdd24657SJonathan Kim link->flags |= CRAT_IOLINK_FLAGS_NO_ATOMICS_32_BIT | 1233d35f00d8SEric Huang CRAT_IOLINK_FLAGS_NO_ATOMICS_64_BIT; 1234deb68983SJonathan Kim } 1235bdd24657SJonathan Kim } 1236bdd24657SJonathan Kim 1237c9cfbf7fSEric Huang static void kfd_set_iolink_non_coherent(struct kfd_topology_device *to_dev, 1238c9cfbf7fSEric Huang struct kfd_iolink_properties *outbound_link, 1239c9cfbf7fSEric Huang struct kfd_iolink_properties *inbound_link) 1240c9cfbf7fSEric Huang { 1241c9cfbf7fSEric Huang /* CPU -> GPU with PCIe */ 1242c9cfbf7fSEric Huang if (!to_dev->gpu && 1243c9cfbf7fSEric Huang inbound_link->iolink_type == CRAT_IOLINK_TYPE_PCIEXPRESS) 1244c9cfbf7fSEric Huang inbound_link->flags |= CRAT_IOLINK_FLAGS_NON_COHERENT; 1245c9cfbf7fSEric Huang 1246c9cfbf7fSEric Huang if (to_dev->gpu) { 1247c9cfbf7fSEric Huang /* GPU <-> GPU with PCIe and 1248c9cfbf7fSEric Huang * Vega20 with XGMI 1249c9cfbf7fSEric Huang */ 1250c9cfbf7fSEric Huang if (inbound_link->iolink_type == CRAT_IOLINK_TYPE_PCIEXPRESS || 1251c9cfbf7fSEric Huang (inbound_link->iolink_type == CRAT_IOLINK_TYPE_XGMI && 1252046e674bSGraham Sider KFD_GC_VERSION(to_dev->gpu) == IP_VERSION(9, 4, 0))) { 1253c9cfbf7fSEric Huang outbound_link->flags |= CRAT_IOLINK_FLAGS_NON_COHERENT; 1254c9cfbf7fSEric Huang inbound_link->flags |= CRAT_IOLINK_FLAGS_NON_COHERENT; 1255c9cfbf7fSEric Huang } 1256c9cfbf7fSEric Huang } 1257c9cfbf7fSEric Huang } 1258c9cfbf7fSEric Huang 1259bdd24657SJonathan Kim static void kfd_fill_iolink_non_crat_info(struct kfd_topology_device *dev) 1260bdd24657SJonathan Kim { 1261bdd24657SJonathan Kim struct kfd_iolink_properties *link, *inbound_link; 1262bdd24657SJonathan Kim struct kfd_topology_device *peer_dev; 1263bdd24657SJonathan Kim 1264bdd24657SJonathan Kim if (!dev || !dev->gpu) 1265bdd24657SJonathan Kim return; 1266d35f00d8SEric Huang 1267d35f00d8SEric Huang /* GPU only creates direct links so apply flags setting to all */ 1268d35f00d8SEric Huang list_for_each_entry(link, &dev->io_link_props, list) { 1269bdd24657SJonathan Kim link->flags = CRAT_IOLINK_FLAGS_ENABLED; 1270bdd24657SJonathan Kim kfd_set_iolink_no_atomics(dev, NULL, link); 1271bdd24657SJonathan Kim peer_dev = kfd_topology_device_by_proximity_domain( 1272d35f00d8SEric Huang link->node_to); 1273bdd24657SJonathan Kim 1274bdd24657SJonathan Kim if (!peer_dev) 1275bdd24657SJonathan Kim continue; 1276bdd24657SJonathan Kim 1277bdd24657SJonathan Kim list_for_each_entry(inbound_link, &peer_dev->io_link_props, 1278bdd24657SJonathan Kim list) { 1279bdd24657SJonathan Kim if (inbound_link->node_to != link->node_from) 1280bdd24657SJonathan Kim continue; 1281bdd24657SJonathan Kim 1282bdd24657SJonathan Kim inbound_link->flags = CRAT_IOLINK_FLAGS_ENABLED; 1283bdd24657SJonathan Kim kfd_set_iolink_no_atomics(peer_dev, dev, inbound_link); 1284c9cfbf7fSEric Huang kfd_set_iolink_non_coherent(peer_dev, link, inbound_link); 1285d35f00d8SEric Huang } 1286d35f00d8SEric Huang } 12873a87177eSHarish Kasiviswanathan } 12883a87177eSHarish Kasiviswanathan 12895b5c4e40SEvgeny Pinchuk int kfd_topology_add_device(struct kfd_dev *gpu) 12905b5c4e40SEvgeny Pinchuk { 12915b5c4e40SEvgeny Pinchuk uint32_t gpu_id; 12925b5c4e40SEvgeny Pinchuk struct kfd_topology_device *dev; 1293f7ce2fadSFlora Cui struct kfd_cu_info cu_info; 12944f449311SHarish Kasiviswanathan int res = 0; 12954f449311SHarish Kasiviswanathan struct list_head temp_topology_device_list; 12963a87177eSHarish Kasiviswanathan void *crat_image = NULL; 12973a87177eSHarish Kasiviswanathan size_t image_size = 0; 12983a87177eSHarish Kasiviswanathan int proximity_domain; 1299b7675b7bSGraham Sider int i; 1300b7675b7bSGraham Sider const char *asic_name = amdgpu_asic_name[gpu->adev->asic_type]; 13014f449311SHarish Kasiviswanathan 13024f449311SHarish Kasiviswanathan INIT_LIST_HEAD(&temp_topology_device_list); 13035b5c4e40SEvgeny Pinchuk 13045b5c4e40SEvgeny Pinchuk gpu_id = kfd_generate_gpu_id(gpu); 13055b5c4e40SEvgeny Pinchuk 130679775b62SKent Russell pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id); 13075b5c4e40SEvgeny Pinchuk 1308d5edb56fSJonathan Kim /* Include the CPU in xGMI hive if xGMI connected by assigning it the hive ID. */ 130956c5977eSGraham Sider if (gpu->hive_id && gpu->adev->gmc.xgmi.connected_to_cpu) { 1310d5edb56fSJonathan Kim struct kfd_topology_device *top_dev; 1311d5edb56fSJonathan Kim 1312d5edb56fSJonathan Kim down_read(&topology_lock); 1313d5edb56fSJonathan Kim 1314d5edb56fSJonathan Kim list_for_each_entry(top_dev, &topology_device_list, list) { 1315d5edb56fSJonathan Kim if (top_dev->gpu) 1316d5edb56fSJonathan Kim break; 1317d5edb56fSJonathan Kim 1318d5edb56fSJonathan Kim top_dev->node_props.hive_id = gpu->hive_id; 1319d5edb56fSJonathan Kim } 1320d5edb56fSJonathan Kim 1321d5edb56fSJonathan Kim up_read(&topology_lock); 1322d5edb56fSJonathan Kim } 1323d5edb56fSJonathan Kim 13243a87177eSHarish Kasiviswanathan /* Check to see if this gpu device exists in the topology_device_list. 13253a87177eSHarish Kasiviswanathan * If so, assign the gpu to that device, 13263a87177eSHarish Kasiviswanathan * else create a Virtual CRAT for this gpu device and then parse that 13273a87177eSHarish Kasiviswanathan * CRAT to create a new topology device. Once created assign the gpu to 13283a87177eSHarish Kasiviswanathan * that topology device 13295b5c4e40SEvgeny Pinchuk */ 13305b5c4e40SEvgeny Pinchuk dev = kfd_assign_gpu(gpu); 13315b5c4e40SEvgeny Pinchuk if (!dev) { 1332*46d18d51SMukul Joshi down_write(&topology_lock); 1333*46d18d51SMukul Joshi proximity_domain = ++topology_crat_proximity_domain; 1334*46d18d51SMukul Joshi 13353a87177eSHarish Kasiviswanathan res = kfd_create_crat_image_virtual(&crat_image, &image_size, 13363a87177eSHarish Kasiviswanathan COMPUTE_UNIT_GPU, gpu, 13373a87177eSHarish Kasiviswanathan proximity_domain); 13383a87177eSHarish Kasiviswanathan if (res) { 13393a87177eSHarish Kasiviswanathan pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n", 13403a87177eSHarish Kasiviswanathan gpu_id); 1341*46d18d51SMukul Joshi topology_crat_proximity_domain--; 13423a87177eSHarish Kasiviswanathan return res; 13433a87177eSHarish Kasiviswanathan } 13443a87177eSHarish Kasiviswanathan res = kfd_parse_crat_table(crat_image, 13453a87177eSHarish Kasiviswanathan &temp_topology_device_list, 13463a87177eSHarish Kasiviswanathan proximity_domain); 13473a87177eSHarish Kasiviswanathan if (res) { 13483a87177eSHarish Kasiviswanathan pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n", 13493a87177eSHarish Kasiviswanathan gpu_id); 1350*46d18d51SMukul Joshi topology_crat_proximity_domain--; 13515b5c4e40SEvgeny Pinchuk goto err; 13525b5c4e40SEvgeny Pinchuk } 13534f449311SHarish Kasiviswanathan 13544f449311SHarish Kasiviswanathan kfd_topology_update_device_list(&temp_topology_device_list, 13554f449311SHarish Kasiviswanathan &topology_device_list); 13564f449311SHarish Kasiviswanathan 13578eabaf54SKent Russell /* Update the SYSFS tree, since we added another topology 13588eabaf54SKent Russell * device 13595b5c4e40SEvgeny Pinchuk */ 13603a87177eSHarish Kasiviswanathan res = kfd_topology_update_sysfs(); 13614f449311SHarish Kasiviswanathan up_write(&topology_lock); 13624f449311SHarish Kasiviswanathan 13633a87177eSHarish Kasiviswanathan if (!res) 13643a87177eSHarish Kasiviswanathan sys_props.generation_count++; 13653a87177eSHarish Kasiviswanathan else 13663a87177eSHarish Kasiviswanathan pr_err("Failed to update GPU (ID: 0x%x) to sysfs topology. res=%d\n", 13673a87177eSHarish Kasiviswanathan gpu_id, res); 13683a87177eSHarish Kasiviswanathan dev = kfd_assign_gpu(gpu); 13693a87177eSHarish Kasiviswanathan if (WARN_ON(!dev)) { 13703a87177eSHarish Kasiviswanathan res = -ENODEV; 13713a87177eSHarish Kasiviswanathan goto err; 13723a87177eSHarish Kasiviswanathan } 13735b5c4e40SEvgeny Pinchuk } 13745b5c4e40SEvgeny Pinchuk 13755b5c4e40SEvgeny Pinchuk dev->gpu_id = gpu_id; 13765b5c4e40SEvgeny Pinchuk gpu->id = gpu_id; 13773a87177eSHarish Kasiviswanathan 13783a87177eSHarish Kasiviswanathan /* TODO: Move the following lines to function 13793a87177eSHarish Kasiviswanathan * kfd_add_non_crat_information 13803a87177eSHarish Kasiviswanathan */ 13813a87177eSHarish Kasiviswanathan 13823a87177eSHarish Kasiviswanathan /* Fill-in additional information that is not available in CRAT but 13833a87177eSHarish Kasiviswanathan * needed for the topology 13843a87177eSHarish Kasiviswanathan */ 13853a87177eSHarish Kasiviswanathan 1386574c4183SGraham Sider amdgpu_amdkfd_get_cu_info(dev->gpu->adev, &cu_info); 1387c181159aSYong Zhao 1388b7675b7bSGraham Sider for (i = 0; i < KFD_TOPOLOGY_PUBLIC_NAME_SIZE-1; i++) { 1389b7675b7bSGraham Sider dev->node_props.name[i] = __tolower(asic_name[i]); 1390b7675b7bSGraham Sider if (asic_name[i] == '\0') 1391b7675b7bSGraham Sider break; 1392b7675b7bSGraham Sider } 1393b7675b7bSGraham Sider dev->node_props.name[i] = '\0'; 1394c181159aSYong Zhao 13953a87177eSHarish Kasiviswanathan dev->node_props.simd_arrays_per_engine = 13963a87177eSHarish Kasiviswanathan cu_info.num_shader_arrays_per_engine; 13973a87177eSHarish Kasiviswanathan 1398f0dc99a6SGraham Sider dev->node_props.gfx_target_version = gpu->device_info.gfx_target_version; 13995b5c4e40SEvgeny Pinchuk dev->node_props.vendor_id = gpu->pdev->vendor; 14005b5c4e40SEvgeny Pinchuk dev->node_props.device_id = gpu->pdev->device; 1401c6d1ec41SJoseph Greathouse dev->node_props.capability |= 140202274fc0SGraham Sider ((dev->gpu->adev->rev_id << HSA_CAP_ASIC_REVISION_SHIFT) & 1403c6d1ec41SJoseph Greathouse HSA_CAP_ASIC_REVISION_MASK); 1404babe2ef3SHeiner Kallweit dev->node_props.location_id = pci_dev_id(gpu->pdev); 14053e58e95aSOri Messinger dev->node_props.domain = pci_domain_nr(gpu->pdev->bus); 14063a87177eSHarish Kasiviswanathan dev->node_props.max_engine_clk_fcompute = 1407574c4183SGraham Sider amdgpu_amdkfd_get_max_engine_clock_in_mhz(dev->gpu->adev); 14083a87177eSHarish Kasiviswanathan dev->node_props.max_engine_clk_ccompute = 14093a87177eSHarish Kasiviswanathan cpufreq_quick_get_max(0) / 1000; 14107c9b7171SOak Zeng dev->node_props.drm_render_minor = 14117c9b7171SOak Zeng gpu->shared_resources.drm_render_minor; 14125b5c4e40SEvgeny Pinchuk 14130c1690e3SShaoyun Liu dev->node_props.hive_id = gpu->hive_id; 1414ee2f17f4SAmber Lin dev->node_props.num_sdma_engines = kfd_get_num_sdma_engines(gpu); 141514568cf6SOak Zeng dev->node_props.num_sdma_xgmi_engines = 1416ee2f17f4SAmber Lin kfd_get_num_xgmi_sdma_engines(gpu); 1417bb71c74dSHuang Rui dev->node_props.num_sdma_queues_per_engine = 1418f0dc99a6SGraham Sider gpu->device_info.num_sdma_queues_per_engine; 141929633d0eSJoseph Greathouse dev->node_props.num_gws = (dev->gpu->gws && 142029e76462SOak Zeng dev->gpu->dqm->sched_policy != KFD_SCHED_POLICY_NO_HWS) ? 142102274fc0SGraham Sider dev->gpu->adev->gds.gws_size : 0; 1422e6945304SYong Zhao dev->node_props.num_cp_queues = get_cp_queues_num(dev->gpu->dqm); 14230c1690e3SShaoyun Liu 14243a87177eSHarish Kasiviswanathan kfd_fill_mem_clk_max_info(dev); 14253a87177eSHarish Kasiviswanathan kfd_fill_iolink_non_crat_info(dev); 14263a87177eSHarish Kasiviswanathan 14277eb0502aSGraham Sider switch (dev->gpu->adev->asic_type) { 14283a87177eSHarish Kasiviswanathan case CHIP_KAVERI: 14293a87177eSHarish Kasiviswanathan case CHIP_HAWAII: 14303a87177eSHarish Kasiviswanathan case CHIP_TONGA: 14313a87177eSHarish Kasiviswanathan dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_PRE_1_0 << 14323a87177eSHarish Kasiviswanathan HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) & 14333a87177eSHarish Kasiviswanathan HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK); 14343a87177eSHarish Kasiviswanathan break; 14353a87177eSHarish Kasiviswanathan case CHIP_CARRIZO: 14363a87177eSHarish Kasiviswanathan case CHIP_FIJI: 14373a87177eSHarish Kasiviswanathan case CHIP_POLARIS10: 14383a87177eSHarish Kasiviswanathan case CHIP_POLARIS11: 1439846a44d7SGang Ba case CHIP_POLARIS12: 1440ed81cd6eSKent Russell case CHIP_VEGAM: 144142aa8793SFelix Kuehling pr_debug("Adding doorbell packet type capability\n"); 14423a87177eSHarish Kasiviswanathan dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_1_0 << 14433a87177eSHarish Kasiviswanathan HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) & 14443a87177eSHarish Kasiviswanathan HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK); 14453a87177eSHarish Kasiviswanathan break; 1446e4804a39SGraham Sider default: 1447e4804a39SGraham Sider if (KFD_GC_VERSION(dev->gpu) >= IP_VERSION(9, 0, 1)) 1448389056e5SFelix Kuehling dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 << 1449389056e5SFelix Kuehling HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) & 1450389056e5SFelix Kuehling HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK); 1451e4804a39SGraham Sider else 14523a87177eSHarish Kasiviswanathan WARN(1, "Unexpected ASIC family %u", 14537eb0502aSGraham Sider dev->gpu->adev->asic_type); 14547639a8c4SBen Goz } 14557639a8c4SBen Goz 14561ae99eabSOak Zeng /* 14571ae99eabSOak Zeng * Overwrite ATS capability according to needs_iommu_device to fix 14581ae99eabSOak Zeng * potential missing corresponding bit in CRAT of BIOS. 14591ae99eabSOak Zeng */ 14606127896fSHuang Rui if (dev->gpu->use_iommu_v2) 14611ae99eabSOak Zeng dev->node_props.capability |= HSA_CAP_ATS_PRESENT; 14621ae99eabSOak Zeng else 14631ae99eabSOak Zeng dev->node_props.capability &= ~HSA_CAP_ATS_PRESENT; 14641ae99eabSOak Zeng 14653a87177eSHarish Kasiviswanathan /* Fix errors in CZ CRAT. 14663a87177eSHarish Kasiviswanathan * simd_count: Carrizo CRAT reports wrong simd_count, probably 14673a87177eSHarish Kasiviswanathan * because it doesn't consider masked out CUs 146870f372bfSPhilip Cox * max_waves_per_simd: Carrizo reports wrong max_waves_per_simd 14693a87177eSHarish Kasiviswanathan */ 14707eb0502aSGraham Sider if (dev->gpu->adev->asic_type == CHIP_CARRIZO) { 14713a87177eSHarish Kasiviswanathan dev->node_props.simd_count = 14723a87177eSHarish Kasiviswanathan cu_info.simd_per_cu * cu_info.cu_active_number; 147370f372bfSPhilip Cox dev->node_props.max_waves_per_simd = 10; 147470f372bfSPhilip Cox } 14753a87177eSHarish Kasiviswanathan 14765436ab94SStanley.Yang /* kfd only concerns sram ecc on GFX and HBM ecc on UMC */ 14770dee45a2SEric Huang dev->node_props.capability |= 147856c5977eSGraham Sider ((dev->gpu->adev->ras_enabled & BIT(AMDGPU_RAS_BLOCK__GFX)) != 0) ? 14790dee45a2SEric Huang HSA_CAP_SRAM_EDCSUPPORTED : 0; 148056c5977eSGraham Sider dev->node_props.capability |= 148156c5977eSGraham Sider ((dev->gpu->adev->ras_enabled & BIT(AMDGPU_RAS_BLOCK__UMC)) != 0) ? 14820dee45a2SEric Huang HSA_CAP_MEM_EDCSUPPORTED : 0; 14830dee45a2SEric Huang 1484046e674bSGraham Sider if (KFD_GC_VERSION(dev->gpu) != IP_VERSION(9, 0, 1)) 148556c5977eSGraham Sider dev->node_props.capability |= (dev->gpu->adev->ras_enabled != 0) ? 14860dee45a2SEric Huang HSA_CAP_RASEVENTNOTIFY : 0; 14870dee45a2SEric Huang 148856c5977eSGraham Sider if (KFD_IS_SVM_API_SUPPORTED(dev->gpu->adev->kfd.dev)) 14894c166eb9SPhilip Yang dev->node_props.capability |= HSA_CAP_SVMAPI_SUPPORTED; 14904c166eb9SPhilip Yang 14913a87177eSHarish Kasiviswanathan kfd_debug_print_topology(); 14923a87177eSHarish Kasiviswanathan 14934f449311SHarish Kasiviswanathan if (!res) 14945b5c4e40SEvgeny Pinchuk kfd_notify_gpu_change(gpu_id, 1); 14954f449311SHarish Kasiviswanathan err: 14963a87177eSHarish Kasiviswanathan kfd_destroy_crat_image(crat_image); 14975b5c4e40SEvgeny Pinchuk return res; 14985b5c4e40SEvgeny Pinchuk } 14995b5c4e40SEvgeny Pinchuk 1500*46d18d51SMukul Joshi /** 1501*46d18d51SMukul Joshi * kfd_topology_update_io_links() - Update IO links after device removal. 1502*46d18d51SMukul Joshi * @proximity_domain: Proximity domain value of the dev being removed. 1503*46d18d51SMukul Joshi * 1504*46d18d51SMukul Joshi * The topology list currently is arranged in increasing order of 1505*46d18d51SMukul Joshi * proximity domain. 1506*46d18d51SMukul Joshi * 1507*46d18d51SMukul Joshi * Two things need to be done when a device is removed: 1508*46d18d51SMukul Joshi * 1. All the IO links to this device need to be removed. 1509*46d18d51SMukul Joshi * 2. All nodes after the current device node need to move 1510*46d18d51SMukul Joshi * up once this device node is removed from the topology 1511*46d18d51SMukul Joshi * list. As a result, the proximity domain values for 1512*46d18d51SMukul Joshi * all nodes after the node being deleted reduce by 1. 1513*46d18d51SMukul Joshi * This would also cause the proximity domain values for 1514*46d18d51SMukul Joshi * io links to be updated based on new proximity domain 1515*46d18d51SMukul Joshi * values. 1516*46d18d51SMukul Joshi * 1517*46d18d51SMukul Joshi * Context: The caller must hold write topology_lock. 1518*46d18d51SMukul Joshi */ 1519*46d18d51SMukul Joshi static void kfd_topology_update_io_links(int proximity_domain) 1520*46d18d51SMukul Joshi { 1521*46d18d51SMukul Joshi struct kfd_topology_device *dev; 1522*46d18d51SMukul Joshi struct kfd_iolink_properties *iolink, *tmp; 1523*46d18d51SMukul Joshi 1524*46d18d51SMukul Joshi list_for_each_entry(dev, &topology_device_list, list) { 1525*46d18d51SMukul Joshi if (dev->proximity_domain > proximity_domain) 1526*46d18d51SMukul Joshi dev->proximity_domain--; 1527*46d18d51SMukul Joshi 1528*46d18d51SMukul Joshi list_for_each_entry_safe(iolink, tmp, &dev->io_link_props, list) { 1529*46d18d51SMukul Joshi /* 1530*46d18d51SMukul Joshi * If there is an io link to the dev being deleted 1531*46d18d51SMukul Joshi * then remove that IO link also. 1532*46d18d51SMukul Joshi */ 1533*46d18d51SMukul Joshi if (iolink->node_to == proximity_domain) { 1534*46d18d51SMukul Joshi list_del(&iolink->list); 1535*46d18d51SMukul Joshi dev->io_link_count--; 1536*46d18d51SMukul Joshi dev->node_props.io_links_count--; 1537*46d18d51SMukul Joshi } else if (iolink->node_from > proximity_domain) { 1538*46d18d51SMukul Joshi iolink->node_from--; 1539*46d18d51SMukul Joshi } else if (iolink->node_to > proximity_domain) { 1540*46d18d51SMukul Joshi iolink->node_to--; 1541*46d18d51SMukul Joshi } 1542*46d18d51SMukul Joshi } 1543*46d18d51SMukul Joshi 1544*46d18d51SMukul Joshi } 1545*46d18d51SMukul Joshi } 1546*46d18d51SMukul Joshi 15475b5c4e40SEvgeny Pinchuk int kfd_topology_remove_device(struct kfd_dev *gpu) 15485b5c4e40SEvgeny Pinchuk { 15494f449311SHarish Kasiviswanathan struct kfd_topology_device *dev, *tmp; 15505b5c4e40SEvgeny Pinchuk uint32_t gpu_id; 15515b5c4e40SEvgeny Pinchuk int res = -ENODEV; 1552*46d18d51SMukul Joshi int i = 0; 15535b5c4e40SEvgeny Pinchuk 15545b5c4e40SEvgeny Pinchuk down_write(&topology_lock); 15555b5c4e40SEvgeny Pinchuk 1556*46d18d51SMukul Joshi list_for_each_entry_safe(dev, tmp, &topology_device_list, list) { 15575b5c4e40SEvgeny Pinchuk if (dev->gpu == gpu) { 15585b5c4e40SEvgeny Pinchuk gpu_id = dev->gpu_id; 15595b5c4e40SEvgeny Pinchuk kfd_remove_sysfs_node_entry(dev); 15605b5c4e40SEvgeny Pinchuk kfd_release_topology_device(dev); 15614f449311SHarish Kasiviswanathan sys_props.num_devices--; 1562*46d18d51SMukul Joshi kfd_topology_update_io_links(i); 1563*46d18d51SMukul Joshi topology_crat_proximity_domain = sys_props.num_devices-1; 1564*46d18d51SMukul Joshi sys_props.generation_count++; 15655b5c4e40SEvgeny Pinchuk res = 0; 15665b5c4e40SEvgeny Pinchuk if (kfd_topology_update_sysfs() < 0) 15675b5c4e40SEvgeny Pinchuk kfd_topology_release_sysfs(); 15685b5c4e40SEvgeny Pinchuk break; 15695b5c4e40SEvgeny Pinchuk } 1570*46d18d51SMukul Joshi i++; 1571*46d18d51SMukul Joshi } 15725b5c4e40SEvgeny Pinchuk 15735b5c4e40SEvgeny Pinchuk up_write(&topology_lock); 15745b5c4e40SEvgeny Pinchuk 1575174de876SFelix Kuehling if (!res) 15765b5c4e40SEvgeny Pinchuk kfd_notify_gpu_change(gpu_id, 0); 15775b5c4e40SEvgeny Pinchuk 15785b5c4e40SEvgeny Pinchuk return res; 15795b5c4e40SEvgeny Pinchuk } 15805b5c4e40SEvgeny Pinchuk 15816d82eb0eSHarish Kasiviswanathan /* kfd_topology_enum_kfd_devices - Enumerate through all devices in KFD 15826d82eb0eSHarish Kasiviswanathan * topology. If GPU device is found @idx, then valid kfd_dev pointer is 15836d82eb0eSHarish Kasiviswanathan * returned through @kdev 15846d82eb0eSHarish Kasiviswanathan * Return - 0: On success (@kdev will be NULL for non GPU nodes) 15856d82eb0eSHarish Kasiviswanathan * -1: If end of list 15865b5c4e40SEvgeny Pinchuk */ 15876d82eb0eSHarish Kasiviswanathan int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev) 15885b5c4e40SEvgeny Pinchuk { 15895b5c4e40SEvgeny Pinchuk 15905b5c4e40SEvgeny Pinchuk struct kfd_topology_device *top_dev; 15915b5c4e40SEvgeny Pinchuk uint8_t device_idx = 0; 15925b5c4e40SEvgeny Pinchuk 15936d82eb0eSHarish Kasiviswanathan *kdev = NULL; 15945b5c4e40SEvgeny Pinchuk down_read(&topology_lock); 15955b5c4e40SEvgeny Pinchuk 15965b5c4e40SEvgeny Pinchuk list_for_each_entry(top_dev, &topology_device_list, list) { 15975b5c4e40SEvgeny Pinchuk if (device_idx == idx) { 15986d82eb0eSHarish Kasiviswanathan *kdev = top_dev->gpu; 15996d82eb0eSHarish Kasiviswanathan up_read(&topology_lock); 16006d82eb0eSHarish Kasiviswanathan return 0; 16015b5c4e40SEvgeny Pinchuk } 16025b5c4e40SEvgeny Pinchuk 16035b5c4e40SEvgeny Pinchuk device_idx++; 16045b5c4e40SEvgeny Pinchuk } 16055b5c4e40SEvgeny Pinchuk 16065b5c4e40SEvgeny Pinchuk up_read(&topology_lock); 16075b5c4e40SEvgeny Pinchuk 16086d82eb0eSHarish Kasiviswanathan return -1; 16095b5c4e40SEvgeny Pinchuk 16105b5c4e40SEvgeny Pinchuk } 1611851a645eSFelix Kuehling 1612520b8fb7SFelix Kuehling static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask) 1613520b8fb7SFelix Kuehling { 1614520b8fb7SFelix Kuehling int first_cpu_of_numa_node; 1615520b8fb7SFelix Kuehling 1616520b8fb7SFelix Kuehling if (!cpumask || cpumask == cpu_none_mask) 1617520b8fb7SFelix Kuehling return -1; 1618520b8fb7SFelix Kuehling first_cpu_of_numa_node = cpumask_first(cpumask); 1619520b8fb7SFelix Kuehling if (first_cpu_of_numa_node >= nr_cpu_ids) 1620520b8fb7SFelix Kuehling return -1; 1621df1dd4f4SFelix Kuehling #ifdef CONFIG_X86_64 1622df1dd4f4SFelix Kuehling return cpu_data(first_cpu_of_numa_node).apicid; 1623df1dd4f4SFelix Kuehling #else 1624df1dd4f4SFelix Kuehling return first_cpu_of_numa_node; 1625df1dd4f4SFelix Kuehling #endif 1626520b8fb7SFelix Kuehling } 1627520b8fb7SFelix Kuehling 1628520b8fb7SFelix Kuehling /* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor 1629520b8fb7SFelix Kuehling * of the given NUMA node (numa_node_id) 1630520b8fb7SFelix Kuehling * Return -1 on failure 1631520b8fb7SFelix Kuehling */ 1632520b8fb7SFelix Kuehling int kfd_numa_node_to_apic_id(int numa_node_id) 1633520b8fb7SFelix Kuehling { 1634520b8fb7SFelix Kuehling if (numa_node_id == -1) { 1635520b8fb7SFelix Kuehling pr_warn("Invalid NUMA Node. Use online CPU mask\n"); 1636520b8fb7SFelix Kuehling return kfd_cpumask_to_apic_id(cpu_online_mask); 1637520b8fb7SFelix Kuehling } 1638520b8fb7SFelix Kuehling return kfd_cpumask_to_apic_id(cpumask_of_node(numa_node_id)); 1639520b8fb7SFelix Kuehling } 1640520b8fb7SFelix Kuehling 16416127896fSHuang Rui void kfd_double_confirm_iommu_support(struct kfd_dev *gpu) 16426127896fSHuang Rui { 16436127896fSHuang Rui struct kfd_topology_device *dev; 16446127896fSHuang Rui 16456127896fSHuang Rui gpu->use_iommu_v2 = false; 16466127896fSHuang Rui 1647f0dc99a6SGraham Sider if (!gpu->device_info.needs_iommu_device) 16486127896fSHuang Rui return; 16496127896fSHuang Rui 16506127896fSHuang Rui down_read(&topology_lock); 16516127896fSHuang Rui 16526127896fSHuang Rui /* Only use IOMMUv2 if there is an APU topology node with no GPU 16536127896fSHuang Rui * assigned yet. This GPU will be assigned to it. 16546127896fSHuang Rui */ 16556127896fSHuang Rui list_for_each_entry(dev, &topology_device_list, list) 16566127896fSHuang Rui if (dev->node_props.cpu_cores_count && 16576127896fSHuang Rui dev->node_props.simd_count && 16586127896fSHuang Rui !dev->gpu) 16596127896fSHuang Rui gpu->use_iommu_v2 = true; 16606127896fSHuang Rui 16616127896fSHuang Rui up_read(&topology_lock); 16626127896fSHuang Rui } 16636127896fSHuang Rui 1664851a645eSFelix Kuehling #if defined(CONFIG_DEBUG_FS) 1665851a645eSFelix Kuehling 1666851a645eSFelix Kuehling int kfd_debugfs_hqds_by_device(struct seq_file *m, void *data) 1667851a645eSFelix Kuehling { 1668851a645eSFelix Kuehling struct kfd_topology_device *dev; 1669851a645eSFelix Kuehling unsigned int i = 0; 1670851a645eSFelix Kuehling int r = 0; 1671851a645eSFelix Kuehling 1672851a645eSFelix Kuehling down_read(&topology_lock); 1673851a645eSFelix Kuehling 1674851a645eSFelix Kuehling list_for_each_entry(dev, &topology_device_list, list) { 1675851a645eSFelix Kuehling if (!dev->gpu) { 1676851a645eSFelix Kuehling i++; 1677851a645eSFelix Kuehling continue; 1678851a645eSFelix Kuehling } 1679851a645eSFelix Kuehling 1680851a645eSFelix Kuehling seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); 1681851a645eSFelix Kuehling r = dqm_debugfs_hqds(m, dev->gpu->dqm); 1682851a645eSFelix Kuehling if (r) 1683851a645eSFelix Kuehling break; 1684851a645eSFelix Kuehling } 1685851a645eSFelix Kuehling 1686851a645eSFelix Kuehling up_read(&topology_lock); 1687851a645eSFelix Kuehling 1688851a645eSFelix Kuehling return r; 1689851a645eSFelix Kuehling } 1690851a645eSFelix Kuehling 1691851a645eSFelix Kuehling int kfd_debugfs_rls_by_device(struct seq_file *m, void *data) 1692851a645eSFelix Kuehling { 1693851a645eSFelix Kuehling struct kfd_topology_device *dev; 1694851a645eSFelix Kuehling unsigned int i = 0; 1695851a645eSFelix Kuehling int r = 0; 1696851a645eSFelix Kuehling 1697851a645eSFelix Kuehling down_read(&topology_lock); 1698851a645eSFelix Kuehling 1699851a645eSFelix Kuehling list_for_each_entry(dev, &topology_device_list, list) { 1700851a645eSFelix Kuehling if (!dev->gpu) { 1701851a645eSFelix Kuehling i++; 1702851a645eSFelix Kuehling continue; 1703851a645eSFelix Kuehling } 1704851a645eSFelix Kuehling 1705851a645eSFelix Kuehling seq_printf(m, "Node %u, gpu_id %x:\n", i++, dev->gpu->id); 17069af5379cSOak Zeng r = pm_debugfs_runlist(m, &dev->gpu->dqm->packet_mgr); 1707851a645eSFelix Kuehling if (r) 1708851a645eSFelix Kuehling break; 1709851a645eSFelix Kuehling } 1710851a645eSFelix Kuehling 1711851a645eSFelix Kuehling up_read(&topology_lock); 1712851a645eSFelix Kuehling 1713851a645eSFelix Kuehling return r; 1714851a645eSFelix Kuehling } 1715851a645eSFelix Kuehling 1716851a645eSFelix Kuehling #endif 1717