aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/1219-drm-amdkfd-Add-perf-counters-to-topology.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/1219-drm-amdkfd-Add-perf-counters-to-topology.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/1219-drm-amdkfd-Add-perf-counters-to-topology.patch266
1 files changed, 266 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/1219-drm-amdkfd-Add-perf-counters-to-topology.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/1219-drm-amdkfd-Add-perf-counters-to-topology.patch
new file mode 100644
index 00000000..cb12ea4f
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/1219-drm-amdkfd-Add-perf-counters-to-topology.patch
@@ -0,0 +1,266 @@
+From a9879130e6adba2e8c537ae29bad271cb059f056 Mon Sep 17 00:00:00 2001
+From: Amber Lin <Amber.Lin@amd.com>
+Date: Mon, 30 Jan 2017 11:55:50 -0500
+Subject: [PATCH 1219/4131] drm/amdkfd: Add perf counters to topology
+
+For hardware blocks whose performance counters are accessed via MMIO
+registers, KFD provides the support for those privileged blocks. IOMMU is
+one of those privileged blocks. Most performance counter properties
+required by Thunk are available at /sys/bus/event_source/devices/amd_iommu.
+ This patch adds properties to topology in KFD sysfs for information not
+available in /sys/bus/event_source/devices/amd_iommu. They are shown at
+/sys/devices/virtual/kfd/kfd/topology/nodes/0/perf/iommu/ formatted as
+/sys/devices/virtual/kfd/kfd/topology/nodes/0/perf/<block>/<property>, i.e.
+/sys/devices/virtual/kfd/kfd/topology/nodes/0/perf/iommu/max_concurrent.
+For dGPUs, who don't have IOMMU, nothing appears under
+/sys/devices/virtual/kfd/kfd/topology/nodes/0/perf.
+
+Change-Id: I849d52f923169d074d36aa55313988cba3fb8192
+Signed-off-by: Amber Lin <Amber.Lin@amd.com>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 116 +++++++++++++++++++++++++++++-
+ drivers/gpu/drm/amd/amdkfd/kfd_topology.h | 13 ++++
+ 2 files changed, 127 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+index ce136c0..36e2cba 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+@@ -121,6 +121,7 @@ static void kfd_release_topology_device(struct kfd_topology_device *dev)
+ struct kfd_mem_properties *mem;
+ struct kfd_cache_properties *cache;
+ struct kfd_iolink_properties *iolink;
++ struct kfd_perf_properties *perf;
+
+ BUG_ON(!dev);
+
+@@ -147,6 +148,13 @@ static void kfd_release_topology_device(struct kfd_topology_device *dev)
+ kfree(iolink);
+ }
+
++ while (dev->perf_props.next != &dev->perf_props) {
++ perf = container_of(dev->perf_props.next,
++ struct kfd_perf_properties, list);
++ list_del(&perf->list);
++ kfree(perf);
++ }
++
+ kfree(dev);
+
+ sys_props.num_devices--;
+@@ -180,6 +188,7 @@ struct kfd_topology_device *kfd_create_topology_device(
+ INIT_LIST_HEAD(&dev->mem_props);
+ INIT_LIST_HEAD(&dev->cache_props);
+ INIT_LIST_HEAD(&dev->io_link_props);
++ INIT_LIST_HEAD(&dev->perf_props);
+
+ list_add_tail(&dev->list, device_list);
+ sys_props.num_devices++;
+@@ -346,6 +355,39 @@ static struct kobj_type cache_type = {
+ .sysfs_ops = &cache_ops,
+ };
+
++/****** Sysfs of Performance Counters ******/
++
++struct kfd_perf_attr {
++ struct kobj_attribute attr;
++ uint32_t data;
++};
++
++static ssize_t perf_show(struct kobject *kobj, struct kobj_attribute *attrs,
++ char *buf)
++{
++ struct kfd_perf_attr *attr;
++
++ buf[0] = 0;
++ attr = container_of(attrs, struct kfd_perf_attr, attr);
++ if (!attr->data) /* invalid data for PMC */
++ return 0;
++ else
++ return sysfs_show_32bit_val(buf, attr->data);
++}
++
++#define KFD_PERF_DESC(_name, _data) \
++{ \
++ .attr = __ATTR(_name, 0444, perf_show, NULL), \
++ .data = _data, \
++}
++
++static struct kfd_perf_attr perf_attr_iommu[] = {
++ KFD_PERF_DESC(max_concurrent, 0),
++ KFD_PERF_DESC(num_counters, 0),
++ KFD_PERF_DESC(counter_ids, 0),
++};
++/****************************************/
++
+ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+ {
+@@ -485,6 +527,7 @@ static void kfd_remove_sysfs_node_entry(struct kfd_topology_device *dev)
+ struct kfd_iolink_properties *iolink;
+ struct kfd_cache_properties *cache;
+ struct kfd_mem_properties *mem;
++ struct kfd_perf_properties *perf;
+
+ BUG_ON(!dev);
+
+@@ -523,6 +566,16 @@ static void kfd_remove_sysfs_node_entry(struct kfd_topology_device *dev)
+ dev->kobj_mem = NULL;
+ }
+
++ if (dev->kobj_perf) {
++ list_for_each_entry(perf, &dev->perf_props, list) {
++ kfree(perf->attr_group);
++ perf->attr_group = NULL;
++ }
++ kobject_del(dev->kobj_perf);
++ kobject_put(dev->kobj_perf);
++ dev->kobj_perf = NULL;
++ }
++
+ if (dev->kobj_node) {
+ sysfs_remove_file(dev->kobj_node, &dev->attr_gpuid);
+ sysfs_remove_file(dev->kobj_node, &dev->attr_name);
+@@ -539,8 +592,10 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev,
+ struct kfd_iolink_properties *iolink;
+ struct kfd_cache_properties *cache;
+ struct kfd_mem_properties *mem;
++ struct kfd_perf_properties *perf;
+ int ret;
+- uint32_t i;
++ uint32_t i, num_attrs;
++ struct attribute **attrs;
+
+ BUG_ON(!dev);
+
+@@ -569,6 +624,10 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev,
+ if (!dev->kobj_iolink)
+ return -ENOMEM;
+
++ dev->kobj_perf = kobject_create_and_add("perf", dev->kobj_node);
++ if (!dev->kobj_perf)
++ return -ENOMEM;
++
+ /*
+ * Creating sysfs files for node properties
+ */
+@@ -646,7 +705,33 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev,
+ if (ret < 0)
+ return ret;
+ i++;
+-}
++ }
++
++ /* All hardware blocks have the same number of attributes. */
++ num_attrs = sizeof(perf_attr_iommu)/sizeof(struct kfd_perf_attr);
++ list_for_each_entry(perf, &dev->perf_props, list) {
++ perf->attr_group = kzalloc(sizeof(struct kfd_perf_attr)
++ * num_attrs + sizeof(struct attribute_group),
++ GFP_KERNEL);
++ if (!perf->attr_group)
++ return -ENOMEM;
++
++ attrs = (struct attribute **)(perf->attr_group + 1);
++ if (!strcmp(perf->block_name, "iommu")) {
++ /* Information of IOMMU's num_counters and counter_ids is shown
++ * under /sys/bus/event_source/devices/amd_iommu. We don't
++ * duplicate here.
++ */
++ perf_attr_iommu[0].data = perf->max_concurrent;
++ for (i = 0; i < num_attrs; i++)
++ attrs[i] = &perf_attr_iommu[i].attr.attr;
++ }
++ perf->attr_group->name = perf->block_name;
++ perf->attr_group->attrs = attrs;
++ ret = sysfs_create_group(dev->kobj_perf, perf->attr_group);
++ if (ret < 0)
++ return ret;
++ }
+
+ return 0;
+ }
+@@ -811,6 +896,29 @@ static void find_system_memory(const struct dmi_header *dm,
+ }
+ }
+ }
++
++/*
++ * Performance counters information is not part of CRAT but we would like to
++ * put them in the sysfs under topology directory for Thunk to get the data.
++ * This function is called before updating the sysfs.
++ */
++static int kfd_add_perf_to_topology(struct kfd_topology_device *kdev)
++{
++ struct kfd_perf_properties *props;
++
++ if (amd_iommu_pc_supported()) {
++ props = kfd_alloc_struct(props);
++ if (props == NULL)
++ return -ENOMEM;
++ strcpy(props->block_name, "iommu");
++ props->max_concurrent = amd_iommu_pc_get_max_banks(0) *
++ amd_iommu_pc_get_max_counters(0); /* assume one iommu */
++ list_add_tail(&props->list, &kdev->perf_props);
++ }
++
++ return 0;
++}
++
+ /* kfd_add_non_crat_information - Add information that is not currently
+ * defined in CRAT but is necessary for KFD topology
+ * @dev - topology device to which addition info is added
+@@ -879,6 +987,10 @@ int kfd_topology_init(void)
+ goto err;
+ }
+
++ kdev = list_first_entry(&temp_topology_device_list,
++ struct kfd_topology_device, list);
++ kfd_add_perf_to_topology(kdev);
++
+ down_write(&topology_lock);
+ num_nodes = kfd_topology_update_device_list(&temp_topology_device_list,
+ &topology_device_list);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
+index ab28188..aa8056b 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
+@@ -138,6 +138,13 @@ struct kfd_iolink_properties {
+ struct attribute attr;
+ };
+
++struct kfd_perf_properties {
++ struct list_head list;
++ char block_name[16];
++ uint32_t max_concurrent;
++ struct attribute_group *attr_group;
++};
++
+ struct kfd_topology_device {
+ struct list_head list;
+ uint32_t gpu_id;
+@@ -148,11 +155,13 @@ struct kfd_topology_device {
+ struct list_head cache_props;
+ uint32_t io_link_count;
+ struct list_head io_link_props;
++ struct list_head perf_props;
+ struct kfd_dev *gpu;
+ struct kobject *kobj_node;
+ struct kobject *kobj_mem;
+ struct kobject *kobj_cache;
+ struct kobject *kobj_iolink;
++ struct kobject *kobj_perf;
+ struct attribute attr_gpuid;
+ struct attribute attr_name;
+ struct attribute attr_props;
+@@ -177,4 +186,8 @@ struct kfd_topology_device *kfd_create_topology_device(
+ struct list_head *device_list);
+ void kfd_release_live_view(void);
+
++extern bool amd_iommu_pc_supported(void);
++extern u8 amd_iommu_pc_get_max_banks(u16 devid);
++extern u8 amd_iommu_pc_get_max_counters(u16 devid);
++
+ #endif /* __KFD_TOPOLOGY_H__ */
+--
+2.7.4
+