to introduce the profiler manager infrastructure needed to support per-process GPU hardware profiling features such as SPM and PCS.
Two new files are added: - amdgpu_profiler.c/.h: define struct amdgpu_profiler_mgr, which holds an array of per-XCP partition managers (amdgpu_profiler_xcp_mgr), each reference-counted via kref and protected by a dedicated mutex. A device-level struct amdgpu_profiler_mgr prof_mgr is embedded in struct amdgpu_device and its top-level mutex is initialized during amdgpu_device_init(). The per-XCP profiler manager is initialized lazily on the first amdgpu_driver_open_kms() call for a given XCP partition: - If the XCP manager is already initialized, only the kref is incremented. - On file close (amdgpu_drm_release()), the kref is decremented and the per-XCP manager is destroyed (mutex destroyed, is_init cleared) when the last user releases it. Non-partitioned devices uses XCP partition 0. Initialization is skipped when fpriv->xcp_id is AMDGPU_XCP_NO_PARTITION, which indicates the device has not yet been fully initialized. Signed-off-by: James Zhu <[email protected]> --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.c | 89 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.h | 48 +++++++++++ 7 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 3b563c73bb66..74abc061cd4d 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -67,7 +67,8 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \ amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o amdgpu_dev_coredump.o \ - amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o amdgpu_cwsr.o + amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o amdgpu_cwsr.o \ + amdgpu_profiler.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 116e509e7bed..7c18640ddb59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -109,6 +109,7 @@ #include "amdgpu_seq64.h" #include "amdgpu_reg_state.h" #include "amdgpu_userq.h" +#include "amdgpu_profiler.h" #include "amdgpu_eviction_fence.h" #include "amdgpu_ip.h" #if defined(CONFIG_DRM_AMD_ISP) @@ -1252,6 +1253,8 @@ struct amdgpu_device { struct amdgpu_uma_carveout_info uma_info; + struct amdgpu_profiler_mgr prof_mgr; + /* KFD * Must be last --ends in a flexible-array member. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b5a5b1670fe4..09ea4f1d7e33 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4448,6 +4448,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->gfx.userq_sch_mutex); mutex_init(&adev->gfx.workload_profile_mutex); mutex_init(&adev->vcn.workload_profile_mutex); + mutex_init(&adev->prof_mgr.mutex); amdgpu_device_init_apu_flags(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 5e784d4de81b..52423c98ebf5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2955,6 +2955,7 @@ static int amdgpu_drm_release(struct inode *inode, struct file *filp) fpriv->evf_mgr.fd_closing = true; amdgpu_eviction_fence_destroy(&fpriv->evf_mgr); amdgpu_userq_mgr_fini(&fpriv->userq_mgr); + amdgpu_profiler_mgr_fini(fpriv_to_prof_mgr(fpriv), fpriv); drm_dev_exit(idx); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 24ecdee0d735..ead67b4c54a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1626,6 +1626,10 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) dev_dbg(adev->dev, "cwsr trap not enabled"); } + r = amdgpu_profiler_mgr_init(fpriv_to_prof_mgr(fpriv), fpriv); + if (r) + DRM_WARN("Can't setup profiler\n"); + r = amdgpu_eviction_fence_init(&fpriv->evf_mgr); if (r) goto error_vm; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.c new file mode 100644 index 000000000000..d2cf0520c6f1 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright 2026 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. + */ + +#include "amdgpu.h" + +/* + * Profiler revision change log + * + * 1.1 - Initial revision + */ + +#define AMDGPU_PROFILER_VERSION_MAJOR 1 +#define AMDGPU_PROFILER_VERSION_MINOR 1 + +int amdgpu_profiler_mgr_init( + struct amdgpu_profiler_mgr *prof_mgr, + struct amdgpu_fpriv *fpriv) +{ + struct amdgpu_profiler_xcp_mgr *prof_xcp_mgr; + struct amdgpu_device *adev = fpriv_to_adev(fpriv); + + if (fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION) + return 0; + + mutex_lock(&prof_mgr->mutex); + + prof_xcp_mgr = &prof_mgr->prof_xcp_mgr[fpriv->xcp_id]; + if (prof_xcp_mgr->is_init) { + kref_get(&prof_xcp_mgr->ref); + mutex_unlock(&prof_mgr->mutex); + return 0; + } + + dev_dbg(adev->dev, "Initialize profiler on render node %d xcp %d", + adev->ddev.render->index, fpriv->xcp_id); + kref_init(&prof_xcp_mgr->ref); + mutex_init(&prof_xcp_mgr->mutex); + prof_xcp_mgr->xcp_id = fpriv->xcp_id; + + prof_xcp_mgr->is_init = true; + + mutex_unlock(&prof_mgr->mutex); + return 0; +} + +static void amdgpu_profiler_mgr_release(struct kref *ref) +{ + struct amdgpu_profiler_xcp_mgr *prof_xcp_mgr = + container_of(ref, struct amdgpu_profiler_xcp_mgr, ref); + + mutex_destroy(&prof_xcp_mgr->mutex); + prof_xcp_mgr->is_init = false; +} + +void amdgpu_profiler_mgr_fini( + struct amdgpu_profiler_mgr *prof_mgr, + struct amdgpu_fpriv *fpriv) +{ + struct amdgpu_profiler_xcp_mgr *prof_xcp_mgr; + + if (fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION) + return; + + mutex_lock(&prof_mgr->mutex); + prof_xcp_mgr = &prof_mgr->prof_xcp_mgr[fpriv->xcp_id]; + if (prof_xcp_mgr->is_init) + kref_put(&prof_xcp_mgr->ref, amdgpu_profiler_mgr_release); + mutex_unlock(&prof_mgr->mutex); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.h new file mode 100644 index 000000000000..2dfc0b1bb207 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_profiler.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * Copyright 2026 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. + * + */ + +#ifndef AMDGPU_PROFILER_H_ +#define AMDGPU_PROFILER_H_ + +#define fpriv_to_prof_mgr(fpriv) (&(fpriv)->userq_mgr.adev->prof_mgr) +#define fpriv_to_adev(fpriv) ((fpriv)->userq_mgr.adev) + +struct amdgpu_profiler_xcp_mgr { + struct mutex mutex; + uint32_t xcp_id; + bool is_init; + struct kref ref; +}; + +struct amdgpu_profiler_mgr { + struct mutex mutex; + struct amdgpu_profiler_xcp_mgr prof_xcp_mgr[MAX_XCP]; +}; + +int amdgpu_profiler_mgr_init(struct amdgpu_profiler_mgr *prof_mgr, + struct amdgpu_fpriv *fpriv); +void amdgpu_profiler_mgr_fini(struct amdgpu_profiler_mgr *prof_mgr, + struct amdgpu_fpriv *fpriv); + +#endif /* AMDGPU_PROFILER_H_ */ -- 2.34.1
