summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
authorPerry Yuan <perry.yuan@amd.com>2026-02-09 00:42:02 +0800
committerAlex Deucher <alexander.deucher@amd.com>2026-05-11 15:55:55 -0400
commit8ce9c73104e34f1fbb8d7f50468e4a62905331f2 (patch)
treec9b4fb1dd5b9851e9f731239529502b75bacebe7 /drivers/gpu/drm/amd/amdgpu
parente486360db8df9d032bfff44b629d25a803a1d21c (diff)
downloadlwn-8ce9c73104e34f1fbb8d7f50468e4a62905331f2.tar.gz
lwn-8ce9c73104e34f1fbb8d7f50468e4a62905331f2.zip
drm/amdgpu: add psp interfaces for peak tops limiter driver
Introduce a Peak Tops Limiter (PTL) driver that dynamically caps engine frequency to ensure delivered TOPS never exceeds a defined TOPS_limit. This initial implementation provides core data structures and kernel-space interfaces (set/get, enable/disable) to manage PTL state. PTL performs a firmware handshake to initialize its state and update predefined format types. It supports updating these format types at runtime while user-space tools automatically switch PTL state, and also allows explicitly switching PTL state via newly added commands. Signed-off-by: Perry Yuan <perry.yuan@amd.com> Reviewed-by: Lijo Lazar <lijo.lazar@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c111
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h3
4 files changed, 116 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index cdbab7f8cee8..4fee011c2e26 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -38,6 +38,8 @@
#include "amdgpu_vm.h"
#include "amdgpu_xcp.h"
#include "kfd_topology.h"
+#include "amdgpu_ptl.h"
+
extern uint64_t amdgpu_amdkfd_total_mem_size;
enum TLB_FLUSH_TYPE {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d293444d026f..d91bf647757f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -3731,6 +3731,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
mutex_init(&adev->virt.vf_errors.lock);
hash_init(adev->mn_hash);
mutex_init(&adev->psp.mutex);
+ mutex_init(&adev->psp.ptl.mutex);
mutex_init(&adev->notifier_lock);
mutex_init(&adev->pm.stable_pstate_ctx_lock);
mutex_init(&adev->benchmark_mutex);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 4a64e39fa9cd..0734ddaf6388 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -682,6 +682,8 @@ static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id)
return "SPATIAL_PARTITION";
case GFX_CMD_ID_FB_NPS_MODE:
return "NPS_MODE_CHANGE";
+ case GFX_CMD_ID_PERF_HW:
+ return "PERF MONITORING HW";
default:
return "UNKNOWN CMD";
}
@@ -1201,6 +1203,115 @@ int psp_memory_partition(struct psp_context *psp, int mode)
return ret;
}
+static int psp_ptl_fmt_verify(struct psp_context *psp, enum amdgpu_ptl_fmt fmt,
+ uint32_t *ptl_fmt)
+{
+ struct amdgpu_device *adev = psp->adev;
+
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 4))
+ return -EINVAL;
+
+ switch (fmt) {
+ case AMDGPU_PTL_FMT_I8:
+ *ptl_fmt = GFX_FTYPE_I8;
+ break;
+ case AMDGPU_PTL_FMT_F16:
+ *ptl_fmt = GFX_FTYPE_F16;
+ break;
+ case AMDGPU_PTL_FMT_BF16:
+ *ptl_fmt = GFX_FTYPE_BF16;
+ break;
+ case AMDGPU_PTL_FMT_F32:
+ *ptl_fmt = GFX_FTYPE_F32;
+ break;
+ case AMDGPU_PTL_FMT_F64:
+ *ptl_fmt = GFX_FTYPE_F64;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int psp_ptl_invoke(struct psp_context *psp, u32 req_code,
+ uint32_t *ptl_state, uint32_t *fmt1, uint32_t *fmt2)
+{
+ struct psp_gfx_cmd_resp *cmd;
+ struct amdgpu_ptl *ptl = &psp->ptl;
+ int ret;
+
+ cmd = acquire_psp_cmd_buf(psp);
+
+ cmd->cmd_id = GFX_CMD_ID_PERF_HW;
+ cmd->cmd.cmd_req_perf_hw.req = req_code;
+ cmd->cmd.cmd_req_perf_hw.ptl_state = *ptl_state;
+ cmd->cmd.cmd_req_perf_hw.pref_format1 = *fmt1;
+ cmd->cmd.cmd_req_perf_hw.pref_format2 = *fmt2;
+
+ ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+ if (ret)
+ goto out;
+
+ /* Parse response */
+ switch (req_code) {
+ case PSP_PTL_PERF_MON_QUERY:
+ *ptl_state = cmd->resp.uresp.perf_hw_info.ptl_state;
+ *fmt1 = cmd->resp.uresp.perf_hw_info.pref_format1;
+ *fmt2 = cmd->resp.uresp.perf_hw_info.pref_format2;
+ break;
+ case PSP_PTL_PERF_MON_SET:
+ /* Update cached state only on success */
+ ptl->enabled = *ptl_state;
+ ptl->fmt1 = *fmt1;
+ ptl->fmt2 = *fmt2;
+ break;
+ }
+
+out:
+ release_psp_cmd_buf(psp);
+ return ret;
+}
+
+int amdgpu_ptl_perf_monitor_ctrl(struct amdgpu_device *adev, u32 req_code,
+ uint32_t *ptl_state,
+ enum amdgpu_ptl_fmt *fmt1,
+ enum amdgpu_ptl_fmt *fmt2)
+{
+ uint32_t ptl_fmt1, ptl_fmt2;
+ struct psp_context *psp;
+ struct amdgpu_ptl *ptl;
+
+ if (!adev || !ptl_state || !fmt1 || !fmt2)
+ return -EINVAL;
+
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ psp = &adev->psp;
+ ptl = &psp->ptl;
+
+ if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 4) ||
+ psp->sos.fw_version < 0x0036081a)
+ return -EOPNOTSUPP;
+
+ /* Verify formats */
+ if (psp_ptl_fmt_verify(psp, *fmt1, &ptl_fmt1) ||
+ psp_ptl_fmt_verify(psp, *fmt2, &ptl_fmt2))
+ return -EINVAL;
+
+ /*
+ * Add check to skip if state and formats are identical to current ones
+ */
+ if (req_code == PSP_PTL_PERF_MON_SET &&
+ ptl->enabled == *ptl_state &&
+ ptl->fmt1 == ptl_fmt1 &&
+ ptl->fmt2 == ptl_fmt2)
+ return 0;
+
+ return psp_ptl_invoke(psp, req_code, ptl_state, &ptl_fmt1, &ptl_fmt2);
+}
+
int psp_spatial_partition(struct psp_context *psp, int mode)
{
struct psp_gfx_cmd_resp *cmd;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 73e7e919c851..979650182431 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -31,6 +31,7 @@
#include "ta_ras_if.h"
#include "ta_rap_if.h"
#include "ta_secureDisplay_if.h"
+#include "amdgpu_ptl.h"
#define PSP_FENCE_BUFFER_SIZE 0x1000
#define PSP_CMD_BUFFER_SIZE 0x1000
@@ -469,6 +470,7 @@ struct psp_context {
#if defined(CONFIG_DEBUG_FS)
struct spirom_bo *spirom_dump_trip;
#endif
+ struct amdgpu_ptl ptl;
};
struct amdgpu_psp_funcs {
@@ -652,5 +654,4 @@ void amdgpu_psp_debugfs_init(struct amdgpu_device *adev);
int amdgpu_psp_get_fw_type(struct amdgpu_firmware_info *ucode,
enum psp_gfx_fw_type *type);
-
#endif