diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2608-drm-amdgpu-add-pmu-counters.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2608-drm-amdgpu-add-pmu-counters.patch | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2608-drm-amdgpu-add-pmu-counters.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2608-drm-amdgpu-add-pmu-counters.patch new file mode 100644 index 00000000..a1895722 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2608-drm-amdgpu-add-pmu-counters.patch @@ -0,0 +1,400 @@ +From 5df059e4293b1dad849895f5e000fe5b432d1988 Mon Sep 17 00:00:00 2001 +From: Jonathan Kim <jonathan.kim@amd.com> +Date: Wed, 19 Jun 2019 23:56:25 -0400 +Subject: [PATCH 2608/2940] drm/amdgpu: add pmu counters + +adding perf event counters' + +Change-Id: I95ddedd8bc0dd33559094da4c10ff93fc7c7be4f +Signed-off-by: Jonathan Kim <Jonathan.Kim@amd.com> +Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 + + drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c | 280 +++++++++++++++++++++ + drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.h | 37 +++ + 4 files changed, 326 insertions(+), 1 deletion(-) + create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c + create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.h + +diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile +index d9fe65786054..098e96456cad 100644 +--- a/drivers/gpu/drm/amd/amdgpu/Makefile ++++ b/drivers/gpu/drm/amd/amdgpu/Makefile +@@ -53,7 +53,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ + amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \ + amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ + amdgpu_sem.o amdgpu_gmc.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o \ +- amdgpu_vm_cpu.o amdgpu_vm_sdma.o amdgpu_discovery.o ++ amdgpu_vm_cpu.o amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_pmu.o + + # add asic specific block + amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 8b75cc05a1c6..d5eaa3d61b7d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -62,6 +62,7 @@ + + #include "amdgpu_xgmi.h" + #include "amdgpu_ras.h" ++#include "amdgpu_pmu.h" + + MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin"); + MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin"); +@@ -2798,6 +2799,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, + return r; + } + ++ r = amdgpu_pmu_init(adev); ++ if (r) ++ dev_err(adev->dev, "amdgpu_pmu_init failed\n"); ++ + return 0; + + failed: +@@ -2866,9 +2871,12 @@ void amdgpu_device_fini(struct amdgpu_device *adev) + amdgpu_debugfs_regs_cleanup(adev); + device_remove_file(adev->dev, &dev_attr_pcie_replay_count); + amdgpu_ucode_sysfs_fini(adev); ++ + amdgpu_debugfs_preempt_cleanup(adev); + if (amdgpu_discovery) + amdgpu_discovery_fini(adev); ++ ++ amdgpu_pmu_fini(adev); + } + + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c +new file mode 100644 +index 000000000000..0e6dba9f60f0 +--- /dev/null ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c +@@ -0,0 +1,280 @@ ++/* ++ * Copyright 2019 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Author: Jonathan Kim <jonathan.kim@amd.com> ++ * ++ */ ++ ++#include <linux/perf_event.h> ++#include <linux/init.h> ++#include "amdgpu.h" ++#include "amdgpu_pmu.h" ++#include "df_v3_6.h" ++ ++#define PMU_NAME_SIZE 32 ++ ++/* record to keep track of pmu entry per pmu type per device */ ++struct amdgpu_pmu_entry { ++ struct list_head entry; ++ struct amdgpu_device *adev; ++ struct pmu pmu; ++ unsigned int pmu_perf_type; ++}; ++ ++static LIST_HEAD(amdgpu_pmu_list); ++ ++ ++/* initialize perf counter */ ++static int amdgpu_perf_event_init(struct perf_event *event) ++{ ++ struct hw_perf_event *hwc = &event->hw; ++ ++ /* test the event attr type check for PMU enumeration */ ++ if (event->attr.type != event->pmu->type) ++ return -ENOENT; ++ ++ /* update the hw_perf_event struct with config data */ ++ hwc->conf = event->attr.config; ++ ++ return 0; ++} ++ ++/* start perf counter */ ++static void amdgpu_perf_start(struct perf_event *event, int flags) ++{ ++ struct hw_perf_event *hwc = &event->hw; ++ struct amdgpu_pmu_entry *pe = container_of(event->pmu, ++ struct amdgpu_pmu_entry, ++ pmu); ++ ++ if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) ++ return; ++ ++ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); ++ hwc->state = 0; ++ ++ switch (pe->pmu_perf_type) { ++ case PERF_TYPE_AMDGPU_DF: ++ if (!(flags & PERF_EF_RELOAD)) ++ pe->adev->df_funcs->pmc_start(pe->adev, hwc->conf, 1); ++ ++ pe->adev->df_funcs->pmc_start(pe->adev, hwc->conf, 0); ++ break; ++ default: ++ break; ++ } ++ ++ perf_event_update_userpage(event); ++ ++} ++ ++/* read perf counter */ ++static void amdgpu_perf_read(struct perf_event *event) ++{ ++ struct hw_perf_event *hwc = &event->hw; ++ struct amdgpu_pmu_entry *pe = container_of(event->pmu, ++ struct amdgpu_pmu_entry, ++ pmu); ++ ++ u64 count, prev; ++ ++ do { ++ prev = local64_read(&hwc->prev_count); ++ ++ switch (pe->pmu_perf_type) { ++ case PERF_TYPE_AMDGPU_DF: ++ pe->adev->df_funcs->pmc_get_count(pe->adev, hwc->conf, ++ &count); ++ break; ++ default: ++ count = 0; ++ break; ++ }; ++ } while (local64_cmpxchg(&hwc->prev_count, prev, count) != prev); ++ ++ local64_add(count - prev, &event->count); ++} ++ ++/* stop perf counter */ ++static void amdgpu_perf_stop(struct perf_event *event, int flags) ++{ ++ struct hw_perf_event *hwc = &event->hw; ++ struct amdgpu_pmu_entry *pe = container_of(event->pmu, ++ struct amdgpu_pmu_entry, ++ pmu); ++ ++ if (hwc->state & PERF_HES_UPTODATE) ++ return; ++ ++ switch (pe->pmu_perf_type) { ++ case PERF_TYPE_AMDGPU_DF: ++ pe->adev->df_funcs->pmc_stop(pe->adev, hwc->conf, 0); ++ break; ++ default: ++ break; ++ }; ++ ++ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); ++ hwc->state |= PERF_HES_STOPPED; ++ ++ if (hwc->state & PERF_HES_UPTODATE) ++ return; ++ ++ amdgpu_perf_read(event); ++ hwc->state |= PERF_HES_UPTODATE; ++} ++ ++/* add perf counter */ ++static int amdgpu_perf_add(struct perf_event *event, int flags) ++{ ++ struct hw_perf_event *hwc = &event->hw; ++ int retval; ++ ++ struct amdgpu_pmu_entry *pe = container_of(event->pmu, ++ struct amdgpu_pmu_entry, ++ pmu); ++ ++ event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED; ++ ++ switch (pe->pmu_perf_type) { ++ case PERF_TYPE_AMDGPU_DF: ++ retval = pe->adev->df_funcs->pmc_start(pe->adev, hwc->conf, 1); ++ break; ++ default: ++ return 0; ++ }; ++ ++ if (retval) ++ return retval; ++ ++ if (flags & PERF_EF_START) ++ amdgpu_perf_start(event, PERF_EF_RELOAD); ++ ++ return retval; ++ ++} ++ ++/* delete perf counter */ ++static void amdgpu_perf_del(struct perf_event *event, int flags) ++{ ++ struct hw_perf_event *hwc = &event->hw; ++ struct amdgpu_pmu_entry *pe = container_of(event->pmu, ++ struct amdgpu_pmu_entry, ++ pmu); ++ ++ amdgpu_perf_stop(event, PERF_EF_UPDATE); ++ ++ switch (pe->pmu_perf_type) { ++ case PERF_TYPE_AMDGPU_DF: ++ pe->adev->df_funcs->pmc_stop(pe->adev, hwc->conf, 1); ++ break; ++ default: ++ break; ++ }; ++ ++ perf_event_update_userpage(event); ++} ++ ++/* vega20 pmus */ ++ ++/* init pmu tracking per pmu type */ ++static int init_pmu_by_type(struct amdgpu_device *adev, ++ const struct attribute_group *attr_groups[], ++ char *pmu_type_name, char *pmu_file_prefix, ++ unsigned int pmu_perf_type, ++ unsigned int num_counters) ++{ ++ char pmu_name[PMU_NAME_SIZE]; ++ struct amdgpu_pmu_entry *pmu_entry; ++ int ret = 0; ++ ++ pmu_entry = kzalloc(sizeof(struct amdgpu_pmu_entry), GFP_KERNEL); ++ ++ if (!pmu_entry) ++ return -ENOMEM; ++ ++ pmu_entry->adev = adev; ++ pmu_entry->pmu = (struct pmu){ ++ .event_init = amdgpu_perf_event_init, ++ .add = amdgpu_perf_add, ++ .del = amdgpu_perf_del, ++ .start = amdgpu_perf_start, ++ .stop = amdgpu_perf_stop, ++ .read = amdgpu_perf_read, ++ .task_ctx_nr = perf_invalid_context, ++ }; ++ ++ pmu_entry->pmu.attr_groups = attr_groups; ++ pmu_entry->pmu_perf_type = pmu_perf_type; ++ snprintf(pmu_name, PMU_NAME_SIZE, "%s_%d", ++ pmu_file_prefix, adev->ddev->primary->index); ++ ++ ret = perf_pmu_register(&pmu_entry->pmu, pmu_name, -1); ++ ++ if (ret) { ++ kfree(pmu_entry); ++ pr_warn("Error initializing AMDGPU %s PMUs.\n", pmu_type_name); ++ return ret; ++ } ++ ++ pr_info("Detected AMDGPU %s Counters. # of Counters = %d.\n", ++ pmu_type_name, num_counters); ++ ++ list_add_tail(&pmu_entry->entry, &amdgpu_pmu_list); ++ ++ return 0; ++} ++ ++/* init amdgpu_pmu */ ++int amdgpu_pmu_init(struct amdgpu_device *adev) ++{ ++ int ret = 0; ++ ++ switch (adev->asic_type) { ++ case CHIP_VEGA20: ++ /* init df */ ++ ret = init_pmu_by_type(adev, df_v3_6_attr_groups, ++ "DF", "amdgpu_df", PERF_TYPE_AMDGPU_DF, ++ DF_V3_6_MAX_COUNTERS); ++ ++ /* other pmu types go here*/ ++ break; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++ ++/* destroy all pmu data associated with target device */ ++void amdgpu_pmu_fini(struct amdgpu_device *adev) ++{ ++ struct amdgpu_pmu_entry *pe, *temp; ++ ++ list_for_each_entry_safe(pe, temp, &amdgpu_pmu_list, entry) { ++ if (pe->adev == adev) { ++ list_del(&pe->entry); ++ perf_pmu_unregister(&pe->pmu); ++ kfree(pe); ++ } ++ } ++} +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.h +new file mode 100644 +index 000000000000..7dddb7160a11 +--- /dev/null ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright 2019 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Author: Jonathan Kim <jonathan.kim@amd.com> ++ * ++ */ ++ ++#ifndef _AMDGPU_PMU_H_ ++#define _AMDGPU_PMU_H_ ++ ++enum amdgpu_pmu_perf_type { ++ PERF_TYPE_AMDGPU_DF = 0, ++ PERF_TYPE_AMDGPU_MAX ++}; ++ ++int amdgpu_pmu_init(struct amdgpu_device *adev); ++void amdgpu_pmu_fini(struct amdgpu_device *adev); ++ ++#endif /* _AMDGPU_PMU_H_ */ +-- +2.17.1 + |