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";
}
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;
--- /dev/null
+/*
+ * 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_PTL_H__
+#define __AMDGPU_PTL_H__
+
+enum amdgpu_ptl_fmt {
+ AMDGPU_PTL_FMT_I8 = 0,
+ AMDGPU_PTL_FMT_F16 = 1,
+ AMDGPU_PTL_FMT_BF16 = 2,
+ AMDGPU_PTL_FMT_F32 = 3,
+ AMDGPU_PTL_FMT_F64 = 4,
+ AMDGPU_PTL_FMT_F8 = 5,
+ AMDGPU_PTL_FMT_VECTOR = 6,
+ AMDGPU_PTL_FMT_INVALID = 7,
+};
+
+struct amdgpu_ptl {
+ enum amdgpu_ptl_fmt fmt1;
+ enum amdgpu_ptl_fmt fmt2;
+ bool enabled;
+ bool hw_supported;
+ struct mutex mutex;
+};
+
+int amdgpu_ptl_perf_monitor_ctrl(struct amdgpu_device *adev, u32 req_code,
+ u32 *ptl_state,
+ enum amdgpu_ptl_fmt *fmt1,
+ enum amdgpu_ptl_fmt *fmt2);
+
+#endif /* __AMDGPU_PTL_H__ */