* [PATCH 02/25] drm/amd/pm: Add smu v15_0_8 message header
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 03/25] drm/amd/pm: Add smu v15_0_8 pmfw header Alex Deucher
` (22 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Hawking Zhang, Likun Gao, Yang Wang, Alex Deucher
From: Hawking Zhang <Hawking.Zhang@amd.com>
Add smu v15_0_8 message header
v2: squash in updates (Alex)
Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Likun Gao <Likun.Gao@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h | 100 ++++++++++++++++++
1 file changed, 100 insertions(+)
create mode 100644 drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
new file mode 100644
index 0000000000000..7ffb445f4c0cc
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_ppsmc.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2025 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 SMU_15_0_8_PPSMC_H
+#define SMU_15_0_8_PPSMC_H
+
+/* SMU Response Codes */
+#define PPSMC_Result_OK 0x1
+#define PPSMC_Result_Failed 0xFF
+#define PPSMC_Result_UnknownCmd 0xFE
+#define PPSMC_Result_CmdRejectedPrereq 0xFD
+#define PPSMC_Result_CmdRejectedBusy 0xFC
+
+/* Message Definitions */
+#define PPSMC_MSG_TestMessage 0x1
+#define PPSMC_MSG_GetSmuVersion 0x2
+#define PPSMC_MSG_GfxDriverReset 0x3
+#define PPSMC_MSG_GetDriverIfVersion 0x4
+#define PPSMC_MSG_EnableAllSmuFeatures 0x5
+#define PPSMC_MSG_GetMetricsVersion 0x6
+#define PPSMC_MSG_GetMetricsTable 0x7
+#define PPSMC_MSG_GetEnabledSmuFeatures 0x8
+#define PPSMC_MSG_SetDriverDramAddr 0x9 //ARG0: low address, ARG1: high address
+#define PPSMC_MSG_SetToolsDramAddr 0xA //ARG0: low address, ARG1: high address
+//#define PPSMC_MSG_SetSystemVirtualDramAddr 0xB
+#define PPSMC_MSG_SetSoftMaxByFreq 0xC
+#define PPSMC_MSG_SetPptLimit 0xD
+#define PPSMC_MSG_GetPptLimit 0xE
+#define PPSMC_MSG_DramLogSetDramAddr 0xF //ARG0: low address, ARG1: high address, ARG2: size
+#define PPSMC_MSG_HeavySBR 0x10
+#define PPSMC_MSG_DFCstateControl 0x11
+#define PPSMC_MSG_GfxDriverResetRecovery 0x12
+#define PPSMC_MSG_TriggerVFFLR 0x13
+#define PPSMC_MSG_SetSoftMinGfxClk 0x14
+#define PPSMC_MSG_SetSoftMaxGfxClk 0x15
+#define PPSMC_MSG_PrepareForDriverUnload 0x16
+#define PPSMC_MSG_QueryValidMcaCount 0x17
+#define PPSMC_MSG_McaBankDumpDW 0x18
+#define PPSMC_MSG_ClearMcaOnRead 0x19
+#define PPSMC_MSG_QueryValidMcaCeCount 0x1A
+#define PPSMC_MSG_McaBankCeDumpDW 0x1B
+#define PPSMC_MSG_SelectPLPDMode 0x1C
+#define PPSMC_MSG_SetThrottlingPolicy 0x1D
+#define PPSMC_MSG_ResetSDMA 0x1E
+#define PPSMC_MSG_GetRasTableVersion 0x1F
+#define PPSMC_MSG_GetRmaStatus 0x20
+#define PPSMC_MSG_GetBadPageCount 0x21
+#define PPSMC_MSG_GetBadPageMcaAddress 0x22
+#define PPSMC_MSG_GetBadPagePaAddress 0x23
+#define PPSMC_MSG_SetTimestamp 0x24
+#define PPSMC_MSG_GetTimestamp 0x25
+#define PPSMC_MSG_GetRasPolicy 0x26
+#define PPSMC_MSG_GetBadPageIpIdLoHi 0x27
+#define PPSMC_MSG_EraseRasTable 0x28
+#define PPSMC_MSG_GetStaticMetricsTable 0x29
+#define PPSMC_MSG_ResetVfArbitersByIndex 0x2A
+#define PPSMC_MSG_GetBadPageSeverity 0x2B
+#define PPSMC_MSG_GetSystemMetricsTable 0x2C
+#define PPSMC_MSG_GetSystemMetricsVersion 0x2D
+#define PPSMC_MSG_ResetVCN 0x2E
+#define PPSMC_MSG_SetFastPptLimit 0x2F
+#define PPSMC_MSG_GetFastPptLimit 0x30
+#define PPSMC_MSG_SetSoftMinGl2clk 0x31
+#define PPSMC_MSG_SetSoftMaxGl2clk 0x32
+#define PPSMC_MSG_SetSoftMinFclk 0x33
+#define PPSMC_MSG_SetSoftMaxFclk 0x34
+#define PPSMC_Message_Count 0x35
+
+/* PSMC Reset Types for driver msg argument */
+#define PPSMC_RESET_TYPE_DRIVER_MODE_1_RESET 0x1
+#define PPSMC_RESET_TYPE_DRIVER_MODE_2_RESET 0x2
+#define PPSMC_RESET_TYPE_DRIVER_MODE_3_RESET 0x3
+
+/* PLPD modes */
+#define PPSMC_PLPD_MODE_DEFAULT 0x1
+#define PPSMC_PLPD_MODE_OPTIMIZED 0x2
+
+typedef uint32_t PPSMC_Result;
+typedef uint32_t PPSMC_MSG;
+
+#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 03/25] drm/amd/pm: Add smu v15_0_8 pmfw header
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
2026-03-17 20:12 ` [PATCH 02/25] drm/amd/pm: Add smu v15_0_8 message header Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 04/25] drm/amd/pm: Add initial support for smu v15_0_8 Alex Deucher
` (21 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Hawking Zhang, Likun Gao, Yang Wang, Alex Deucher
From: Hawking Zhang <Hawking.Zhang@amd.com>
Add smu v15_0_8 pmfw header
v2: squash in updates (Alex)
Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Likun Gao <Likun.Gao@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h | 427 ++++++++++++++++++
1 file changed, 427 insertions(+)
create mode 100644 drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h
new file mode 100644
index 0000000000000..a3401c4cc20bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v15_0_8_pmfw.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2025 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 SMU_15_0_8_PMFW_H
+#define SMU_15_0_8_PMFW_H
+
+#define NUM_VCLK_DPM_LEVELS 4
+#define NUM_DCLK_DPM_LEVELS 4
+#define NUM_SOCCLK_DPM_LEVELS 4
+#define NUM_LCLK_DPM_LEVELS 4
+#define NUM_UCLK_DPM_LEVELS 4
+#define NUM_FCLK_DPM_LEVELS 4
+#define NUM_XGMI_DPM_LEVELS 2
+#define NUM_PCIE_BITRATES 4
+#define NUM_XGMI_BITRATES 4
+#define NUM_XGMI_WIDTHS 3
+#define NUM_GFX_P2S_TABLES 8
+#define NUM_PSM_DIDT_THRESHOLDS 3
+#define NUM_XCD_XVMIN_VMIN_THRESHOLDS 3
+
+#define PRODUCT_MODEL_NUMBER_LEN 20
+#define PRODUCT_NAME_LEN 64
+#define PRODUCT_SERIAL_LEN 20
+#define PRODUCT_MANUFACTURER_NAME_LEN 32
+#define PRODUCT_FRU_ID_LEN 32
+
+//Feature ID list
+#define FEATURE_ID_DATA_CALCULATION 1
+#define FEATURE_ID_DPM_FCLK 2
+#define FEATURE_ID_DPM_GFXCLK 3
+#define FEATURE_ID_DPM_SPARE_4 4
+#define FEATURE_ID_DPM_SPARE_5 5
+#define FEATURE_ID_DPM_UCLK 6
+#define FEATURE_ID_DPM_SPARE_7 7
+#define FEATURE_ID_DPM_XGMI 8
+#define FEATURE_ID_DS_FCLK 9
+#define FEATURE_ID_DS_GFXCLK 10
+#define FEATURE_ID_DS_LCLK 11
+#define FEATURE_ID_DS_MP0CLK 12
+#define FEATURE_ID_DS_MP1CLK 13
+#define FEATURE_ID_DS_MPIOCLK 14
+#define FEATURE_ID_DS_SOCCLK 15
+#define FEATURE_ID_DS_VCN 16
+#define FEATURE_ID_PPT 17
+#define FEATURE_ID_TDC 18
+#define FEATURE_ID_THERMAL 19
+#define FEATURE_ID_SOC_PCC 20
+#define FEATURE_ID_PROCHOT 21
+#define FEATURE_ID_XVMIN0_VMIN_AID 22
+#define FEATURE_ID_XVMIN1_DD_AID 23
+#define FEATURE_ID_XVMIN0_VMIN_XCD 24
+#define FEATURE_ID_XVMIN1_DD_XCD 25
+#define FEATURE_ID_FW_CTF 26
+#define FEATURE_ID_MGCG 27
+#define FEATURE_ID_PSI7 28
+#define FEATURE_ID_XGMI_PER_LINK_PWR_DOWN 29
+#define FEATURE_ID_SOC_DC_RTC 30
+#define FEATURE_ID_GFX_DC_RTC 31
+#define FEATURE_ID_DVM_MIN_PSM 32
+#define FEATURE_ID_PRC 33
+#define FEATURE_ID_PSM_DIDT 34
+#define FEATURE_ID_PIT 35
+#define FEATURE_ID_DVO 36
+#define FEATURE_ID_XVMIN_CLKSTOP_DS 37
+#define FEATURE_ID_HBM_THROTTLE_CTRL 38
+#define FEATURE_ID_DPM_GL2CLK 39
+#define FEATURE_ID_GC_CAC_EDC 40
+#define FEATURE_ID_DS_DMABECLK 41
+#define FEATURE_ID_DS_MPIFOECLK 42
+#define FEATURE_ID_DS_MPRASCLK 43
+#define FEATURE_ID_DS_MPNHTCLK 44
+#define FEATURE_ID_DS_FIOCLK 45
+#define FEATURE_ID_DS_DXIOCLK 46
+#define FEATURE_ID_PCC 47
+#define FEATURE_ID_OCP 48
+#define FEATURE_ID_TRO 49
+#define FEATURE_ID_GL2_CAC_EDC 50
+#define FEATURE_ID_SPARE_51 51
+#define FEATURE_ID_GL2_CGCG 52
+#define FEATURE_ID_XCAC 53
+#define FEATURE_ID_DS_GL2CLK 54
+#define FEATURE_ID_FCS_VIN_PCC 55
+#define FEATURE_ID_FCS_VDDX_OCP_WARN 56
+#define FEATURE_ID_FCS_PWRBRK 57
+#define FEATURE_ID_DF_CSTATE 58
+#define FEATURE_ID_ARO 59
+#define FEATURE_ID_PS_PsPowerLimit 60
+#define FEATURE_ID_PS_PsPowerFloor 61
+#define FEATURE_ID_OCPWARNRC 62
+#define FEATURE_ID_XGMI_FOLDING 63
+#define FEATURE_ID_SMU_CG 64
+#define NUM_FEATURES 65
+
+//MGCG Feature ID List
+#define WAFL_CG 0
+#define SMU_FUSE_CG_DEEPSLEEP 1
+#define SMUIO_CG 2
+#define RSMU_MGCG 3
+#define SMU_CLK_MGCG 4
+#define MP5_CG 5
+#define UMC_CG 6
+#define WAFL0_CLK 7
+#define WAFL1_CLK 8
+#define VCN_MGCG 9
+#define GL2_MGCG 10
+#define MGCG_NUM_FEATURES 11
+
+/* enum for MPIO PCIe gen speed msgs */
+typedef enum {
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN1,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN2,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN3,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN4,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN5,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN6,
+ PCIE_LINK_SPEED_INDEX_TABLE_GEN6_ESM,
+ PCIE_LINK_SPEED_INDEX_TABLE_COUNT
+} PCIE_LINK_SPEED_INDEX_TABLE_e;
+
+typedef enum {
+ GFX_GUARDBAND_OFFSET_0,
+ GFX_GUARDBAND_OFFSET_1,
+ GFX_GUARDBAND_OFFSET_2,
+ GFX_GUARDBAND_OFFSET_3,
+ GFX_GUARDBAND_OFFSET_4,
+ GFX_GUARDBAND_OFFSET_5,
+ GFX_GUARDBAND_OFFSET_6,
+ GFX_GUARDBAND_OFFSET_7,
+ GFX_GUARDBAND_OFFSET_COUNT
+} GFX_GUARDBAND_OFFSET_e;
+
+typedef enum {
+ GFX_DVM_MARGINHI_0,
+ GFX_DVM_MARGINHI_1,
+ GFX_DVM_MARGINHI_2,
+ GFX_DVM_MARGINHI_3,
+ GFX_DVM_MARGINHI_4,
+ GFX_DVM_MARGINHI_5,
+ GFX_DVM_MARGINHI_6,
+ GFX_DVM_MARGINHI_7,
+ GFX_DVM_MARGINLO_0,
+ GFX_DVM_MARGINLO_1,
+ GFX_DVM_MARGINLO_2,
+ GFX_DVM_MARGINLO_3,
+ GFX_DVM_MARGINLO_4,
+ GFX_DVM_MARGINLO_5,
+ GFX_DVM_MARGINLO_6,
+ GFX_DVM_MARGINLO_7,
+ GFX_DVM_MARGIN_COUNT
+} GFX_DVM_MARGIN_e;
+
+typedef enum{
+ SYSTEM_TEMP_UBB_FPGA,
+ SYSTEM_TEMP_UBB_FRONT,
+ SYSTEM_TEMP_UBB_BACK,
+ SYSTEM_TEMP_UBB_OAM7,
+ SYSTEM_TEMP_UBB_IBC,
+ SYSTEM_TEMP_UBB_UFPGA,
+ SYSTEM_TEMP_UBB_OAM1,
+ SYSTEM_TEMP_OAM_0_1_HSC,
+ SYSTEM_TEMP_OAM_2_3_HSC,
+ SYSTEM_TEMP_OAM_4_5_HSC,
+ SYSTEM_TEMP_OAM_6_7_HSC,
+ SYSTEM_TEMP_UBB_FPGA_0V72_VR,
+ SYSTEM_TEMP_UBB_FPGA_3V3_VR,
+ SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR,
+ SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR,
+ SYSTEM_TEMP_RETIMER_0_1_0V9_VR,
+ SYSTEM_TEMP_RETIMER_4_5_0V9_VR,
+ SYSTEM_TEMP_RETIMER_2_3_0V9_VR,
+ SYSTEM_TEMP_RETIMER_6_7_0V9_VR,
+ SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR,
+ SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR,
+ SYSTEM_TEMP_IBC_HSC,
+ SYSTEM_TEMP_IBC,
+ SYSTEM_TEMP_MAX_ENTRIES = 32
+} SYSTEM_TEMP_e;
+
+typedef enum{
+ NODE_TEMP_RETIMER,
+ NODE_TEMP_IBC_TEMP,
+ NODE_TEMP_IBC_2_TEMP,
+ NODE_TEMP_VDD18_VR_TEMP,
+ NODE_TEMP_04_HBM_B_VR_TEMP,
+ NODE_TEMP_04_HBM_D_VR_TEMP,
+ NODE_TEMP_MAX_TEMP_ENTRIES = 12
+} NODE_TEMP_e;
+
+typedef enum {
+ SVI_PLANE_VDDCR_X0_TEMP,
+ SVI_PLANE_VDDCR_X1_TEMP,
+
+ SVI_PLANE_VDDIO_HBM_B_TEMP,
+ SVI_PLANE_VDDIO_HBM_D_TEMP,
+ SVI_PLANE_VDDIO_04_HBM_B_TEMP,
+ SVI_PLANE_VDDIO_04_HBM_D_TEMP,
+ SVI_PLANE_VDDCR_HBM_B_TEMP,
+ SVI_PLANE_VDDCR_HBM_D_TEMP,
+ SVI_PLANE_VDDCR_075_HBM_B_TEMP,
+ SVI_PLANE_VDDCR_075_HBM_D_TEMP,
+
+ SVI_PLANE_VDDIO_11_GTA_A_TEMP,
+ SVI_PLANE_VDDIO_11_GTA_C_TEMP,
+ SVI_PLANE_VDDAN_075_GTA_A_TEMP,
+ SVI_PLANE_VDDAN_075_GTA_C_TEMP,
+
+ SVI_PLANE_VDDCR_075_UCIE_TEMP,
+ SVI_PLANE_VDDIO_065_UCIEAA_TEMP,
+ SVI_PLANE_VDDIO_065_UCIEAM_A_TEMP,
+ SVI_PLANE_VDDIO_065_UCIEAM_C_TEMP,
+
+ SVI_PLANE_VDDCR_SOCIO_A_TEMP,
+ SVI_PLANE_VDDCR_SOCIO_C_TEMP,
+
+ SVI_PLANE_VDDAN_075_TEMP,
+ SVI_MAX_TEMP_ENTRIES, //22
+} SVI_TEMP_e;
+
+typedef enum{
+ SYSTEM_POWER_UBB_POWER,
+ SYSTEM_POWER_UBB_POWER_THRESHOLD,
+ SYSTEM_POWER_MAX_ENTRIES_WO_RESERVED,
+ SYSTEM_POWER_MAX_ENTRIES = 4
+} SYSTEM_POWER_e;
+
+#define SMU_METRICS_TABLE_VERSION 0xF
+
+typedef struct __attribute__((packed, aligned(4))) {
+ uint64_t AccumulationCounter;
+
+ //TEMPERATURE
+ uint32_t MaxSocketTemperature;
+ uint32_t MaxVrTemperature;
+ uint32_t HbmTemperature[12];
+ uint64_t MaxSocketTemperatureAcc;
+ uint64_t MaxVrTemperatureAcc;
+ uint64_t HbmTemperatureAcc[12];
+ uint32_t MidTemperature[2];
+ uint32_t AidTemperature[2];
+ uint32_t XcdTemperature[8];
+
+ //POWER
+ uint32_t SocketPowerLimit;
+ uint32_t SocketPower;
+
+ //ENERGY
+ uint64_t Timestamp;
+ uint64_t SocketEnergyAcc;
+ uint64_t HbmEnergyAcc;
+
+ //FREQUENCY
+ uint32_t GfxclkFrequencyLimit;
+ uint32_t FclkFrequency[2];
+ uint32_t UclkFrequency[2];
+ uint64_t GfxclkFrequencyAcc[8];
+ uint32_t GfxclkFrequency[8];
+ uint32_t SocclkFrequency[2];
+ uint32_t VclkFrequency[4];
+ uint32_t DclkFrequency[4];
+ uint32_t LclkFrequency[2];
+
+ //XGMI:
+ uint32_t XgmiWidth;
+ uint32_t XgmiBitrate;
+ uint64_t XgmiReadBandwidthAcc;
+ uint64_t XgmiWriteBandwidthAcc;
+
+ //ACTIVITY:
+ uint32_t SocketGfxBusy;
+ uint32_t DramBandwidthUtilization;
+ uint64_t SocketGfxBusyAcc;
+ uint64_t DramBandwidthAcc;
+ uint32_t MaxDramBandwidth;
+ uint64_t DramBandwidthUtilizationAcc;
+ uint64_t PcieBandwidthAcc[2];
+
+ //THROTTLERS
+ uint64_t ProchotResidencyAcc;
+ uint64_t PptResidencyAcc;
+ uint64_t SocketThmResidencyAcc;
+ uint64_t VrThmResidencyAcc;
+ uint64_t HbmThmResidencyAcc;
+
+ //PCIE BW Data and error count
+ uint32_t PcieBandwidth[2];
+ uint64_t PCIeL0ToRecoveryCountAcc;
+ uint64_t PCIenReplayAAcc;
+ uint64_t PCIenReplayARolloverCountAcc;
+ uint64_t PCIeNAKSentCountAcc;
+ uint64_t PCIeNAKReceivedCountAcc;
+ uint64_t PCIeOtherEndRecoveryAcc; // The Pcie counter itself is accumulated
+
+ // VCN/JPEG ACTIVITY
+ uint32_t VcnBusy[4];
+ uint32_t JpegBusy[40];
+
+ // PCIE LINK Speed and width
+ uint32_t PCIeLinkSpeed;
+ uint32_t PCIeLinkWidth;
+
+ // PER XCD ACTIVITY
+ uint32_t GfxBusy[8];
+ uint64_t GfxBusyAcc[8];
+
+ //NVML-Parity: Total App Clock Counter
+ uint64_t GfxclkBelowHostLimitPptAcc[8];
+ uint64_t GfxclkBelowHostLimitThmAcc[8];
+ uint64_t GfxclkBelowHostLimitTotalAcc[8];
+ uint64_t GfxclkLowUtilizationAcc[8];
+} MetricsTable_t;
+
+#define SMU_SYSTEM_METRICS_TABLE_VERSION 0x1
+
+#pragma pack(push, 4)
+typedef struct {
+ uint64_t AccumulationCounter; // Last update timestamp
+ uint16_t LabelVersion; //Defaults to 0.
+ uint16_t NodeIdentifier;
+ int16_t SystemTemperatures[SYSTEM_TEMP_MAX_ENTRIES]; // Signed integer temperature value in Celsius, unused fields are set to 0xFFFF
+ int16_t NodeTemperatures[NODE_TEMP_MAX_TEMP_ENTRIES]; // Signed integer temperature value in Celsius, unused fields are set to 0xFFFF
+ int16_t VrTemperatures[SVI_MAX_TEMP_ENTRIES]; // Signed integer temperature value in Celsius, 13 entries,
+ int16_t spare[7];
+
+ //NPM: NODE POWER MANAGEMENT
+ uint32_t NodePowerLimit;
+ uint32_t NodePower;
+ uint32_t GlobalPPTResidencyAcc;
+
+ uint16_t SystemPower[SYSTEM_POWER_MAX_ENTRIES]; // UBB Current Power and Power Threshold
+} SystemMetricsTable_t;
+#pragma pack(pop)
+
+#define SMU_VF_METRICS_TABLE_VERSION 0x5
+
+typedef struct __attribute__((packed, aligned(4))) {
+ uint32_t AccumulationCounter;
+ uint32_t InstGfxclk_TargFreq;
+ uint64_t AccGfxclk_TargFreq;
+ uint64_t AccGfxRsmuDpm_Busy;
+ uint64_t AccGfxclkBelowHostLimit;
+} VfMetricsTable_t;
+
+/* FRU product information */
+typedef struct __attribute__((aligned(4))) {
+ uint8_t ModelNumber[PRODUCT_MODEL_NUMBER_LEN];
+ uint8_t Name[PRODUCT_NAME_LEN];
+ uint8_t Serial[PRODUCT_SERIAL_LEN];
+ uint8_t ManufacturerName[PRODUCT_MANUFACTURER_NAME_LEN];
+ uint8_t FruId[PRODUCT_FRU_ID_LEN];
+} FRUProductInfo_t;
+
+#define SMU_STATIC_METRICS_TABLE_VERSION 0x1
+
+#pragma pack(push, 4)
+typedef struct {
+ //FRU PRODUCT INFO
+ FRUProductInfo_t ProductInfo; //from i2c
+
+ //POWER
+ uint32_t MaxSocketPowerLimit;
+
+ //FREQUENCY RANGE
+ uint32_t MaxGfxclkFrequency;
+ uint32_t MinGfxclkFrequency;
+ uint32_t MaxFclkFrequency;
+ uint32_t MinFclkFrequency;
+ uint32_t MaxGl2clkFrequency;
+ uint32_t MinGl2clkFrequency;
+ uint32_t UclkFrequencyTable[4];
+ uint32_t SocclkFrequency;
+ uint32_t LclkFrequency;
+ uint32_t VclkFrequency;
+ uint32_t DclkFrequency;
+
+ //CTF limits
+ uint32_t CTFLimit_MID;
+ uint32_t CTFLimit_AID;
+ uint32_t CTFLimit_XCD;
+ uint32_t CTFLimit_HBM;
+
+ //Thermal Throttling limits
+ uint32_t ThermalLimit_MID;
+ uint32_t ThermalLimit_AID;
+ uint32_t ThermalLimit_XCD;
+ uint32_t ThermalLimit_HBM;
+
+ //PSNs
+ uint64_t PublicSerialNumber_MID[2];
+ uint64_t PublicSerialNumber_AID[2];
+ uint64_t PublicSerialNumber_XCD[8];
+
+ //XGMI
+ uint32_t MaxXgmiWidth;
+ uint32_t MaxXgmiBitrate;
+
+ // Telemetry
+ uint32_t InputTelemetryVoltageInmV;
+
+ // General info
+ uint32_t pldmVersion[2];
+
+ uint32_t PPT1Max;
+ uint32_t PPT1Min;
+ uint32_t PPT1Default;
+} StaticMetricsTable_t;
+#pragma pack(pop)
+
+#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 04/25] drm/amd/pm: Add initial support for smu v15_0_8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
2026-03-17 20:12 ` [PATCH 02/25] drm/amd/pm: Add smu v15_0_8 message header Alex Deucher
2026-03-17 20:12 ` [PATCH 03/25] drm/amd/pm: Add smu v15_0_8 pmfw header Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 05/25] drm/amd/pm: Add mode2 support for smu_v15_0_8 Alex Deucher
` (20 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Hawking Zhang, Likun Gao, Yang Wang, Alex Deucher
From: Hawking Zhang <Hawking.Zhang@amd.com>
smu v15_0_8 is the new generation of smu ip block
v2: Squash in rebase changes (Alex)
v3: Squash in fw version check changes (Alex)
Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Likun Gao <Likun.Gao@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 +
drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 15 +-
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h | 6 +
drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile | 2 +-
.../gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c | 81 ++-
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 483 ++++++++++++++++++
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h | 28 +
7 files changed, 564 insertions(+), 52 deletions(-)
create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 3dc9171941542..5a92ab9601a15 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -47,6 +47,7 @@
#include "smu_v14_0_0_ppt.h"
#include "smu_v14_0_2_ppt.h"
#include "smu_v15_0_0_ppt.h"
+#include "smu_v15_0_8_ppt.h"
#include "amd_pcie.h"
/*
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index 584c4cfd0c16f..5f77749998e32 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -292,7 +292,12 @@
__SMU_DUMMY_MAP(AllowZstates), \
__SMU_DUMMY_MAP(GetSmartShiftStatus), \
__SMU_DUMMY_MAP(EnableLSdma), \
- __SMU_DUMMY_MAP(DisableLSdma),
+ __SMU_DUMMY_MAP(DisableLSdma), \
+ __SMU_DUMMY_MAP(InitializeGfx), \
+ __SMU_DUMMY_MAP(SetSoftMaxFclk), \
+ __SMU_DUMMY_MAP(SetSoftMaxGl2clk), \
+ __SMU_DUMMY_MAP(SetSoftMinGl2clk), \
+ __SMU_DUMMY_MAP(GetSystemMetricsVersion),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
@@ -472,6 +477,14 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(GFX_DIDT_XVMIN), \
__SMU_DUMMY_MAP(FAN_ABNORMAL), \
__SMU_DUMMY_MAP(PIT), \
+ __SMU_DUMMY_MAP(DS_DMABECLK), \
+ __SMU_DUMMY_MAP(DS_MPIFOECLK), \
+ __SMU_DUMMY_MAP(DS_MPRASCLK), \
+ __SMU_DUMMY_MAP(DS_MPNHTCLK), \
+ __SMU_DUMMY_MAP(DS_FIOCLK), \
+ __SMU_DUMMY_MAP(DS_DXIOCLK), \
+ __SMU_DUMMY_MAP(DS_GL2CLK), \
+ __SMU_DUMMY_MAP(DPM_GL2CLK), \
__SMU_DUMMY_MAP(HROM_EN),
#undef __SMU_DUMMY_MAP
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
index 09743ccd0d15c..95c77e926e1fe 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
@@ -41,6 +41,10 @@
#define smnMP1_FIRMWARE_FLAGS 0x3010024
#define smnMP1_PUB_CTRL 0x3010d10
+#define SMU15_DRIVER_IF_VERSION_SMU_V15_0_8 0x007D0000
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+
#define MAX_DPM_LEVELS 16
#define MAX_PCIE_CONF 3
@@ -104,6 +108,7 @@ struct smu_15_0_dpm_context {
struct smu_15_0_dpm_tables dpm_tables;
uint32_t workload_policy_mask;
uint32_t dcef_min_ds_clk;
+ uint64_t caps;
};
enum smu_15_0_power_state {
@@ -118,6 +123,7 @@ struct smu_15_0_power_context {
uint32_t power_source;
uint8_t in_power_limit_boost_mode;
enum smu_15_0_power_state power_state;
+ atomic_t throttle_status;
};
#if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile
index 7f59a0aabdeb6..fa083ad46c0fd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/Makefile
@@ -23,7 +23,7 @@
# Makefile for the 'smu manager' sub-component of powerplay.
# It provides the smu management services for the driver.
-SMU15_MGR = smu_v15_0.o smu_v15_0_0_ppt.o
+SMU15_MGR = smu_v15_0.o smu_v15_0_0_ppt.o smu_v15_0_8_ppt.o
AMD_SWSMU_SMU15MGR = $(addprefix $(AMD_SWSMU_PATH)/smu15/,$(SMU15_MGR))
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
index 478ee87af51f3..51d1f5d42ad31 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
@@ -590,71 +590,52 @@ int smu_v15_0_notify_memory_pool_location(struct smu_context *smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *memory_pool = &smu_table->memory_pool;
- int ret = 0;
- uint64_t address;
- uint32_t address_low, address_high;
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_DramLogSetDramAddr,
+ .num_args = 3,
+ .num_out_args = 0,
+ };
if (memory_pool->size == 0 || memory_pool->cpu_addr == NULL)
- return ret;
-
- address = memory_pool->mc_address;
- address_high = (uint32_t)upper_32_bits(address);
- address_low = (uint32_t)lower_32_bits(address);
+ return 0;
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrHigh,
- address_high, NULL);
- if (ret)
- return ret;
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrLow,
- address_low, NULL);
- if (ret)
- return ret;
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramSize,
- (uint32_t)memory_pool->size, NULL);
- if (ret)
- return ret;
+ /* SMU_MSG_DramLogSetDramAddr: ARG0=low, ARG1=high, ARG2=size */
+ args.args[0] = lower_32_bits(memory_pool->mc_address);
+ args.args[1] = upper_32_bits(memory_pool->mc_address);
+ args.args[2] = (u32)memory_pool->size;
- return ret;
+ return smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
}
int smu_v15_0_set_driver_table_location(struct smu_context *smu)
{
struct smu_table *driver_table = &smu->smu_table.driver_table;
- int ret = 0;
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_SetDriverDramAddrHigh,
+ .num_args = 2,
+ .num_out_args = 0,
+ };
- if (driver_table->mc_address) {
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetDriverDramAddrHigh,
- upper_32_bits(driver_table->mc_address),
- NULL);
- if (!ret)
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetDriverDramAddrLow,
- lower_32_bits(driver_table->mc_address),
- NULL);
- }
+ args.args[0] = lower_32_bits(driver_table->mc_address);
+ args.args[1] = upper_32_bits(driver_table->mc_address);
- return ret;
+ return smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
}
int smu_v15_0_set_tool_table_location(struct smu_context *smu)
{
- int ret = 0;
struct smu_table *tool_table = &smu->smu_table.tables[SMU_TABLE_PMSTATUSLOG];
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_SetToolsDramAddrHigh,
+ .num_args = 2,
+ .num_out_args = 0,
+ };
- if (tool_table->mc_address) {
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetToolsDramAddrHigh,
- upper_32_bits(tool_table->mc_address),
- NULL);
- if (!ret)
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetToolsDramAddrLow,
- lower_32_bits(tool_table->mc_address),
- NULL);
- }
+ /* SMU_MSG_SetToolsDramAddr: ARG0=low, ARG1=high */
+ args.args[0] = lower_32_bits(tool_table->mc_address);
+ args.args[1] = upper_32_bits(tool_table->mc_address);
- return ret;
+ return smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
}
int smu_v15_0_set_allowed_mask(struct smu_context *smu)
@@ -701,8 +682,7 @@ int smu_v15_0_gfx_off_control(struct smu_context *smu, bool enable)
return ret;
}
-int smu_v15_0_system_features_control(struct smu_context *smu,
- bool en)
+int smu_v15_0_system_features_control(struct smu_context *smu, bool en)
{
return smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures :
SMU_MSG_DisableAllSmuFeatures), NULL);
@@ -906,7 +886,8 @@ static int smu_v15_0_wait_for_reset_complete(struct smu_context *smu,
return ret;
}
-int smu_v15_0_wait_for_event(struct smu_context *smu, enum smu_event_type event,
+int smu_v15_0_wait_for_event(struct smu_context *smu,
+ enum smu_event_type event,
uint64_t event_arg)
{
int ret = -EINVAL;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
new file mode 100644
index 0000000000000..c4da0cdc1222a
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2025 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.
+ *
+ */
+
+#define SWSMU_CODE_LAYER_L2
+
+#include <linux/firmware.h>
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "smu_v15_0_8_pmfw.h"
+#include "smu15_driver_if_v15_0_8.h"
+#include "smu_v15_0_8_ppsmc.h"
+#include "smu_v15_0_8_ppt.h"
+#include <linux/pci.h>
+#include "smu_cmn.h"
+#include "mp/mp_15_0_8_offset.h"
+#include "mp/mp_15_0_8_sh_mask.h"
+#include "smu_v15_0.h"
+
+#undef MP1_Public
+
+/* address block */
+#define MP1_Public 0x03b00000
+#define smnMP1_FIRMWARE_FLAGS_15_0_8 0x3010024
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+
+#define SMU_15_0_8_FEA_MAP(smu_feature, smu_15_0_8_feature) \
+ [smu_feature] = { 1, (smu_15_0_8_feature) }
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+
+static const struct smu_feature_bits smu_v15_0_8_dpm_features = {
+ .bits = { SMU_FEATURE_BIT_INIT(FEATURE_ID_DATA_CALCULATION),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_GFXCLK),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_UCLK),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_FCLK),
+ SMU_FEATURE_BIT_INIT(FEATURE_ID_DPM_GL2CLK) }
+};
+
+static const struct cmn2asic_msg_mapping smu_v15_0_8_message_map[SMU_MSG_MAX_COUNT] = {
+ MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0),
+ MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
+ MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDriverReset, SMU_MSG_RAS_PRI | SMU_MSG_NO_PRECHECK),
+ MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
+ MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
+ MSG_MAP(GetMetricsVersion, PPSMC_MSG_GetMetricsVersion, 1),
+ MSG_MAP(GetMetricsTable, PPSMC_MSG_GetMetricsTable, 1),
+ MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 1),
+ MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddr, 1),
+ MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddr, 0),
+ MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1),
+ MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
+ MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1),
+ MSG_MAP(DramLogSetDramAddr, PPSMC_MSG_DramLogSetDramAddr, 0),
+ MSG_MAP(HeavySBR, PPSMC_MSG_HeavySBR, 0),
+ MSG_MAP(DFCstateControl, PPSMC_MSG_DFCstateControl, 0),
+ MSG_MAP(GfxDriverResetRecovery, PPSMC_MSG_GfxDriverResetRecovery, 0),
+ MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 1),
+ MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1),
+ MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareForDriverUnload, 0),
+ MSG_MAP(QueryValidMcaCount, PPSMC_MSG_QueryValidMcaCount, SMU_MSG_RAS_PRI),
+ MSG_MAP(McaBankDumpDW, PPSMC_MSG_McaBankDumpDW, SMU_MSG_RAS_PRI),
+ MSG_MAP(ClearMcaOnRead, PPSMC_MSG_ClearMcaOnRead, 0),
+ MSG_MAP(QueryValidMcaCeCount, PPSMC_MSG_QueryValidMcaCeCount, SMU_MSG_RAS_PRI),
+ MSG_MAP(McaBankCeDumpDW, PPSMC_MSG_McaBankCeDumpDW, SMU_MSG_RAS_PRI),
+ MSG_MAP(SelectPLPDMode, PPSMC_MSG_SelectPLPDMode, 0),
+ MSG_MAP(SetThrottlingPolicy, PPSMC_MSG_SetThrottlingPolicy, 0),
+ MSG_MAP(ResetSDMA, PPSMC_MSG_ResetSDMA, 0),
+ MSG_MAP(GetRASTableVersion, PPSMC_MSG_GetRasTableVersion, 0),
+ MSG_MAP(SetTimestamp, PPSMC_MSG_SetTimestamp, 0),
+ MSG_MAP(GetTimestamp, PPSMC_MSG_GetTimestamp, 0),
+ MSG_MAP(GetBadPageIpid, PPSMC_MSG_GetBadPageIpIdLoHi, 0),
+ MSG_MAP(EraseRasTable, PPSMC_MSG_EraseRasTable, 0),
+ MSG_MAP(GetStaticMetricsTable, PPSMC_MSG_GetStaticMetricsTable, 1),
+ MSG_MAP(GetSystemMetricsTable, PPSMC_MSG_GetSystemMetricsTable, 1),
+ MSG_MAP(GetSystemMetricsVersion, PPSMC_MSG_GetSystemMetricsVersion, 0),
+ MSG_MAP(ResetVCN, PPSMC_MSG_ResetVCN, 0),
+ MSG_MAP(SetFastPptLimit, PPSMC_MSG_SetFastPptLimit, 0),
+ MSG_MAP(GetFastPptLimit, PPSMC_MSG_GetFastPptLimit, 0),
+ MSG_MAP(SetSoftMinGl2clk, PPSMC_MSG_SetSoftMinGl2clk, 0),
+ MSG_MAP(SetSoftMaxGl2clk, PPSMC_MSG_SetSoftMaxGl2clk, 0),
+ MSG_MAP(SetSoftMinFclk, PPSMC_MSG_SetSoftMinFclk, 0),
+ MSG_MAP(SetSoftMaxFclk, PPSMC_MSG_SetSoftMaxFclk, 0),
+};
+
+/* TODO: Update the clk map once enum PPCLK is updated in smu15_driver_if_v15_0_8.h */
+static struct cmn2asic_mapping smu_v15_0_8_clk_map[SMU_CLK_COUNT] = {
+ CLK_MAP(UCLK, PPCLK_UCLK),
+};
+
+static const struct cmn2asic_mapping smu_v15_0_8_feature_mask_map[SMU_FEATURE_COUNT] = {
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT, FEATURE_ID_DATA_CALCULATION),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT, FEATURE_ID_DPM_GFXCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_UCLK_BIT, FEATURE_ID_DPM_UCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_FCLK_BIT, FEATURE_ID_DPM_FCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DPM_GL2CLK_BIT, FEATURE_ID_DPM_GL2CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_GFXCLK_BIT, FEATURE_ID_DS_GFXCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_SOCCLK_BIT, FEATURE_ID_DS_SOCCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_LCLK_BIT, FEATURE_ID_DS_LCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_FCLK_BIT, FEATURE_ID_DS_FCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_DMABECLK_BIT, FEATURE_ID_DS_DMABECLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPIFOECLK_BIT, FEATURE_ID_DS_MPIFOECLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPRASCLK_BIT, FEATURE_ID_DS_MPRASCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPNHTCLK_BIT, FEATURE_ID_DS_MPNHTCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_FIOCLK_BIT, FEATURE_ID_DS_FIOCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_DXIOCLK_BIT, FEATURE_ID_DS_DXIOCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_GL2CLK_BIT, FEATURE_ID_DS_GL2CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_PPT_BIT, FEATURE_ID_PPT),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_TDC_BIT, FEATURE_ID_TDC),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_MP1_CG_BIT, FEATURE_ID_SMU_CG),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_FW_CTF_BIT, FEATURE_ID_FW_CTF),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_THERMAL_BIT, FEATURE_ID_THERMAL),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_SOC_PCC_BIT, FEATURE_ID_SOC_PCC),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_XGMI_PER_LINK_PWR_DWN_BIT, FEATURE_ID_XGMI_PER_LINK_PWR_DOWN),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_VCN_BIT, FEATURE_ID_DS_VCN),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MP1CLK_BIT, FEATURE_ID_DS_MP1CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MPIOCLK_BIT, FEATURE_ID_DS_MPIOCLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_DS_MP0CLK_BIT, FEATURE_ID_DS_MP0CLK),
+ SMU_15_0_8_FEA_MAP(SMU_FEATURE_PIT_BIT, FEATURE_ID_PIT),
+};
+
+#define TABLE_PMSTATUSLOG 0
+#define TABLE_SMU_METRICS 1
+#define TABLE_I2C_COMMANDS 2
+#define TABLE_COUNT 3
+
+static const struct cmn2asic_mapping smu_v15_0_8_table_map[SMU_TABLE_COUNT] = {
+ TAB_MAP(PMSTATUSLOG),
+ TAB_MAP(SMU_METRICS),
+ TAB_MAP(I2C_COMMANDS),
+};
+
+static int smu_v15_0_8_tables_init(struct smu_context *smu)
+{
+ return 0;
+}
+
+static int smu_v15_0_8_allocate_dpm_context(struct smu_context *smu)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+
+ smu_dpm->dpm_context =
+ kzalloc(sizeof(struct smu_15_0_dpm_context), GFP_KERNEL);
+ if (!smu_dpm->dpm_context)
+ return -ENOMEM;
+ smu_dpm->dpm_context_size = sizeof(struct smu_15_0_dpm_context);
+
+ smu_dpm->dpm_policies =
+ kzalloc(sizeof(struct smu_dpm_policy_ctxt), GFP_KERNEL);
+ if (!smu_dpm->dpm_policies) {
+ kfree(smu_dpm->dpm_context);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_init_smc_tables(struct smu_context *smu)
+{
+ int ret = 0;
+
+ ret = smu_v15_0_8_tables_init(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_v15_0_8_allocate_dpm_context(smu);
+
+ return ret;
+}
+
+static int smu_v15_0_8_init_allowed_features(struct smu_context *smu)
+{
+ /* pptable will handle the features to enable */
+ smu_feature_list_set_all(smu, SMU_FEATURE_LIST_ALLOWED);
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_default_dpm_table(struct smu_context *smu)
+{
+ return 0;
+}
+
+static int smu_v15_0_8_setup_pptable(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+
+ /* TODO: PPTable is not available.
+ * 1) Find an alternate way to get 'PPTable values' here.
+ * 2) Check if there is SW CTF
+ */
+ table_context->thermal_controller_type = 0;
+
+ return 0;
+}
+
+static int smu_v15_0_8_check_fw_status(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t mp1_fw_flags;
+
+ mp1_fw_flags = RREG32_PCIE(MP1_Public |
+ (smnMP1_FIRMWARE_FLAGS_15_0_8 & 0xffffffff));
+
+ if ((mp1_fw_flags & MP1_CRU1_MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+ MP1_CRU1_MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
+ return 0;
+
+ return -EIO;
+}
+
+static int smu_v15_0_8_irq_process(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ struct amdgpu_iv_entry *entry)
+{
+ struct smu_context *smu = adev->powerplay.pp_handle;
+ struct smu_power_context *smu_power = &smu->smu_power;
+ struct smu_15_0_power_context *power_context = smu_power->power_context;
+ uint32_t client_id = entry->client_id;
+ uint32_t ctxid = entry->src_data[0];
+ uint32_t src_id = entry->src_id;
+ uint32_t data;
+
+ if (client_id == SOC_V1_0_IH_CLIENTID_MP1) {
+ if (src_id == IH_INTERRUPT_ID_TO_DRIVER) {
+ /* ACK SMUToHost interrupt */
+ data = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, data);
+ /*
+ * ctxid is used to distinguish different events for SMCToHost
+ * interrupt.
+ */
+ switch (ctxid) {
+ case IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING:
+ /*
+ * Increment the throttle interrupt counter
+ */
+ atomic64_inc(&smu->throttle_int_counter);
+
+ if (!atomic_read(&adev->throttling_logging_enabled))
+ return 0;
+
+ /* This uses the new method which fixes the
+ * incorrect throttling status reporting
+ * through metrics table. For older FWs,
+ * it will be ignored.
+ */
+ if (__ratelimit(&adev->throttling_logging_rs)) {
+ atomic_set(
+ &power_context->throttle_status,
+ entry->src_data[1]);
+ schedule_work(&smu->throttling_logging_work);
+ }
+ break;
+ default:
+ dev_dbg(adev->dev, "Unhandled context id %d from client:%d!\n",
+ ctxid, client_id);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_irq_state(struct amdgpu_device *adev,
+ struct amdgpu_irq_src *source,
+ unsigned type,
+ enum amdgpu_interrupt_state state)
+{
+ uint32_t val = 0;
+
+ switch (state) {
+ case AMDGPU_IRQ_STATE_DISABLE:
+ /* For MP1 SW irqs */
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
+
+ break;
+ case AMDGPU_IRQ_STATE_ENABLE:
+ /* For MP1 SW irqs */
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT, val);
+
+ val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+ val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0);
+ WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct amdgpu_irq_src_funcs smu_v15_0_8_irq_funcs = {
+ .set = smu_v15_0_8_set_irq_state,
+ .process = smu_v15_0_8_irq_process,
+};
+
+static int smu_v15_0_8_register_irq_handler(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct amdgpu_irq_src *irq_src = &smu->irq_source;
+ int ret = 0;
+
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ irq_src->num_types = 1;
+ irq_src->funcs = &smu_v15_0_8_irq_funcs;
+
+ ret = amdgpu_irq_add_id(adev, SOC_V1_0_IH_CLIENTID_MP1,
+ IH_INTERRUPT_ID_TO_DRIVER,
+ irq_src);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int smu_v15_0_8_notify_unload(struct smu_context *smu)
+{
+ if (amdgpu_in_reset(smu->adev))
+ return 0;
+
+ dev_dbg(smu->adev->dev, "Notify PMFW about driver unload");
+ /* Ignore return, just intimate FW that driver is not going to be there */
+ smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
+
+ return 0;
+}
+
+
+static int smu_v15_0_8_system_features_control(struct smu_context *smu,
+ bool enable)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ if (enable)
+ ret = smu_v15_0_system_features_control(smu, enable);
+ else
+ smu_v15_0_8_notify_unload(smu);
+
+ return ret;
+}
+
+/**
+ * smu_v15_0_8_get_enabled_mask - Get enabled SMU features (128-bit)
+ * @smu: SMU context
+ * @feature_mask: feature mask structure
+ *
+ * SMU 15 returns all 128 feature bits in a single message via out_args[0..3].
+ * For backward compatibility, this function returns only the first 64 bits.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int smu_v15_0_8_get_enabled_mask(struct smu_context *smu,
+ struct smu_feature_bits *feature_mask)
+{
+ struct smu_msg_args args = {
+ .msg = SMU_MSG_GetEnabledSmuFeatures,
+ .num_args = 0,
+ .num_out_args = 2,
+ };
+ int ret;
+
+ if (!feature_mask)
+ return -EINVAL;
+
+ ret = smu->msg_ctl.ops->send_msg(&smu->msg_ctl, &args);
+
+ if (ret)
+ return ret;
+
+ smu_feature_bits_from_arr32(feature_mask, args.out_args,
+ SMU_FEATURE_NUM_DEFAULT);
+
+ return 0;
+}
+
+static bool smu_v15_0_8_is_dpm_running(struct smu_context *smu)
+{
+ int ret = 0;
+ struct smu_feature_bits feature_enabled;
+
+ ret = smu_v15_0_8_get_enabled_mask(smu, &feature_enabled);
+ if (ret)
+ return false;
+
+ return smu_feature_bits_test_mask(&feature_enabled,
+ smu_v15_0_8_dpm_features.bits);
+}
+
+static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
+ .init_allowed_features = smu_v15_0_8_init_allowed_features,
+ .set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
+ .is_dpm_running = smu_v15_0_8_is_dpm_running,
+ .init_smc_tables = smu_v15_0_8_init_smc_tables,
+ .fini_smc_tables = smu_v15_0_fini_smc_tables,
+ .init_power = smu_v15_0_init_power,
+ .fini_power = smu_v15_0_fini_power,
+ .check_fw_status = smu_v15_0_8_check_fw_status,
+ .check_fw_version = smu_cmn_check_fw_version,
+ .set_driver_table_location = smu_v15_0_set_driver_table_location,
+ .set_tool_table_location = smu_v15_0_set_tool_table_location,
+ .notify_memory_pool_location = smu_v15_0_notify_memory_pool_location,
+ .system_features_control = smu_v15_0_8_system_features_control,
+ .get_enabled_mask = smu_v15_0_8_get_enabled_mask,
+ .feature_is_enabled = smu_cmn_feature_is_enabled,
+ .register_irq_handler = smu_v15_0_8_register_irq_handler,
+ .setup_pptable = smu_v15_0_8_setup_pptable,
+ .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
+ .wait_for_event = smu_v15_0_wait_for_event,
+};
+
+static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
+ const struct cmn2asic_msg_mapping *message_map)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct smu_msg_ctl *ctl = &smu->msg_ctl;
+
+ ctl->smu = smu;
+ mutex_init(&ctl->lock);
+ ctl->config.msg_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_40);
+ ctl->config.resp_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_41);
+ ctl->config.arg_regs[0] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_42);
+ ctl->config.arg_regs[1] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_43);
+ ctl->config.arg_regs[2] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_44);
+ ctl->config.arg_regs[3] = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_45);
+ ctl->config.num_arg_regs = 4;
+ ctl->ops = &smu_msg_v1_ops;
+ ctl->default_timeout = adev->usec_timeout * 20;
+ ctl->message_map = message_map;
+}
+
+void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu)
+{
+ smu->ppt_funcs = &smu_v15_0_8_ppt_funcs;
+ smu->clock_map = smu_v15_0_8_clk_map;
+ smu->feature_map = smu_v15_0_8_feature_mask_map;
+ smu->table_map = smu_v15_0_8_table_map;
+ smu_v15_0_8_init_msg_ctl(smu, smu_v15_0_8_message_map);
+ smu->smc_driver_if_version = SMU15_DRIVER_IF_VERSION_SMU_V15_0_8;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
new file mode 100644
index 0000000000000..40c410928c966
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2025 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 __SMU_15_0_8_PPT_H__
+#define __SMU_15_0_8_PPT_H__
+
+extern void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu);
+
+#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 05/25] drm/amd/pm: Add mode2 support for smu_v15_0_8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (2 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 04/25] drm/amd/pm: Add initial support for smu v15_0_8 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 06/25] drm/amd/pm: Add static metrics support Alex Deucher
` (19 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Yang Wang, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add initial mode2 support for smu_v15_0_8
v2: Move out non smu code, remove pci save/restore logic (Lijo)
v3: squash in updated msg (Alex)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 44 +++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index c4da0cdc1222a..b3dc04ea5e713 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -430,6 +430,49 @@ static bool smu_v15_0_8_is_dpm_running(struct smu_context *smu)
smu_v15_0_8_dpm_features.bits);
}
+static int smu_v15_0_8_mode2_reset(struct smu_context *smu)
+{
+ struct smu_msg_ctl *ctl = &smu->msg_ctl;
+ struct amdgpu_device *adev = smu->adev;
+ int timeout = 10;
+ int ret = 0;
+
+ mutex_lock(&ctl->lock);
+
+ ret = smu_msg_send_async_locked(ctl, SMU_MSG_GfxDeviceDriverReset,
+ SMU_RESET_MODE_2);
+
+ if (ret)
+ goto out;
+
+ /* Reset takes a bit longer, wait for 200ms. */
+ msleep(200);
+
+ dev_dbg(adev->dev, "wait for reset ack\n");
+ do {
+ ret = smu_msg_wait_response(ctl, 0);
+ /* Wait a bit more time for getting ACK */
+ if (ret == -ETIME) {
+ --timeout;
+ usleep_range(500, 1000);
+ continue;
+ }
+
+ if (ret)
+ goto out;
+
+ } while (ret == -ETIME && timeout);
+
+out:
+ mutex_unlock(&ctl->lock);
+
+ if (ret)
+ dev_err(adev->dev, "failed to send mode2 reset, error code %d",
+ ret);
+
+ return ret;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -450,6 +493,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.setup_pptable = smu_v15_0_8_setup_pptable,
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.wait_for_event = smu_v15_0_wait_for_event,
+ .mode2_reset = smu_v15_0_8_mode2_reset,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 06/25] drm/amd/pm: Add static metrics support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (3 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 05/25] drm/amd/pm: Add mode2 support for smu_v15_0_8 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 07/25] drm/amd/pm: Setup driver pptable for smu 15.0.8 Alex Deucher
` (18 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add static metrics support for smu_v15_0_8
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index b3dc04ea5e713..ae2e0d44b1da1 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -238,6 +238,26 @@ static int smu_v15_0_8_check_fw_status(struct smu_context *smu)
return -EIO;
}
+static int smu_v15_0_8_get_static_metrics_table(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ uint32_t table_size = smu_table->tables[SMU_TABLE_SMU_METRICS].size;
+ struct smu_table *table = &smu_table->driver_table;
+ int ret;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetStaticMetricsTable, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev,
+ "Failed to export static metrics table!\n");
+ return ret;
+ }
+
+ amdgpu_hdp_invalidate(smu->adev, NULL);
+ memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
+
+ return 0;
+}
+
static int smu_v15_0_8_irq_process(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 07/25] drm/amd/pm: Setup driver pptable for smu 15.0.8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (4 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 06/25] drm/amd/pm: Add static metrics support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 08/25] drm/amd/pm: Update dpm table structs for smu_v15_0 Alex Deucher
` (17 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Yang Wang, Asad Kamal, Lijo Lazar, Alex Deucher
From: Yang Wang <kevinyang.wang@amd.com>
Setup driver pptable and initialize data from static metrics table for
smu_v15_0_8
v2: Remove unrelated changes and update description (Lijo)
v3: Use ARRAY_SIZE (Lijo)
v4: Move structure to header file
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 +
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h | 1 +
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 210 +++++++++++++++++-
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h | 30 +++
4 files changed, 237 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 892c90b8d063b..49e7881750fa7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -690,6 +690,7 @@ enum amdgpu_uid_type {
AMDGPU_UID_TYPE_XCD,
AMDGPU_UID_TYPE_AID,
AMDGPU_UID_TYPE_SOC,
+ AMDGPU_UID_TYPE_MID,
AMDGPU_UID_TYPE_MAX
};
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
index 95c77e926e1fe..06842d38c92bd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
@@ -109,6 +109,7 @@ struct smu_15_0_dpm_context {
uint32_t workload_policy_mask;
uint32_t dcef_min_ds_clk;
uint64_t caps;
+ uint32_t board_volt;
};
enum smu_15_0_power_state {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index ae2e0d44b1da1..82b09fe7fccd5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -35,6 +35,7 @@
#include "mp/mp_15_0_8_offset.h"
#include "mp/mp_15_0_8_sh_mask.h"
#include "smu_v15_0.h"
+#include "amdgpu_fru_eeprom.h"
#undef MP1_Public
@@ -51,6 +52,10 @@
#undef pr_info
#undef pr_debug
+#define SMUQ10_TO_UINT(x) ((x) >> 10)
+#define SMUQ10_FRAC(x) ((x) & 0x3ff)
+#define SMUQ10_ROUND(x) ((SMUQ10_TO_UINT(x)) + ((SMUQ10_FRAC(x)) >= 0x200))
+
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
#define SMU_15_0_8_FEA_MAP(smu_feature, smu_15_0_8_feature) \
@@ -161,6 +166,35 @@ static const struct cmn2asic_mapping smu_v15_0_8_table_map[SMU_TABLE_COUNT] = {
static int smu_v15_0_8_tables_init(struct smu_context *smu)
{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+ int gpu_metrcs_size = sizeof(MetricsTable_t);
+ void *driver_pptable __free(kfree) = NULL;
+ void *metrics_table __free(kfree) = NULL;
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU15_TOOL_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS,
+ gpu_metrcs_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT);
+
+ metrics_table = kzalloc(gpu_metrcs_size, GFP_KERNEL);
+ if (!metrics_table)
+ return -ENOMEM;
+
+ smu_table->metrics_time = 0;
+
+ driver_pptable = kzalloc(sizeof(PPTable_t), GFP_KERNEL);
+ if (!driver_pptable)
+ return -ENOMEM;
+
+ smu_table->metrics_table = no_free_ptr(metrics_table);
+ smu_table->driver_pptable = no_free_ptr(driver_pptable);
+
+ mutex_init(&smu_table->metrics_lock);
+
return 0;
}
@@ -197,16 +231,35 @@ static int smu_v15_0_8_init_smc_tables(struct smu_context *smu)
return ret;
}
-static int smu_v15_0_8_init_allowed_features(struct smu_context *smu)
+static int smu_v15_0_8_tables_fini(struct smu_context *smu)
{
- /* pptable will handle the features to enable */
- smu_feature_list_set_all(smu, SMU_FEATURE_LIST_ALLOWED);
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ mutex_destroy(&smu_table->metrics_lock);
return 0;
}
-static int smu_v15_0_8_set_default_dpm_table(struct smu_context *smu)
+static int smu_v15_0_8_fini_smc_tables(struct smu_context *smu)
{
+ int ret;
+
+ ret = smu_v15_0_8_tables_fini(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_v15_0_fini_smc_tables(smu);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int smu_v15_0_8_init_allowed_features(struct smu_context *smu)
+{
+ /* pptable will handle the features to enable */
+ smu_feature_list_set_all(smu, SMU_FEATURE_LIST_ALLOWED);
+
return 0;
}
@@ -258,6 +311,153 @@ static int smu_v15_0_8_get_static_metrics_table(struct smu_context *smu)
return 0;
}
+static int smu_v15_0_8_fru_get_product_info(struct smu_context *smu,
+ StaticMetricsTable_t *static_metrics)
+{
+ struct amdgpu_fru_info *fru_info;
+ struct amdgpu_device *adev = smu->adev;
+
+ if (!adev->fru_info) {
+ adev->fru_info = kzalloc(sizeof(*adev->fru_info), GFP_KERNEL);
+ if (!adev->fru_info)
+ return -ENOMEM;
+ }
+
+ fru_info = adev->fru_info;
+ strscpy(fru_info->product_number, static_metrics->ProductInfo.ModelNumber,
+ sizeof(fru_info->product_number));
+ strscpy(fru_info->product_name, static_metrics->ProductInfo.Name,
+ sizeof(fru_info->product_name));
+ strscpy(fru_info->serial, static_metrics->ProductInfo.Serial,
+ sizeof(fru_info->serial));
+ strscpy(fru_info->manufacturer_name, static_metrics->ProductInfo.ManufacturerName,
+ sizeof(fru_info->manufacturer_name));
+ strscpy(fru_info->fru_id, static_metrics->ProductInfo.FruId,
+ sizeof(fru_info->fru_id));
+
+ return 0;
+}
+
+static void smu_v15_0_8_init_xgmi_data(struct smu_context *smu,
+ StaticMetricsTable_t *static_metrics)
+{
+ uint16_t max_speed;
+ uint8_t max_width;
+
+ max_width = (uint8_t)static_metrics->MaxXgmiWidth;
+ max_speed = (uint16_t)static_metrics->MaxXgmiBitrate;
+ amgpu_xgmi_set_max_speed_width(smu->adev, max_speed, max_width);
+}
+
+static int smu_v15_0_8_set_driver_pptable(struct smu_context *smu)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ StaticMetricsTable_t *static_metrics = (StaticMetricsTable_t *)smu_table->metrics_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int ret, i, n;
+ uint32_t table_version;
+
+ if (!pptable->init) {
+ ret = smu_v15_0_8_get_static_metrics_table(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMetricsVersion,
+ &table_version);
+ if (ret)
+ return ret;
+ smu_table->tables[SMU_TABLE_SMU_METRICS].version =
+ table_version;
+
+ pptable->MaxSocketPowerLimit =
+ SMUQ10_ROUND(static_metrics->MaxSocketPowerLimit);
+ pptable->MaxGfxclkFrequency =
+ SMUQ10_ROUND(static_metrics->MaxGfxclkFrequency);
+ pptable->MinGfxclkFrequency =
+ SMUQ10_ROUND(static_metrics->MinGfxclkFrequency);
+ pptable->MaxFclkFrequency =
+ SMUQ10_ROUND(static_metrics->MaxFclkFrequency);
+ pptable->MinFclkFrequency =
+ SMUQ10_ROUND(static_metrics->MinFclkFrequency);
+ pptable->MaxGl2clkFrequency =
+ SMUQ10_ROUND(static_metrics->MaxGl2clkFrequency);
+ pptable->MinGl2clkFrequency =
+ SMUQ10_ROUND(static_metrics->MinGl2clkFrequency);
+
+ for (i = 0; i < ARRAY_SIZE(static_metrics->UclkFrequencyTable); ++i)
+ pptable->UclkFrequencyTable[i] =
+ SMUQ10_ROUND(static_metrics->UclkFrequencyTable[i]);
+
+ pptable->SocclkFrequency = SMUQ10_ROUND(static_metrics->SocclkFrequency);
+ pptable->LclkFrequency = SMUQ10_ROUND(static_metrics->LclkFrequency);
+ pptable->VclkFrequency = SMUQ10_ROUND(static_metrics->VclkFrequency);
+ pptable->DclkFrequency = SMUQ10_ROUND(static_metrics->DclkFrequency);
+
+ pptable->CTFLimitMID = SMUQ10_ROUND(static_metrics->CTFLimit_MID);
+ pptable->CTFLimitAID = SMUQ10_ROUND(static_metrics->CTFLimit_AID);
+ pptable->CTFLimitXCD = SMUQ10_ROUND(static_metrics->CTFLimit_XCD);
+ pptable->CTFLimitHBM = SMUQ10_ROUND(static_metrics->CTFLimit_HBM);
+ pptable->ThermalLimitMID = SMUQ10_ROUND(static_metrics->ThermalLimit_MID);
+ pptable->ThermalLimitAID = SMUQ10_ROUND(static_metrics->ThermalLimit_AID);
+ pptable->ThermalLimitXCD = SMUQ10_ROUND(static_metrics->ThermalLimit_XCD);
+ pptable->ThermalLimitHBM = SMUQ10_ROUND(static_metrics->ThermalLimit_HBM);
+
+ /* use MID0 serial number by default */
+ pptable->PublicSerialNumberMID =
+ static_metrics->PublicSerialNumber_MID[0];
+
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_SOC,
+ 0, pptable->PublicSerialNumberMID);
+ pptable->PublicSerialNumberAID =
+ static_metrics->PublicSerialNumber_AID[0];
+ pptable->PublicSerialNumberXCD =
+ static_metrics->PublicSerialNumber_XCD[0];
+ n = ARRAY_SIZE(static_metrics->PublicSerialNumber_MID);
+ for (i = 0; i < n; i++) {
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_MID, i,
+ static_metrics->PublicSerialNumber_MID[i]);
+ }
+ n = ARRAY_SIZE(static_metrics->PublicSerialNumber_AID);
+ for (i = 0; i < n; i++) {
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_AID, i,
+ static_metrics->PublicSerialNumber_AID[i]);
+ }
+ n = ARRAY_SIZE(static_metrics->PublicSerialNumber_XCD);
+ for (i = 0; i < n; i++) {
+ amdgpu_device_set_uid(smu->adev->uid_info, AMDGPU_UID_TYPE_XCD, i,
+ static_metrics->PublicSerialNumber_XCD[i]);
+ }
+
+ ret = smu_v15_0_8_fru_get_product_info(smu, static_metrics);
+ if (ret)
+ return ret;
+ pptable->PPT1Max = static_metrics->PPT1Max;
+ pptable->PPT1Min = static_metrics->PPT1Min;
+ pptable->PPT1Default = static_metrics->PPT1Default;
+
+ if (static_metrics->pldmVersion[0] != 0xFFFFFFFF)
+ smu->adev->firmware.pldm_version =
+ static_metrics->pldmVersion[0];
+ dpm_context->board_volt = static_metrics->InputTelemetryVoltageInmV;
+ smu_v15_0_8_init_xgmi_data(smu, static_metrics);
+ pptable->init = true;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_default_dpm_table(struct smu_context *smu)
+{
+ int ret;
+
+ ret = smu_v15_0_8_set_driver_pptable(smu);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int smu_v15_0_8_irq_process(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
@@ -498,7 +698,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
.is_dpm_running = smu_v15_0_8_is_dpm_running,
.init_smc_tables = smu_v15_0_8_init_smc_tables,
- .fini_smc_tables = smu_v15_0_fini_smc_tables,
+ .fini_smc_tables = smu_v15_0_8_fini_smc_tables,
.init_power = smu_v15_0_init_power,
.fini_power = smu_v15_0_fini_power,
.check_fw_status = smu_v15_0_8_check_fw_status,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
index 40c410928c966..6c85f23d31116 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
@@ -25,4 +25,34 @@
extern void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu);
+typedef struct {
+ uint32_t MaxSocketPowerLimit;
+ uint32_t MaxGfxclkFrequency;
+ uint32_t MinGfxclkFrequency;
+ uint32_t MaxFclkFrequency;
+ uint32_t MinFclkFrequency;
+ uint32_t MaxGl2clkFrequency;
+ uint32_t MinGl2clkFrequency;
+ uint32_t UclkFrequencyTable[4];
+ uint32_t SocclkFrequency;
+ uint32_t LclkFrequency;
+ uint32_t VclkFrequency;
+ uint32_t DclkFrequency;
+ uint32_t CTFLimitMID;
+ uint32_t CTFLimitAID;
+ uint32_t CTFLimitXCD;
+ uint32_t CTFLimitHBM;
+ uint32_t ThermalLimitMID;
+ uint32_t ThermalLimitAID;
+ uint32_t ThermalLimitXCD;
+ uint32_t ThermalLimitHBM;
+ uint64_t PublicSerialNumberMID;
+ uint64_t PublicSerialNumberAID;
+ uint64_t PublicSerialNumberXCD;
+ uint32_t PPT1Max;
+ uint32_t PPT1Min;
+ uint32_t PPT1Default;
+ bool init;
+} PPTable_t;
+
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 08/25] drm/amd/pm: Update dpm table structs for smu_v15_0
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (5 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 07/25] drm/amd/pm: Setup driver pptable for smu 15.0.8 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 09/25] drm/amd/pm: Add default dpm table support for smu 15.0.8 Alex Deucher
` (16 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Update dpm table structs to use common definitions for smu_15_0
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h | 47 +++--------
.../gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c | 79 +++++++++----------
2 files changed, 49 insertions(+), 77 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
index 06842d38c92bd..3c8c086f0f9d8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
@@ -45,7 +45,6 @@
#define FEATURE_MASK(feature) (1ULL << feature)
-#define MAX_DPM_LEVELS 16
#define MAX_PCIE_CONF 3
#define SMU15_TOOL_SIZE 0x19000
@@ -69,39 +68,19 @@ struct smu_15_0_max_sustainable_clocks {
uint32_t soc_clock;
};
-struct smu_15_0_dpm_clk_level {
- bool enabled;
- uint32_t value;
-};
-
-struct smu_15_0_dpm_table {
- uint32_t min; /* MHz */
- uint32_t max; /* MHz */
- uint32_t count;
- bool is_fine_grained;
- struct smu_15_0_dpm_clk_level dpm_levels[MAX_DPM_LEVELS];
-};
-
-struct smu_15_0_pcie_table {
- uint8_t pcie_gen[MAX_PCIE_CONF];
- uint8_t pcie_lane[MAX_PCIE_CONF];
- uint16_t clk_freq[MAX_PCIE_CONF];
- uint32_t num_of_link_levels;
-};
-
struct smu_15_0_dpm_tables {
- struct smu_15_0_dpm_table soc_table;
- struct smu_15_0_dpm_table gfx_table;
- struct smu_15_0_dpm_table uclk_table;
- struct smu_15_0_dpm_table eclk_table;
- struct smu_15_0_dpm_table vclk_table;
- struct smu_15_0_dpm_table dclk_table;
- struct smu_15_0_dpm_table dcef_table;
- struct smu_15_0_dpm_table pixel_table;
- struct smu_15_0_dpm_table display_table;
- struct smu_15_0_dpm_table phy_table;
- struct smu_15_0_dpm_table fclk_table;
- struct smu_15_0_pcie_table pcie_table;
+ struct smu_dpm_table soc_table;
+ struct smu_dpm_table gfx_table;
+ struct smu_dpm_table uclk_table;
+ struct smu_dpm_table eclk_table;
+ struct smu_dpm_table vclk_table;
+ struct smu_dpm_table dclk_table;
+ struct smu_dpm_table dcef_table;
+ struct smu_dpm_table pixel_table;
+ struct smu_dpm_table display_table;
+ struct smu_dpm_table phy_table;
+ struct smu_dpm_table fclk_table;
+ struct smu_pcie_table pcie_table;
};
struct smu_15_0_dpm_context {
@@ -204,7 +183,7 @@ int smu_v15_0_set_power_source(struct smu_context *smu,
int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
- struct smu_15_0_dpm_table *single_dpm_table);
+ struct smu_dpm_table *single_dpm_table);
int smu_v15_0_gfx_ulv_control(struct smu_context *smu,
bool enablement);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
index 51d1f5d42ad31..a9417cb4e920b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c
@@ -1059,18 +1059,12 @@ int smu_v15_0_set_performance_level(struct smu_context *smu,
{
struct smu_15_0_dpm_context *dpm_context =
smu->smu_dpm.dpm_context;
- struct smu_15_0_dpm_table *gfx_table =
- &dpm_context->dpm_tables.gfx_table;
- struct smu_15_0_dpm_table *mem_table =
- &dpm_context->dpm_tables.uclk_table;
- struct smu_15_0_dpm_table *soc_table =
- &dpm_context->dpm_tables.soc_table;
- struct smu_15_0_dpm_table *vclk_table =
- &dpm_context->dpm_tables.vclk_table;
- struct smu_15_0_dpm_table *dclk_table =
- &dpm_context->dpm_tables.dclk_table;
- struct smu_15_0_dpm_table *fclk_table =
- &dpm_context->dpm_tables.fclk_table;
+ struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
+ struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_dpm_table *soc_table = &dpm_context->dpm_tables.soc_table;
+ struct smu_dpm_table *vclk_table = &dpm_context->dpm_tables.vclk_table;
+ struct smu_dpm_table *dclk_table = &dpm_context->dpm_tables.dclk_table;
+ struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table =
&smu->pstate_table;
struct amdgpu_device *adev = smu->adev;
@@ -1085,34 +1079,34 @@ int smu_v15_0_set_performance_level(struct smu_context *smu,
switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH:
- sclk_min = sclk_max = gfx_table->max;
- mclk_min = mclk_max = mem_table->max;
- socclk_min = socclk_max = soc_table->max;
- vclk_min = vclk_max = vclk_table->max;
- dclk_min = dclk_max = dclk_table->max;
- fclk_min = fclk_max = fclk_table->max;
+ sclk_min = sclk_max = SMU_DPM_TABLE_MAX(gfx_table);
+ mclk_min = mclk_max = SMU_DPM_TABLE_MAX(mem_table);
+ socclk_min = socclk_max = SMU_DPM_TABLE_MAX(soc_table);
+ vclk_min = vclk_max = SMU_DPM_TABLE_MAX(vclk_table);
+ dclk_min = dclk_max = SMU_DPM_TABLE_MAX(dclk_table);
+ fclk_min = fclk_max = SMU_DPM_TABLE_MAX(fclk_table);
break;
case AMD_DPM_FORCED_LEVEL_LOW:
- sclk_min = sclk_max = gfx_table->min;
- mclk_min = mclk_max = mem_table->min;
- socclk_min = socclk_max = soc_table->min;
- vclk_min = vclk_max = vclk_table->min;
- dclk_min = dclk_max = dclk_table->min;
- fclk_min = fclk_max = fclk_table->min;
+ sclk_min = sclk_max = SMU_DPM_TABLE_MIN(gfx_table);
+ mclk_min = mclk_max = SMU_DPM_TABLE_MIN(mem_table);
+ socclk_min = socclk_max = SMU_DPM_TABLE_MIN(soc_table);
+ vclk_min = vclk_max = SMU_DPM_TABLE_MIN(vclk_table);
+ dclk_min = dclk_max = SMU_DPM_TABLE_MIN(dclk_table);
+ fclk_min = fclk_max = SMU_DPM_TABLE_MIN(fclk_table);
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
- sclk_min = gfx_table->min;
- sclk_max = gfx_table->max;
- mclk_min = mem_table->min;
- mclk_max = mem_table->max;
- socclk_min = soc_table->min;
- socclk_max = soc_table->max;
- vclk_min = vclk_table->min;
- vclk_max = vclk_table->max;
- dclk_min = dclk_table->min;
- dclk_max = dclk_table->max;
- fclk_min = fclk_table->min;
- fclk_max = fclk_table->max;
+ sclk_min = SMU_DPM_TABLE_MIN(gfx_table);
+ sclk_max = SMU_DPM_TABLE_MAX(gfx_table);
+ mclk_min = SMU_DPM_TABLE_MIN(mem_table);
+ mclk_max = SMU_DPM_TABLE_MAX(mem_table);
+ socclk_min = SMU_DPM_TABLE_MIN(soc_table);
+ socclk_max = SMU_DPM_TABLE_MAX(soc_table);
+ vclk_min = SMU_DPM_TABLE_MIN(vclk_table);
+ vclk_max = SMU_DPM_TABLE_MAX(vclk_table);
+ dclk_min = SMU_DPM_TABLE_MIN(dclk_table);
+ dclk_max = SMU_DPM_TABLE_MAX(dclk_table);
+ fclk_min = SMU_DPM_TABLE_MIN(fclk_table);
+ fclk_max = SMU_DPM_TABLE_MAX(fclk_table);
auto_level = true;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
@@ -1334,10 +1328,11 @@ static int smu_v15_0_get_fine_grained_status(struct smu_context *smu,
int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
- struct smu_15_0_dpm_table *single_dpm_table)
+ struct smu_dpm_table *single_dpm_table)
{
int ret = 0;
uint32_t clk;
+ bool is_fine_grained;
int i;
ret = smu_v15_0_get_dpm_level_count(smu,
@@ -1350,12 +1345,15 @@ int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
ret = smu_v15_0_get_fine_grained_status(smu,
clk_type,
- &single_dpm_table->is_fine_grained);
+ &is_fine_grained);
if (ret) {
dev_err(smu->adev->dev, "[%s] failed to get fine grained status!\n", __func__);
return ret;
}
+ if (is_fine_grained)
+ single_dpm_table->flags |= SMU_DPM_TABLE_FINE_GRAINED;
+
for (i = 0; i < single_dpm_table->count; i++) {
ret = smu_v15_0_get_dpm_freq_by_index(smu,
clk_type,
@@ -1368,11 +1366,6 @@ int smu_v15_0_set_single_dpm_table(struct smu_context *smu,
single_dpm_table->dpm_levels[i].value = clk;
single_dpm_table->dpm_levels[i].enabled = true;
-
- if (i == 0)
- single_dpm_table->min = clk;
- else if (i == single_dpm_table->count - 1)
- single_dpm_table->max = clk;
}
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 09/25] drm/amd/pm: Add default dpm table support for smu 15.0.8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (6 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 08/25] drm/amd/pm: Update dpm table structs for smu_v15_0 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 10/25] drm/amd/pm: Add get_pm_metrics " Alex Deucher
` (15 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add default dpm table support for smu 15.0.8
v2: Remove lclk, move pptable check up, add missing clk (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h | 1 +
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h | 1 +
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 211 ++++++++++++++++++
3 files changed, 213 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index 5f77749998e32..d4801a5ebc30c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -339,6 +339,7 @@ enum smu_clk_type {
SMU_OD_FAN_MINIMUM_PWM,
SMU_OD_FAN_ZERO_RPM_ENABLE,
SMU_OD_FAN_ZERO_RPM_STOP_TEMP,
+ SMU_GL2CLK,
SMU_CLK_COUNT,
};
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
index 3c8c086f0f9d8..e6fd8be2cc4a0 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v15_0.h
@@ -81,6 +81,7 @@ struct smu_15_0_dpm_tables {
struct smu_dpm_table phy_table;
struct smu_dpm_table fclk_table;
struct smu_pcie_table pcie_table;
+ struct smu_dpm_table gl2_table;
};
struct smu_15_0_dpm_context {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 82b09fe7fccd5..149421b1c6cbf 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -263,6 +263,212 @@ static int smu_v15_0_8_init_allowed_features(struct smu_context *smu)
return 0;
}
+static int smu_v15_0_8_get_dpm_ultimate_freq(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *min, uint32_t *max)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ struct smu_dpm_table *dpm_table;
+ uint32_t min_clk = 0, max_clk = 0;
+
+ if (!pptable->init)
+ return -EINVAL;
+
+ /* Try cached DPM tables first */
+ if (dpm_context) {
+ switch (clk_type) {
+ case SMU_MCLK:
+ case SMU_UCLK:
+ dpm_table = &dpm_context->dpm_tables.uclk_table;
+ break;
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ dpm_table = &dpm_context->dpm_tables.gfx_table;
+ break;
+ case SMU_SOCCLK:
+ dpm_table = &dpm_context->dpm_tables.soc_table;
+ break;
+ case SMU_FCLK:
+ dpm_table = &dpm_context->dpm_tables.fclk_table;
+ break;
+ case SMU_GL2CLK:
+ dpm_table = &dpm_context->dpm_tables.gl2_table;
+ break;
+ case SMU_VCLK:
+ dpm_table = &dpm_context->dpm_tables.vclk_table;
+ break;
+ case SMU_DCLK:
+ dpm_table = &dpm_context->dpm_tables.dclk_table;
+ break;
+ default:
+ dpm_table = NULL;
+ break;
+ }
+
+ if (dpm_table && dpm_table->count > 0) {
+ min_clk = SMU_DPM_TABLE_MIN(dpm_table);
+ max_clk = SMU_DPM_TABLE_MAX(dpm_table);
+
+ if (min_clk && max_clk) {
+ if (min)
+ *min = min_clk;
+ if (max)
+ *max = max_clk;
+ return 0;
+ }
+ }
+ }
+
+ /* Fall back to pptable */
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ min_clk = pptable->MinGfxclkFrequency;
+ max_clk = pptable->MaxGfxclkFrequency;
+ break;
+ case SMU_FCLK:
+ min_clk = pptable->MinFclkFrequency;
+ max_clk = pptable->MaxFclkFrequency;
+ break;
+ case SMU_GL2CLK:
+ min_clk = pptable->MinGl2clkFrequency;
+ max_clk = pptable->MaxGl2clkFrequency;
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ min_clk = pptable->UclkFrequencyTable[0];
+ max_clk = pptable->UclkFrequencyTable[ARRAY_SIZE(pptable->UclkFrequencyTable) - 1];
+ break;
+ case SMU_SOCCLK:
+ min_clk = pptable->SocclkFrequency;
+ max_clk = pptable->SocclkFrequency;
+ break;
+ case SMU_VCLK:
+ min_clk = pptable->VclkFrequency;
+ max_clk = pptable->VclkFrequency;
+ break;
+ case SMU_DCLK:
+ min_clk = pptable->DclkFrequency;
+ max_clk = pptable->DclkFrequency;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (min)
+ *min = min_clk;
+ if (max)
+ *max = max_clk;
+
+ return 0;
+}
+
+static int smu_v15_0_8_set_dpm_table(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_dpm_table *dpm_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int i, ret;
+ uint32_t gfxclkmin, gfxclkmax;
+
+ /* gfxclk dpm table setup - fine-grained */
+ dpm_table = &dpm_context->dpm_tables.gfx_table;
+ dpm_table->clk_type = SMU_GFXCLK;
+ dpm_table->flags = SMU_DPM_TABLE_FINE_GRAINED;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
+ ret = smu_v15_0_8_get_dpm_ultimate_freq(smu, SMU_GFXCLK,
+ &gfxclkmin, &gfxclkmax);
+ if (ret)
+ return ret;
+
+ dpm_table->count = 2;
+ dpm_table->dpm_levels[0].value = gfxclkmin;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->dpm_levels[1].value = gfxclkmax;
+ dpm_table->dpm_levels[1].enabled = true;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->MinGfxclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* fclk dpm table setup - fine-grained */
+ dpm_table = &dpm_context->dpm_tables.fclk_table;
+ dpm_table->clk_type = SMU_FCLK;
+ dpm_table->flags = SMU_DPM_TABLE_FINE_GRAINED;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
+ dpm_table->count = 2;
+ dpm_table->dpm_levels[0].value = pptable->MinFclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->dpm_levels[1].value = pptable->MaxFclkFrequency;
+ dpm_table->dpm_levels[1].enabled = true;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->MinFclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* gl2clk dpm table setup - fine-grained */
+ dpm_table = &dpm_context->dpm_tables.gl2_table;
+ dpm_table->flags = SMU_DPM_TABLE_FINE_GRAINED;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GL2CLK_BIT)) {
+ dpm_table->count = 2;
+ dpm_table->dpm_levels[0].value = pptable->MinGl2clkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->dpm_levels[1].value = pptable->MaxGl2clkFrequency;
+ dpm_table->dpm_levels[1].enabled = true;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->MinGl2clkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* uclk dpm table setup - discrete levels */
+ dpm_table = &dpm_context->dpm_tables.uclk_table;
+ dpm_table->clk_type = SMU_UCLK;
+ dpm_table->flags = 0;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
+ dpm_table->count = ARRAY_SIZE(pptable->UclkFrequencyTable);
+ for (i = 0; i < dpm_table->count; ++i) {
+ dpm_table->dpm_levels[i].value = pptable->UclkFrequencyTable[i];
+ dpm_table->dpm_levels[i].enabled = true;
+ }
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->UclkFrequencyTable[0];
+ dpm_table->dpm_levels[0].enabled = true;
+ }
+
+ /* socclk dpm table setup - single boot-time value */
+ dpm_table = &dpm_context->dpm_tables.soc_table;
+ dpm_table->clk_type = SMU_SOCCLK;
+ dpm_table->flags = 0;
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->SocclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+
+ /* vclk dpm table setup - single boot-time value */
+ dpm_table = &dpm_context->dpm_tables.vclk_table;
+ dpm_table->clk_type = SMU_VCLK;
+ dpm_table->flags = 0;
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->VclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+
+ /* dclk dpm table setup - single boot-time value */
+ dpm_table = &dpm_context->dpm_tables.dclk_table;
+ dpm_table->clk_type = SMU_DCLK;
+ dpm_table->flags = 0;
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = pptable->DclkFrequency;
+ dpm_table->dpm_levels[0].enabled = true;
+
+ return 0;
+}
+
static int smu_v15_0_8_setup_pptable(struct smu_context *smu)
{
struct smu_table_context *table_context = &smu->smu_table;
@@ -455,6 +661,10 @@ static int smu_v15_0_8_set_default_dpm_table(struct smu_context *smu)
if (ret)
return ret;
+ ret = smu_v15_0_8_set_dpm_table(smu);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -714,6 +924,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.wait_for_event = smu_v15_0_wait_for_event,
.mode2_reset = smu_v15_0_8_mode2_reset,
+ .get_dpm_ultimate_freq = smu_v15_0_8_get_dpm_ultimate_freq,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 10/25] drm/amd/pm: Add get_pm_metrics support for smu 15.0.8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (7 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 09/25] drm/amd/pm: Add default dpm table support for smu 15.0.8 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 11/25] drm/amd/pm: add get_gpu_metrics support for 15.0.8 Alex Deucher
` (14 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Yang Wang, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
export .get_pm_metrics interface for smu 15.0.8.
v2: Make tmo as unsigned (Lijo)
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 65 +++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 149421b1c6cbf..60a43ce5648a5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -263,6 +263,37 @@ static int smu_v15_0_8_init_allowed_features(struct smu_context *smu)
return 0;
}
+static int smu_v15_0_8_get_metrics_table_internal(struct smu_context *smu, uint32_t tmo, void *data)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ uint32_t table_size = smu_table->tables[SMU_TABLE_SMU_METRICS].size;
+ struct smu_table *table = &smu_table->driver_table;
+ struct amdgpu_device *adev = smu->adev;
+ int ret;
+
+ mutex_lock(&smu_table->metrics_lock);
+
+ if (!tmo || !smu_table->metrics_time ||
+ time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(tmo))) {
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMetricsTable, NULL);
+ if (ret) {
+ dev_info(adev->dev,
+ "Failed to export SMU metrics table!\n");
+ return ret;
+ }
+
+ amdgpu_device_invalidate_hdp(smu->adev, NULL);
+ memcpy(smu_table->metrics_table, table->cpu_addr, table_size);
+
+ smu_table->metrics_time = jiffies;
+ }
+
+ if (data)
+ memcpy(data, smu_table->metrics_table, table_size);
+ mutex_unlock(&smu_table->metrics_lock);
+ return ret;
+}
+
static int smu_v15_0_8_get_dpm_ultimate_freq(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t *min, uint32_t *max)
@@ -860,6 +891,39 @@ static bool smu_v15_0_8_is_dpm_running(struct smu_context *smu)
smu_v15_0_8_dpm_features.bits);
}
+static ssize_t smu_v15_0_8_get_pm_metrics(struct smu_context *smu,
+ void *metrics, size_t max_size)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct amdgpu_pm_metrics *pm_metrics = (struct amdgpu_pm_metrics *)metrics;
+ uint32_t table_version = smu_table->tables[SMU_TABLE_SMU_METRICS].version;
+ uint32_t table_size = smu_table->tables[SMU_TABLE_SMU_METRICS].size;
+ uint32_t pmfw_version;
+ int ret;
+
+ if (!pm_metrics || !max_size)
+ return -EINVAL;
+
+ if (max_size < (table_size + sizeof(pm_metrics->common_header)))
+ return -EOVERFLOW;
+
+ /* Don't use cached metrics data */
+ ret = smu_v15_0_8_get_metrics_table_internal(smu, 0, pm_metrics->data);
+ if (ret)
+ return ret;
+
+ smu_cmn_get_smc_version(smu, NULL, &pmfw_version);
+ memset(&pm_metrics->common_header, 0, sizeof(pm_metrics->common_header));
+ pm_metrics->common_header.mp1_ip_discovery_version =
+ amdgpu_ip_version(smu->adev, MP1_HWIP, 0);
+ pm_metrics->common_header.pmfw_version = pmfw_version;
+ pm_metrics->common_header.pmmetrics_version = table_version;
+ pm_metrics->common_header.structure_size =
+ sizeof(pm_metrics->common_header) + table_size;
+
+ return pm_metrics->common_header.structure_size;
+}
+
static int smu_v15_0_8_mode2_reset(struct smu_context *smu)
{
struct smu_msg_ctl *ctl = &smu->msg_ctl;
@@ -923,6 +987,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.setup_pptable = smu_v15_0_8_setup_pptable,
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.wait_for_event = smu_v15_0_wait_for_event,
+ .get_pm_metrics = smu_v15_0_8_get_pm_metrics,
.mode2_reset = smu_v15_0_8_mode2_reset,
.get_dpm_ultimate_freq = smu_v15_0_8_get_dpm_ultimate_freq,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 11/25] drm/amd/pm: add get_gpu_metrics support for 15.0.8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (8 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 10/25] drm/amd/pm: Add get_pm_metrics " Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 12/25] drm/amd/pm: add get_unique_id support for smu 15.0.8 Alex Deucher
` (13 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Yang Wang, Asad Kamal, Lijo Lazar, Alex Deucher
From: Yang Wang <kevinyang.wang@amd.com>
export .get_gpu_metrics interface for 15.0.8
v2: Remove members already exposed by other interfaces, use mask,
logical conversion (Lijo)
v3: Use correct logic for hbm stacks loop (Lijo)
Remove buffer allocation
v4: Make out of bound check outside loop (Lijo)
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../gpu/drm/amd/include/kgd_pp_interface.h | 1 +
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 174 +++++++++++++++++-
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h | 126 +++++++++++++
3 files changed, 300 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index a9b73f4fd4661..22ee30f514c0a 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -585,6 +585,7 @@ enum amdgpu_metrics_attr_id {
AMDGPU_METRICS_ATTR_ID_GFX_LOW_UTILIZATION_ACC,
AMDGPU_METRICS_ATTR_ID_GFX_BELOW_HOST_LIMIT_TOTAL_ACC,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_HBM,
+ AMDGPU_METRICS_ATTR_ID_TEMPERATURE_MID,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_AID,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_XCD,
AMDGPU_METRICS_ATTR_ID_MAX,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 60a43ce5648a5..c13804c32e706 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -56,6 +56,13 @@
#define SMUQ10_FRAC(x) ((x) & 0x3ff)
#define SMUQ10_ROUND(x) ((SMUQ10_TO_UINT(x)) + ((SMUQ10_FRAC(x)) >= 0x200))
+#define hbm_stack_mask_valid(umc_mask) \
+ (((umc_mask) & 0xF) == 0xF)
+
+#define for_each_hbm_stack(stack_idx, umc_mask) \
+ for ((stack_idx) = 0; (umc_mask); \
+ (umc_mask) >>= 4, (stack_idx)++) \
+
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
#define SMU_15_0_8_FEA_MAP(smu_feature, smu_15_0_8_feature) \
@@ -167,8 +174,9 @@ static const struct cmn2asic_mapping smu_v15_0_8_table_map[SMU_TABLE_COUNT] = {
static int smu_v15_0_8_tables_init(struct smu_context *smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
+ int ret, gpu_metrcs_size = sizeof(MetricsTable_t);
struct smu_table *tables = smu_table->tables;
- int gpu_metrcs_size = sizeof(MetricsTable_t);
+ struct smu_v15_0_8_gpu_metrics *gpu_metrics;
void *driver_pptable __free(kfree) = NULL;
void *metrics_table __free(kfree) = NULL;
@@ -190,6 +198,15 @@ static int smu_v15_0_8_tables_init(struct smu_context *smu)
if (!driver_pptable)
return -ENOMEM;
+ ret = smu_driver_table_init(smu, SMU_DRIVER_TABLE_GPU_METRICS,
+ sizeof(struct smu_v15_0_8_gpu_metrics),
+ SMU_GPU_METRICS_CACHE_INTERVAL);
+ if (ret)
+ return ret;
+
+ gpu_metrics = (struct smu_v15_0_8_gpu_metrics *)smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_GPU_METRICS);
+ smu_v15_0_8_gpu_metrics_init(gpu_metrics, 1, 9);
smu_table->metrics_table = no_free_ptr(metrics_table);
smu_table->driver_pptable = no_free_ptr(driver_pptable);
@@ -967,6 +984,160 @@ static int smu_v15_0_8_mode2_reset(struct smu_context *smu)
return ret;
}
+static ssize_t smu_v15_0_8_get_gpu_metrics(struct smu_context *smu, void **table)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_v15_0_8_gpu_metrics *gpu_metrics;
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0, xcc_id, inst, i, j, idx;
+ uint32_t aid_mask = adev->aid_mask;
+ uint32_t mid_mask = adev->aid_mask;
+ MetricsTable_t *metrics;
+
+ metrics = kzalloc(sizeof(MetricsTable_t), GFP_KERNEL);
+
+ ret = smu_v15_0_8_get_metrics_table_internal(smu, 1, NULL);
+ if (ret)
+ return ret;
+
+ metrics = (MetricsTable_t *)smu_table->metrics_table;
+ gpu_metrics = (struct smu_v15_0_8_gpu_metrics *)smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_GPU_METRICS);
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+
+ gpu_metrics->temperature_hotspot = SMUQ10_ROUND(metrics->MaxSocketTemperature);
+
+ /* Per-HBM stack temperatures */
+ if (adev->umc.active_mask) {
+ u64 mask = adev->umc.active_mask;
+ int out_idx = 0;
+ int stack_idx;
+
+ if (unlikely(hweight64(mask)/4 > SMU_15_0_8_MAX_HBM_STACKS))
+ dev_warn(adev->dev, "Invalid umc mask %lld\n", mask);
+ else {
+ for_each_hbm_stack(stack_idx, mask) {
+ if (!hbm_stack_mask_valid(mask))
+ continue;
+ gpu_metrics->temperature_hbm[out_idx++] =
+ SMUQ10_ROUND(metrics->HbmTemperature[stack_idx]);
+ }
+ }
+ }
+
+ /* Reports max temperature of all voltage rails */
+ gpu_metrics->temperature_vrsoc = SMUQ10_ROUND(metrics->MaxVrTemperature);
+ /* MID, AID, XCD temperatures */
+ idx = 0;
+ for_each_inst(i, mid_mask) {
+ gpu_metrics->temperature_mid[idx] = SMUQ10_ROUND(metrics->MidTemperature[i]);
+ idx++;
+ }
+
+ idx = 0;
+ for_each_inst(i, aid_mask) {
+ gpu_metrics->temperature_aid[idx] = SMUQ10_ROUND(metrics->AidTemperature[i]);
+ idx++;
+ }
+
+ for (i = 0; i < NUM_XCC(adev->gfx.xcc_mask); ++i) {
+ xcc_id = GET_INST(GC, i);
+ if (xcc_id >= 0)
+ gpu_metrics->temperature_xcd[i] = SMUQ10_ROUND(metrics->XcdTemperature[xcc_id]);
+ }
+ /* Power */
+ gpu_metrics->curr_socket_power = SMUQ10_ROUND(metrics->SocketPower);
+
+ gpu_metrics->average_gfx_activity = SMUQ10_ROUND(metrics->SocketGfxBusy);
+ gpu_metrics->average_umc_activity = SMUQ10_ROUND(metrics->DramBandwidthUtilization);
+ gpu_metrics->mem_max_bandwidth = SMUQ10_ROUND(metrics->MaxDramBandwidth);
+
+ /* Energy counter reported in 15.259uJ (2^-16) units */
+ gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc;
+
+ for (i = 0; i < NUM_XCC(adev->gfx.xcc_mask); ++i) {
+ xcc_id = GET_INST(GC, i);
+ if (xcc_id >= 0) {
+ gpu_metrics->current_gfxclk[i] =
+ SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]);
+ }
+ }
+
+ /* Per-MID clocks */
+ idx = 0;
+ for_each_inst(i, mid_mask) {
+ gpu_metrics->current_socclk[idx] = SMUQ10_ROUND(metrics->SocclkFrequency[i]);
+ idx++;
+ }
+
+ /* Per-VCN clocks */
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ inst = GET_INST(VCN, i);
+ if (inst >= 0) {
+ gpu_metrics->current_vclk0[i] = SMUQ10_ROUND(metrics->VclkFrequency[inst]);
+ gpu_metrics->current_dclk0[i] = SMUQ10_ROUND(metrics->DclkFrequency[inst]);
+ }
+ }
+
+ /* Per-AID clocks */
+ idx = 0;
+ for_each_inst(i, aid_mask) {
+ gpu_metrics->current_uclk[idx] = SMUQ10_ROUND(metrics->UclkFrequency[i]);
+ idx++;
+ }
+
+ /* Total accumulated cycle counter */
+ gpu_metrics->accumulation_counter = metrics->AccumulationCounter;
+
+ /* Accumulated throttler residencies */
+ gpu_metrics->prochot_residency_acc = metrics->ProchotResidencyAcc;
+ gpu_metrics->ppt_residency_acc = metrics->PptResidencyAcc;
+ gpu_metrics->socket_thm_residency_acc = metrics->SocketThmResidencyAcc;
+ gpu_metrics->vr_thm_residency_acc = metrics->VrThmResidencyAcc;
+ gpu_metrics->hbm_thm_residency_acc = metrics->HbmThmResidencyAcc;
+
+ gpu_metrics->gfx_activity_acc = SMUQ10_ROUND(metrics->SocketGfxBusyAcc);
+ gpu_metrics->mem_activity_acc = SMUQ10_ROUND(metrics->DramBandwidthUtilizationAcc);
+
+ for (i = 0; i < NUM_XGMI_LINKS; i++) {
+ j = amdgpu_xgmi_get_ext_link(adev, i);
+ if (j < 0 || j >= NUM_XGMI_LINKS)
+ continue;
+ ret = amdgpu_get_xgmi_link_status(adev, i);
+ if (ret >= 0)
+ gpu_metrics->xgmi_link_status[j] = ret;
+ }
+
+ gpu_metrics->xgmi_read_data_acc = SMUQ10_ROUND(metrics->XgmiReadBandwidthAcc);
+ gpu_metrics->xgmi_write_data_acc = SMUQ10_ROUND(metrics->XgmiWriteBandwidthAcc);
+
+ for (i = 0; i < NUM_XCC(adev->gfx.xcc_mask); ++i) {
+ inst = GET_INST(GC, i);
+ gpu_metrics->gfx_busy_inst[i] = SMUQ10_ROUND(metrics->GfxBusy[inst]);
+ gpu_metrics->gfx_busy_acc[i] = SMUQ10_ROUND(metrics->GfxBusyAcc[inst]);
+ gpu_metrics->gfx_below_host_limit_ppt_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkBelowHostLimitPptAcc[inst]);
+ gpu_metrics->gfx_below_host_limit_thm_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkBelowHostLimitThmAcc[inst]);
+ gpu_metrics->gfx_low_utilization_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkLowUtilizationAcc[inst]);
+ gpu_metrics->gfx_below_host_limit_total_acc[i] =
+ SMUQ10_ROUND(metrics->GfxclkBelowHostLimitTotalAcc[inst]);
+ }
+
+ gpu_metrics->xgmi_link_width = metrics->XgmiWidth;
+ gpu_metrics->xgmi_link_speed = metrics->XgmiBitrate;
+
+ gpu_metrics->firmware_timestamp = metrics->Timestamp;
+
+ *table = gpu_metrics;
+
+ smu_driver_table_update_cache_time(smu, SMU_DRIVER_TABLE_GPU_METRICS);
+
+ return sizeof(*gpu_metrics);
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -990,6 +1161,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.get_pm_metrics = smu_v15_0_8_get_pm_metrics,
.mode2_reset = smu_v15_0_8_mode2_reset,
.get_dpm_ultimate_freq = smu_v15_0_8_get_dpm_ultimate_freq,
+ .get_gpu_metrics = smu_v15_0_8_get_gpu_metrics,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
index 6c85f23d31116..8fc16796788b5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
@@ -23,6 +23,15 @@
#ifndef __SMU_15_0_8_PPT_H__
#define __SMU_15_0_8_PPT_H__
+#define SMU_15_0_8_NUM_XGMI_LINKS 8
+#define SMU_15_0_8_MAX_GFX_CLKS 8
+#define SMU_15_0_8_MAX_CLKS 4
+#define SMU_15_0_8_MAX_XCC 8
+#define SMU_15_0_8_MAX_VCN 4
+#define SMU_15_0_8_MAX_JPEG 40
+#define SMU_15_0_8_MAX_AID 2
+#define SMU_15_0_8_MAX_MID 2
+#define SMU_15_0_8_MAX_HBM_STACKS 12
extern void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu);
typedef struct {
@@ -55,4 +64,121 @@ typedef struct {
bool init;
} PPTable_t;
+#if defined(SWSMU_CODE_LAYER_L2)
+#include "smu_cmn.h"
+
+/* SMUv 15.0.8 GPU metrics*/
+#define SMU_15_0_8_METRICS_FIELDS(SMU_SCALAR, SMU_ARRAY) \
+ SMU_SCALAR(SMU_MATTR(TEMPERATURE_HOTSPOT), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_hotspot); \
+ SMU_SCALAR(SMU_MATTR(TEMPERATURE_MEM), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_mem); \
+ SMU_SCALAR(SMU_MATTR(TEMPERATURE_VRSOC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_vrsoc); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_HBM), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_hbm, \
+ SMU_15_0_8_MAX_HBM_STACKS); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_MID), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_mid, SMU_15_0_8_MAX_MID); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_AID), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_aid, SMU_15_0_8_MAX_AID); \
+ SMU_ARRAY(SMU_MATTR(TEMPERATURE_XCD), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(U16), temperature_xcd, SMU_15_0_8_MAX_XCC); \
+ SMU_SCALAR(SMU_MATTR(CURR_SOCKET_POWER), SMU_MUNIT(POWER_1), \
+ SMU_MTYPE(U16), curr_socket_power); \
+ SMU_SCALAR(SMU_MATTR(AVERAGE_GFX_ACTIVITY), SMU_MUNIT(PERCENT), \
+ SMU_MTYPE(U16), average_gfx_activity); \
+ SMU_SCALAR(SMU_MATTR(AVERAGE_UMC_ACTIVITY), SMU_MUNIT(PERCENT), \
+ SMU_MTYPE(U16), average_umc_activity); \
+ SMU_SCALAR(SMU_MATTR(MEM_MAX_BANDWIDTH), SMU_MUNIT(BW_1), \
+ SMU_MTYPE(U64), mem_max_bandwidth); \
+ SMU_SCALAR(SMU_MATTR(ENERGY_ACCUMULATOR), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), energy_accumulator); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_CLOCK_COUNTER), SMU_MUNIT(TIME_1), \
+ SMU_MTYPE(U64), system_clock_counter); \
+ SMU_SCALAR(SMU_MATTR(ACCUMULATION_COUNTER), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), accumulation_counter); \
+ SMU_SCALAR(SMU_MATTR(PROCHOT_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), prochot_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(PPT_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), ppt_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(SOCKET_THM_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), socket_thm_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(VR_THM_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), vr_thm_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(HBM_THM_RESIDENCY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), hbm_thm_residency_acc); \
+ SMU_SCALAR(SMU_MATTR(GFXCLK_LOCK_STATUS), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U32), gfxclk_lock_status); \
+ SMU_SCALAR(SMU_MATTR(PCIE_LINK_WIDTH), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), pcie_link_width); \
+ SMU_SCALAR(SMU_MATTR(PCIE_LINK_SPEED), SMU_MUNIT(SPEED_2), \
+ SMU_MTYPE(U16), pcie_link_speed); \
+ SMU_SCALAR(SMU_MATTR(XGMI_LINK_WIDTH), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), xgmi_link_width); \
+ SMU_SCALAR(SMU_MATTR(XGMI_LINK_SPEED), SMU_MUNIT(SPEED_1), \
+ SMU_MTYPE(U16), xgmi_link_speed); \
+ SMU_SCALAR(SMU_MATTR(GFX_ACTIVITY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_activity_acc); \
+ SMU_SCALAR(SMU_MATTR(MEM_ACTIVITY_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), mem_activity_acc); \
+ SMU_ARRAY(SMU_MATTR(PCIE_BANDWIDTH_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_bandwidth_acc, SMU_15_0_8_MAX_MID); \
+ SMU_ARRAY(SMU_MATTR(PCIE_BANDWIDTH_INST), SMU_MUNIT(BW_1), \
+ SMU_MTYPE(U32), pcie_bandwidth_inst, SMU_15_0_8_MAX_MID); \
+ SMU_SCALAR(SMU_MATTR(PCIE_L0_TO_RECOV_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_l0_to_recov_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_REPLAY_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_replay_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_REPLAY_ROVER_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_replay_rover_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_NAK_SENT_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_nak_sent_count_acc); \
+ SMU_SCALAR(SMU_MATTR(PCIE_NAK_RCVD_COUNT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), pcie_nak_rcvd_count_acc); \
+ SMU_ARRAY(SMU_MATTR(XGMI_LINK_STATUS), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), xgmi_link_status, \
+ SMU_15_0_8_NUM_XGMI_LINKS); \
+ SMU_SCALAR(SMU_MATTR(XGMI_READ_DATA_ACC), SMU_MUNIT(DATA_1), \
+ SMU_MTYPE(U64), xgmi_read_data_acc); \
+ SMU_SCALAR(SMU_MATTR(XGMI_WRITE_DATA_ACC), SMU_MUNIT(DATA_1), \
+ SMU_MTYPE(U64), xgmi_write_data_acc); \
+ SMU_SCALAR(SMU_MATTR(FIRMWARE_TIMESTAMP), SMU_MUNIT(TIME_2), \
+ SMU_MTYPE(U64), firmware_timestamp); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_GFXCLK), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_gfxclk, SMU_15_0_8_MAX_GFX_CLKS); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_SOCCLK), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_socclk, SMU_15_0_8_MAX_MID); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_VCLK0), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_vclk0, SMU_15_0_8_MAX_VCN); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_DCLK0), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_dclk0, SMU_15_0_8_MAX_VCN); \
+ SMU_ARRAY(SMU_MATTR(CURRENT_UCLK), SMU_MUNIT(CLOCK_1), \
+ SMU_MTYPE(U16), current_uclk, SMU_15_0_8_MAX_AID); \
+ SMU_SCALAR(SMU_MATTR(PCIE_LC_PERF_OTHER_END_RECOVERY), \
+ SMU_MUNIT(NONE), SMU_MTYPE(U64), \
+ pcie_lc_perf_other_end_recovery); \
+ SMU_ARRAY(SMU_MATTR(GFX_BUSY_INST), SMU_MUNIT(PERCENT), \
+ SMU_MTYPE(U32), gfx_busy_inst, SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(JPEG_BUSY), SMU_MUNIT(PERCENT), SMU_MTYPE(U16), \
+ jpeg_busy, SMU_15_0_8_MAX_JPEG); \
+ SMU_ARRAY(SMU_MATTR(VCN_BUSY), SMU_MUNIT(PERCENT), SMU_MTYPE(U16), \
+ vcn_busy, SMU_15_0_8_MAX_VCN); \
+ SMU_ARRAY(SMU_MATTR(GFX_BUSY_ACC), SMU_MUNIT(NONE), SMU_MTYPE(U64), \
+ gfx_busy_acc, SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_BELOW_HOST_LIMIT_PPT_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_below_host_limit_ppt_acc, \
+ SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_BELOW_HOST_LIMIT_THM_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_below_host_limit_thm_acc, \
+ SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_LOW_UTILIZATION_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_low_utilization_acc, \
+ SMU_15_0_8_MAX_XCC); \
+ SMU_ARRAY(SMU_MATTR(GFX_BELOW_HOST_LIMIT_TOTAL_ACC), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), gfx_below_host_limit_total_acc, \
+ SMU_15_0_8_MAX_XCC);
+
+DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpu_metrics, SMU_15_0_8_METRICS_FIELDS);
+#endif
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 12/25] drm/amd/pm: add get_unique_id support for smu 15.0.8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (9 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 11/25] drm/amd/pm: add get_gpu_metrics support for 15.0.8 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 13/25] drm/amd/pm: add set{get}_power_limit " Alex Deucher
` (12 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Yang Wang, Lijo Lazar, Alex Deucher
From: Yang Wang <kevinyang.wang@amd.com>
export .get_unique_id interface for smu 15.0.8
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index c13804c32e706..5fd22b145aea7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1138,6 +1138,15 @@ static ssize_t smu_v15_0_8_get_gpu_metrics(struct smu_context *smu, void **table
return sizeof(*gpu_metrics);
}
+static void smu_v15_0_8_get_unique_id(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+
+ adev->unique_id = pptable->PublicSerialNumberMID;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1162,6 +1171,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.mode2_reset = smu_v15_0_8_mode2_reset,
.get_dpm_ultimate_freq = smu_v15_0_8_get_dpm_ultimate_freq,
.get_gpu_metrics = smu_v15_0_8_get_gpu_metrics,
+ .get_unique_id = smu_v15_0_8_get_unique_id,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 13/25] drm/amd/pm: add set{get}_power_limit support for smu 15.0.8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (10 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 12/25] drm/amd/pm: add get_unique_id support for smu 15.0.8 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 14/25] drm/amd/pm: Add emit clock support Alex Deucher
` (11 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Yang Wang, Lijo Lazar, Alex Deucher
From: Yang Wang <kevinyang.wang@amd.com>
export .set_power_limit & .get_power_limit interface for smu 15.0.8
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 +
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 34 +++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 5a92ab9601a15..6b31b5d173e71 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -2966,6 +2966,7 @@ int smu_get_power_limit(void *handle,
case IP_VERSION(11, 0, 11):
case IP_VERSION(11, 0, 12):
case IP_VERSION(11, 0, 13):
+ case IP_VERSION(15, 0, 8):
ret = smu_get_asic_power_limits(smu,
&smu->current_power_limit,
NULL, NULL, NULL);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 5fd22b145aea7..d7d40985b0b71 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1147,6 +1147,38 @@ static void smu_v15_0_8_get_unique_id(struct smu_context *smu)
adev->unique_id = pptable->PublicSerialNumberMID;
}
+static int smu_v15_0_8_get_power_limit(struct smu_context *smu,
+ uint32_t *current_power_limit,
+ uint32_t *default_power_limit,
+ uint32_t *max_power_limit,
+ uint32_t *min_power_limit)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ uint32_t power_limit = 0;
+ int ret;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetPptLimit, &power_limit);
+ if (ret) {
+ dev_err(smu->adev->dev, "Couldn't get PPT limit");
+ return -EINVAL;
+ }
+
+ if (current_power_limit)
+ *current_power_limit = power_limit;
+
+ if (default_power_limit)
+ *max_power_limit = pptable->MaxSocketPowerLimit;
+
+ if (max_power_limit)
+ *max_power_limit = pptable->MaxSocketPowerLimit;
+
+ if (min_power_limit)
+ *min_power_limit = 0;
+
+ return 0;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1172,6 +1204,8 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.get_dpm_ultimate_freq = smu_v15_0_8_get_dpm_ultimate_freq,
.get_gpu_metrics = smu_v15_0_8_get_gpu_metrics,
.get_unique_id = smu_v15_0_8_get_unique_id,
+ .get_power_limit = smu_v15_0_8_get_power_limit,
+ .set_power_limit = smu_v15_0_set_power_limit,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 14/25] drm/amd/pm: Add emit clock support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (11 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 13/25] drm/amd/pm: add set{get}_power_limit " Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 15/25] drm/amd/pm: add populate_umd_state_clk support Alex Deucher
` (10 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add emit clock support and fetching other metrics data like temperature,
clock for smu_v15_0_8
v2: Use umc count for hbm stack temperature (Lijo)
v3: Use correct logic for hbm stacks (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 198 ++++++++++++++++++
1 file changed, 198 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index d7d40985b0b71..9b48c258b1f20 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -311,6 +311,203 @@ static int smu_v15_0_8_get_metrics_table_internal(struct smu_context *smu, uint3
return ret;
}
+static int smu_v15_0_8_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member, uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ MetricsTable_t *metrics = (MetricsTable_t *)smu_table->metrics_table;
+ struct amdgpu_device *adev = smu->adev;
+ int ret, xcc_id;
+
+ ret = smu_v15_0_8_get_metrics_table_internal(smu, 10, NULL);
+ if (ret)
+ return ret;
+
+ switch (member) {
+ case METRICS_CURR_GFXCLK:
+ case METRICS_AVERAGE_GFXCLK:
+ xcc_id = GET_INST(GC, 0);
+ *value = SMUQ10_ROUND(metrics->GfxclkFrequency[xcc_id]);
+ break;
+ case METRICS_CURR_SOCCLK:
+ case METRICS_AVERAGE_SOCCLK:
+ *value = SMUQ10_ROUND(metrics->SocclkFrequency[0]);
+ break;
+ case METRICS_CURR_UCLK:
+ case METRICS_AVERAGE_UCLK:
+ *value = SMUQ10_ROUND(metrics->UclkFrequency[0]);
+ break;
+ case METRICS_CURR_VCLK:
+ *value = SMUQ10_ROUND(metrics->VclkFrequency[0]);
+ break;
+ case METRICS_CURR_DCLK:
+ *value = SMUQ10_ROUND(metrics->DclkFrequency[0]);
+ break;
+ case METRICS_CURR_FCLK:
+ *value = SMUQ10_ROUND(metrics->FclkFrequency[0]);
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = SMUQ10_ROUND(metrics->SocketGfxBusy);
+ break;
+ case METRICS_AVERAGE_MEMACTIVITY:
+ *value = SMUQ10_ROUND(metrics->DramBandwidthUtilization);
+ break;
+ case METRICS_CURR_SOCKETPOWER:
+ *value = SMUQ10_ROUND(metrics->SocketPower) << 8;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = SMUQ10_ROUND(metrics->MaxSocketTemperature) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_MEM:
+ {
+ struct amdgpu_device *adev = smu->adev;
+ u32 max_hbm_temp = 0;
+
+ /* Find max temperature across all HBM stacks */
+ if (adev->umc.active_mask) {
+ u64 mask = adev->umc.active_mask;
+ int stack_idx;
+
+ for_each_hbm_stack(stack_idx, mask) {
+ u32 temp;
+
+ if (!hbm_stack_mask_valid(mask))
+ continue;
+
+ temp = SMUQ10_ROUND(metrics->HbmTemperature[stack_idx]);
+ if (temp > max_hbm_temp)
+ max_hbm_temp = temp;
+ }
+ }
+ *value = max_hbm_temp * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ }
+ /* This is the max of all VRs and not just SOC VR.
+ */
+ case METRICS_TEMPERATURE_VRSOC:
+ *value = SMUQ10_ROUND(metrics->MaxVrTemperature) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ return 0;
+}
+
+static int smu_v15_0_8_get_current_clk_freq_by_table(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *value)
+{
+ MetricsMember_t member_type;
+
+ if (!value)
+ return -EINVAL;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ member_type = METRICS_CURR_GFXCLK;
+ break;
+ case SMU_UCLK:
+ case SMU_MCLK:
+ member_type = METRICS_CURR_UCLK;
+ break;
+ case SMU_SOCCLK:
+ member_type = METRICS_CURR_SOCCLK;
+ break;
+ case SMU_VCLK:
+ member_type = METRICS_CURR_VCLK;
+ break;
+ case SMU_DCLK:
+ member_type = METRICS_CURR_DCLK;
+ break;
+ case SMU_FCLK:
+ member_type = METRICS_CURR_FCLK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return smu_v15_0_8_get_smu_metrics_data(smu, member_type, value);
+}
+
+static int smu_v15_0_8_emit_clk_levels(struct smu_context *smu,
+ enum smu_clk_type type, char *buf,
+ int *offset)
+{
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ struct smu_15_0_dpm_context *dpm_context;
+ struct smu_dpm_table *single_dpm_table = NULL;
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ int ret, now, size = *offset;
+
+ if (amdgpu_ras_intr_triggered()) {
+ sysfs_emit_at(buf, size, "unavailable\n");
+ return -EBUSY;
+ }
+
+ dpm_context = smu_dpm->dpm_context;
+
+ switch (type) {
+ case SMU_OD_SCLK:
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ pstate_table->gfxclk_pstate.curr.min,
+ pstate_table->gfxclk_pstate.curr.max);
+ break;
+ case SMU_OD_MCLK:
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK");
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n",
+ pstate_table->uclk_pstate.curr.min,
+ pstate_table->uclk_pstate.curr.max);
+ break;
+ case SMU_SCLK:
+ case SMU_GFXCLK:
+ single_dpm_table = &dpm_context->dpm_tables.gfx_table;
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ single_dpm_table = &dpm_context->dpm_tables.uclk_table;
+ break;
+ case SMU_SOCCLK:
+ single_dpm_table = &dpm_context->dpm_tables.soc_table;
+ break;
+ case SMU_FCLK:
+ single_dpm_table = &dpm_context->dpm_tables.fclk_table;
+ break;
+ case SMU_VCLK:
+ single_dpm_table = &dpm_context->dpm_tables.vclk_table;
+ break;
+ case SMU_DCLK:
+ single_dpm_table = &dpm_context->dpm_tables.dclk_table;
+ break;
+ default:
+ break;
+ }
+
+ if (single_dpm_table) {
+ ret = smu_v15_0_8_get_current_clk_freq_by_table(smu, type, &now);
+ if (ret) {
+ dev_err(smu->adev->dev,
+ "Attempt to get current clk Failed!");
+ return ret;
+ }
+ ret = smu_cmn_print_dpm_clk_levels(smu, single_dpm_table, now,
+ buf, offset);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+ }
+
+ *offset = size;
+
+ return 0;
+}
+
static int smu_v15_0_8_get_dpm_ultimate_freq(struct smu_context *smu,
enum smu_clk_type clk_type,
uint32_t *min, uint32_t *max)
@@ -1206,6 +1403,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.get_unique_id = smu_v15_0_8_get_unique_id,
.get_power_limit = smu_v15_0_8_get_power_limit,
.set_power_limit = smu_v15_0_set_power_limit,
+ .emit_clk_levels = smu_v15_0_8_emit_clk_levels,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 15/25] drm/amd/pm: add populate_umd_state_clk support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (12 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 14/25] drm/amd/pm: Add emit clock support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 16/25] drm/amd/pm: Add set_performance_support Alex Deucher
` (9 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Yang Wang, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
add populate_umd_state_clk support for smu 15.0.8
v2: remove gl2clk/socclk/fclk, restrict to only current min/max (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 9b48c258b1f20..f3378e73b6ccb 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1376,6 +1376,21 @@ static int smu_v15_0_8_get_power_limit(struct smu_context *smu,
return 0;
}
+static int smu_v15_0_8_populate_umd_state_clk(struct smu_context *smu)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
+ struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+
+ pstate_table->gfxclk_pstate.curr.min = SMU_DPM_TABLE_MIN(gfx_table);
+ pstate_table->gfxclk_pstate.curr.max = SMU_DPM_TABLE_MAX(gfx_table);
+
+ pstate_table->uclk_pstate.curr.min = SMU_DPM_TABLE_MIN(mem_table);
+ pstate_table->uclk_pstate.curr.max = SMU_DPM_TABLE_MAX(mem_table);
+ return 0;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1404,7 +1419,8 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.get_power_limit = smu_v15_0_8_get_power_limit,
.set_power_limit = smu_v15_0_set_power_limit,
.emit_clk_levels = smu_v15_0_8_emit_clk_levels,
-};
+ .populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
+ };
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
const struct cmn2asic_msg_mapping *message_map)
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 16/25] drm/amd/pm: Add set_performance_support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (13 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 15/25] drm/amd/pm: add populate_umd_state_clk support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 17/25] drm/amd/pm: Add od_edit_dpm_table support Alex Deucher
` (8 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Yang Wang, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add set_performance_support for smu_v15_0_8
v2: Skip Gl2clk/fclk (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 141 +++++++++++++++++-
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 10 ++
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 1 +
3 files changed, 151 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index f3378e73b6ccb..435798388b012 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1391,6 +1391,144 @@ static int smu_v15_0_8_populate_umd_state_clk(struct smu_context *smu)
return 0;
}
+static int smu_v15_0_8_set_gfx_soft_freq_limited_range(struct smu_context *smu,
+ uint32_t min,
+ uint32_t max)
+{
+ int ret;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ max & 0xffff, NULL);
+ if (ret)
+ return ret;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinGfxclk,
+ min & 0xffff, NULL);
+
+ return ret;
+}
+
+static int smu_v15_0_8_set_performance_level(struct smu_context *smu,
+ enum amd_dpm_forced_level level)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_15_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
+ struct smu_dpm_table *uclk_table = &dpm_context->dpm_tables.uclk_table;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ int ret;
+
+ switch (level) {
+ case AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM:
+ /* Determinism not supported on SMU v15.0.8 */
+ ret = -EOPNOTSUPP;
+ break;
+
+ case AMD_DPM_FORCED_LEVEL_AUTO:
+ /* Restore GFXCLK to default range */
+ if ((SMU_DPM_TABLE_MIN(gfx_table) !=
+ pstate_table->gfxclk_pstate.curr.min) ||
+ (SMU_DPM_TABLE_MAX(gfx_table) !=
+ pstate_table->gfxclk_pstate.curr.max)) {
+ ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(
+ smu, SMU_DPM_TABLE_MIN(gfx_table),
+ SMU_DPM_TABLE_MAX(gfx_table));
+ if (ret)
+ goto out;
+
+ pstate_table->gfxclk_pstate.curr.min =
+ SMU_DPM_TABLE_MIN(gfx_table);
+ pstate_table->gfxclk_pstate.curr.max =
+ SMU_DPM_TABLE_MAX(gfx_table);
+ }
+
+ /* Restore UCLK to default max */
+ if (SMU_DPM_TABLE_MAX(uclk_table) !=
+ pstate_table->uclk_pstate.curr.max) {
+ /* Min UCLK is not expected to be changed */
+ ret = smu_v15_0_set_soft_freq_limited_range(smu,
+ SMU_UCLK, 0,
+ SMU_DPM_TABLE_MAX(uclk_table),
+ false);
+ if (ret)
+ goto out;
+
+ pstate_table->uclk_pstate.curr.max =
+ SMU_DPM_TABLE_MAX(uclk_table);
+ }
+
+ if (ret)
+ goto out;
+
+ smu_cmn_reset_custom_level(smu);
+
+ break;
+ case AMD_DPM_FORCED_LEVEL_MANUAL:
+ ret = 0;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+out:
+ return ret;
+}
+
+static int smu_v15_0_8_set_soft_freq_limited_range(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t min, uint32_t max,
+ bool automatic)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ int ret = 0;
+
+ if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK &&
+ clk_type != SMU_UCLK)
+ return -EINVAL;
+
+ if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+ return -EINVAL;
+
+ if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
+ if (min >= max) {
+ dev_err(smu->adev->dev,
+ "Minimum clk should be less than the maximum allowed clock\n");
+ return -EINVAL;
+ }
+
+ if (clk_type == SMU_GFXCLK || clk_type == SMU_SCLK) {
+ if ((min == pstate_table->gfxclk_pstate.curr.min) &&
+ (max == pstate_table->gfxclk_pstate.curr.max))
+ return 0;
+
+ ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(smu,
+ min, max);
+ if (!ret) {
+ pstate_table->gfxclk_pstate.curr.min = min;
+ pstate_table->gfxclk_pstate.curr.max = max;
+ }
+ }
+
+ if (clk_type == SMU_UCLK) {
+ if (max == pstate_table->uclk_pstate.curr.max)
+ return 0;
+
+ ret = smu_v15_0_set_soft_freq_limited_range(smu,
+ SMU_UCLK,
+ 0, max,
+ false);
+ if (!ret)
+ pstate_table->uclk_pstate.curr.max = max;
+ }
+
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1420,7 +1558,8 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.set_power_limit = smu_v15_0_set_power_limit,
.emit_clk_levels = smu_v15_0_8_emit_clk_levels,
.populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
- };
+ .set_performance_level = smu_v15_0_8_set_performance_level,
+};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
const struct cmn2asic_msg_mapping *message_map)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index a644579903f40..09b486ed3f1ee 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1305,6 +1305,16 @@ void smu_cmn_get_backend_workload_mask(struct smu_context *smu,
}
}
+void smu_cmn_reset_custom_level(struct smu_context *smu)
+{
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+
+ pstate_table->gfxclk_pstate.custom.min = 0;
+ pstate_table->gfxclk_pstate.custom.max = 0;
+ pstate_table->uclk_pstate.custom.min = 0;
+ pstate_table->uclk_pstate.custom.max = 0;
+}
+
static inline bool smu_cmn_freqs_match(uint32_t freq1, uint32_t freq2)
{
/* Frequencies within 25 MHz are considered equal */
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index e4d282d8bcae3..b76e86df5da78 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -204,6 +204,7 @@ int smu_cmn_print_pcie_levels(struct smu_context *smu,
struct smu_pcie_table *pcie_table,
uint32_t cur_gen, uint32_t cur_lane,
char *buf, int *offset);
+void smu_cmn_reset_custom_level(struct smu_context *smu);
int smu_cmn_dpm_pcie_gen_idx(int gen);
int smu_cmn_dpm_pcie_width_idx(int width);
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 17/25] drm/amd/pm: Add od_edit_dpm_table support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (14 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 16/25] drm/amd/pm: Add set_performance_support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 18/25] drm/amd/pm: Add get_thermal_temperature_range support Alex Deucher
` (7 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Yang Wang, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add od_edit_dpm_table support for smu_v15_0_8
v2: Skip Gl2clk/Fclk (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 155 ++++++++++++++++++
1 file changed, 155 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 435798388b012..04f16fd0633b6 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1529,6 +1529,160 @@ static int smu_v15_0_8_set_soft_freq_limited_range(struct smu_context *smu,
return 0;
}
+static int smu_v15_0_8_od_edit_dpm_table(struct smu_context *smu,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[], uint32_t size)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+ struct smu_15_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ uint32_t min_clk, max_clk;
+ int ret;
+
+ /* Only allowed in manual mode */
+ if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+ return -EINVAL;
+
+ switch (type) {
+ case PP_OD_EDIT_SCLK_VDDC_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.gfx_table);
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.gfx_table);
+ if (input[0] == 0) {
+ if (input[1] < min_clk) {
+ dev_warn(smu->adev->dev,
+ "Minimum GFX clk (%ld) MHz specified is less than the minimum allowed (%d) MHz\n",
+ input[1], min_clk);
+ pstate_table->gfxclk_pstate.custom.min =
+ pstate_table->gfxclk_pstate.curr.min;
+ return -EINVAL;
+ }
+
+ pstate_table->gfxclk_pstate.custom.min = input[1];
+ } else if (input[0] == 1) {
+ if (input[1] > max_clk) {
+ dev_warn(smu->adev->dev,
+ "Maximum GFX clk (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
+ input[1], max_clk);
+ pstate_table->gfxclk_pstate.custom.max =
+ pstate_table->gfxclk_pstate.curr.max;
+ return -EINVAL;
+ }
+
+ pstate_table->gfxclk_pstate.custom.max = input[1];
+ } else {
+ return -EINVAL;
+ }
+ break;
+ case PP_OD_EDIT_MCLK_VDDC_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
+ dev_warn(smu->adev->dev,
+ "UCLK_LIMITS setting not supported!\n");
+ return -EOPNOTSUPP;
+ }
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.uclk_table);
+ if (input[0] == 0) {
+ dev_info(smu->adev->dev,
+ "Setting min UCLK level is not supported");
+ return -EINVAL;
+ } else if (input[0] == 1) {
+ if (input[1] > max_clk) {
+ dev_warn(smu->adev->dev,
+ "Maximum UCLK (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n",
+ input[1], max_clk);
+ pstate_table->uclk_pstate.custom.max =
+ pstate_table->uclk_pstate.curr.max;
+
+ return -EINVAL;
+ }
+
+ pstate_table->uclk_pstate.custom.max = input[1];
+ }
+ break;
+ case PP_OD_RESTORE_DEFAULT_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ /* Use the default frequencies for manual mode */
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.gfx_table);
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.gfx_table);
+
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_GFXCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+
+ min_clk = SMU_DPM_TABLE_MIN(&dpm_context->dpm_tables.uclk_table);
+ max_clk = SMU_DPM_TABLE_MAX(&dpm_context->dpm_tables.uclk_table);
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_UCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+
+ smu_cmn_reset_custom_level(smu);
+ break;
+ case PP_OD_COMMIT_DPM_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev,
+ "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (!pstate_table->gfxclk_pstate.custom.min)
+ pstate_table->gfxclk_pstate.custom.min =
+ pstate_table->gfxclk_pstate.curr.min;
+
+ if (!pstate_table->gfxclk_pstate.custom.max)
+ pstate_table->gfxclk_pstate.custom.max =
+ pstate_table->gfxclk_pstate.curr.max;
+
+ min_clk = pstate_table->gfxclk_pstate.custom.min;
+ max_clk = pstate_table->gfxclk_pstate.custom.max;
+
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_GFXCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+
+ /* Commit UCLK custom range (only max supported) */
+ if (pstate_table->uclk_pstate.custom.max) {
+ min_clk = pstate_table->uclk_pstate.curr.min;
+ max_clk = pstate_table->uclk_pstate.custom.max;
+ ret = smu_v15_0_8_set_soft_freq_limited_range(smu,
+ SMU_UCLK,
+ min_clk, max_clk,
+ false);
+ if (ret)
+ return ret;
+ }
+
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1559,6 +1713,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.emit_clk_levels = smu_v15_0_8_emit_clk_levels,
.populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
.set_performance_level = smu_v15_0_8_set_performance_level,
+ .od_edit_dpm_table = smu_v15_0_8_od_edit_dpm_table,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 18/25] drm/amd/pm: Add get_thermal_temperature_range support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (15 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 17/25] drm/amd/pm: Add od_edit_dpm_table support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 19/25] drm/amd/pm: Add ppt1 support Alex Deucher
` (6 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Yang Wang, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add get_thermal_temperature_range support smu_v15_0_8
v2: Remove sriov check (Lijo)
v3: Restrict to 1VF mode(Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 04f16fd0633b6..7a5582253f5d4 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1683,6 +1683,38 @@ static int smu_v15_0_8_od_edit_dpm_table(struct smu_context *smu,
return 0;
}
+static int smu_v15_0_8_get_thermal_temperature_range(struct smu_context *smu,
+ struct smu_temperature_range *range)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ uint32_t max_ctf, max_thm;
+
+ if (amdgpu_sriov_multi_vf_mode(smu->adev))
+ return 0;
+
+ if (!range)
+ return -EINVAL;
+
+ /* CTF (Critical Temperature Fault) limits */
+ max_ctf = max3(pptable->CTFLimitMID, pptable->CTFLimitXCD,
+ pptable->CTFLimitAID);
+ range->hotspot_emergency_max = max_ctf * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ range->mem_emergency_max = pptable->CTFLimitHBM *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ /* Thermal throttling limits */
+ max_thm = max3(pptable->ThermalLimitMID, pptable->ThermalLimitXCD,
+ pptable->ThermalLimitAID);
+ range->hotspot_crit_max = max_thm * SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ range->mem_crit_max = pptable->ThermalLimitHBM *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+ return 0;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1714,6 +1746,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
.set_performance_level = smu_v15_0_8_set_performance_level,
.od_edit_dpm_table = smu_v15_0_8_od_edit_dpm_table,
+ .get_thermal_temperature_range = smu_v15_0_8_get_thermal_temperature_range,
};
static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 19/25] drm/amd/pm: Add ppt1 support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (16 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 18/25] drm/amd/pm: Add get_thermal_temperature_range support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 20/25] drm/amd/pm: Add read sensor support Alex Deucher
` (5 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add ppt1 support for smu_v15_0_8
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 75 ++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 7a5582253f5d4..7dc5100700808 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1715,6 +1715,78 @@ static int smu_v15_0_8_get_thermal_temperature_range(struct smu_context *smu,
return 0;
}
+static int smu_v15_0_8_set_power_limit(struct smu_context *smu,
+ enum smu_ppt_limit_type limit_type,
+ uint32_t limit)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int ret;
+
+ if (limit_type == SMU_FAST_PPT_LIMIT) {
+ if (!pptable->PPT1Max)
+ return -EOPNOTSUPP;
+
+ if (limit > pptable->PPT1Max || limit < pptable->PPT1Min) {
+ dev_err(smu->adev->dev,
+ "New PPT1 limit (%d) should be between min %d and max %d\n",
+ limit, pptable->PPT1Min, pptable->PPT1Max);
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetFastPptLimit,
+ limit, NULL);
+ if (ret)
+ dev_err(smu->adev->dev, "Set fast PPT limit failed!\n");
+
+ return ret;
+ }
+
+ return smu_v15_0_set_power_limit(smu, limit_type, limit);
+}
+
+static int smu_v15_0_8_get_ppt_limit(struct smu_context *smu,
+ uint32_t *ppt_limit,
+ enum smu_ppt_limit_type type,
+ enum smu_ppt_limit_level level)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ PPTable_t *pptable = (PPTable_t *)smu_table->driver_pptable;
+ int ret = 0;
+
+ if (!ppt_limit)
+ return -EINVAL;
+
+ if (type == SMU_FAST_PPT_LIMIT) {
+ if (!pptable->PPT1Max)
+ return -EOPNOTSUPP;
+
+ switch (level) {
+ case SMU_PPT_LIMIT_MAX:
+ *ppt_limit = pptable->PPT1Max;
+ break;
+ case SMU_PPT_LIMIT_CURRENT:
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPptLimit,
+ ppt_limit);
+ if (ret)
+ dev_err(smu->adev->dev,
+ "Get fast PPT limit failed!\n");
+ break;
+ case SMU_PPT_LIMIT_DEFAULT:
+ *ppt_limit = pptable->PPT1Default;
+ break;
+ case SMU_PPT_LIMIT_MIN:
+ *ppt_limit = pptable->PPT1Min;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return ret;
+ }
+
+ return -EOPNOTSUPP;
+}
+
static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.init_allowed_features = smu_v15_0_8_init_allowed_features,
.set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1741,7 +1813,8 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.get_gpu_metrics = smu_v15_0_8_get_gpu_metrics,
.get_unique_id = smu_v15_0_8_get_unique_id,
.get_power_limit = smu_v15_0_8_get_power_limit,
- .set_power_limit = smu_v15_0_set_power_limit,
+ .set_power_limit = smu_v15_0_8_set_power_limit,
+ .get_ppt_limit = smu_v15_0_8_get_ppt_limit,
.emit_clk_levels = smu_v15_0_8_emit_clk_levels,
.populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
.set_performance_level = smu_v15_0_8_set_performance_level,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 20/25] drm/amd/pm: Add read sensor support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (17 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 19/25] drm/amd/pm: Add ppt1 support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 21/25] drm/amd/pm: Add gpuboard temperature metrics support Alex Deucher
` (4 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add read sensor support for smu_v15_0_8
v2: Remove gfx voltage support (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 112 ++++++++++++++++++
1 file changed, 112 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index 7dc5100700808..a2a640aaa0775 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -434,6 +434,117 @@ static int smu_v15_0_8_get_current_clk_freq_by_table(struct smu_context *smu,
return smu_v15_0_8_get_smu_metrics_data(smu, member_type, value);
}
+static int smu_v15_0_8_get_current_activity_percent(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ int ret = 0;
+
+ if (!value)
+ return -EINVAL;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY, value);
+ break;
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY, value);
+ break;
+ default:
+ dev_err(smu->adev->dev,
+ "Invalid sensor for retrieving clock activity\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int smu_v15_0_8_thermal_get_temperature(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ int ret = 0;
+
+ if (!value)
+ return -EINVAL;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT, value);
+ break;
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM, value);
+ break;
+ default:
+ dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int smu_v15_0_8_read_sensor(struct smu_context *smu,
+ enum amd_pp_sensors sensor, void *data,
+ uint32_t *size)
+{
+ struct smu_15_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ int ret = 0;
+
+ if (amdgpu_ras_intr_triggered())
+ return 0;
+
+ if (!data || !size)
+ return -EINVAL;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = smu_v15_0_8_get_current_activity_percent(smu, sensor,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
+ ret = smu_v15_0_8_get_smu_metrics_data(smu,
+ METRICS_CURR_SOCKETPOWER,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ ret = smu_v15_0_8_thermal_get_temperature(smu, sensor,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_MCLK:
+ ret = smu_v15_0_8_get_current_clk_freq_by_table(smu,
+ SMU_UCLK, (uint32_t *)data);
+ /* the output clock frequency in 10K unit */
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_SCLK:
+ ret = smu_v15_0_8_get_current_clk_freq_by_table(smu,
+ SMU_GFXCLK, (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDBOARD:
+ *(uint32_t *)data = dpm_context->board_volt;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
static int smu_v15_0_8_emit_clk_levels(struct smu_context *smu,
enum smu_clk_type type, char *buf,
int *offset)
@@ -1816,6 +1927,7 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
.set_power_limit = smu_v15_0_8_set_power_limit,
.get_ppt_limit = smu_v15_0_8_get_ppt_limit,
.emit_clk_levels = smu_v15_0_8_emit_clk_levels,
+ .read_sensor = smu_v15_0_8_read_sensor,
.populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
.set_performance_level = smu_v15_0_8_set_performance_level,
.od_edit_dpm_table = smu_v15_0_8_od_edit_dpm_table,
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 21/25] drm/amd/pm: Add gpuboard temperature metrics support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (18 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 20/25] drm/amd/pm: Add read sensor support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 22/25] drm/amd/pm: Add baseboard " Alex Deucher
` (3 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add gpuboard temperature metrics support via system metrics table for
smu_v15_0_8
v3: Use per sensor attr id (Lijo)
v4: Use s16 for temp, remove cast, use separate function to fill
gpuboard temperature metrics data (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../gpu/drm/amd/include/kgd_pp_interface.h | 35 ++++
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 172 ++++++++++++++++++
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h | 71 ++++++++
3 files changed, 278 insertions(+)
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 22ee30f514c0a..04efa127a3dd9 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -588,6 +588,35 @@ enum amdgpu_metrics_attr_id {
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_MID,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_AID,
AMDGPU_METRICS_ATTR_ID_TEMPERATURE_XCD,
+ AMDGPU_METRICS_ATTR_ID_LABEL_VERSION,
+ AMDGPU_METRICS_ATTR_ID_NODE_ID,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_RETIMER,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_IBC,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_IBC_2,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_VDD18_VR,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_04_HBM_B_VR,
+ AMDGPU_METRICS_ATTR_ID_NODE_TEMP_04_HBM_D_VR,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_SOCIO_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_SOCIO_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_X0,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_X1,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_04_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_04_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_075_HBM_B,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_075_HBM_D,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_11_GTA_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_11_GTA_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDAN_075_GTA_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDAN_075_GTA_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDCR_075_UCIE,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAA,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAM_A,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAM_C,
+ AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDAN_075,
AMDGPU_METRICS_ATTR_ID_MAX,
};
@@ -1840,4 +1869,10 @@ enum amdgpu_xgmi_link_status {
AMDGPU_XGMI_LINK_NA = 2,
};
+struct amdgpu_gpuboard_temp_metrics_v1_1 {
+ struct metrics_table_header common_header;
+ int attr_count;
+ struct gpu_metrics_attr metrics_attrs[];
+};
+
#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index a2a640aaa0775..e6895e03aa3a8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -171,8 +171,14 @@ static const struct cmn2asic_mapping smu_v15_0_8_table_map[SMU_TABLE_COUNT] = {
TAB_MAP(I2C_COMMANDS),
};
+static size_t smu_v15_0_8_get_system_metrics_size(void)
+{
+ return sizeof(SystemMetricsTable_t);
+}
+
static int smu_v15_0_8_tables_init(struct smu_context *smu)
{
+ struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics;
struct smu_table_context *smu_table = &smu->smu_table;
int ret, gpu_metrcs_size = sizeof(MetricsTable_t);
struct smu_table *tables = smu_table->tables;
@@ -187,6 +193,9 @@ static int smu_v15_0_8_tables_init(struct smu_context *smu)
gpu_metrcs_size,
PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT);
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMFW_SYSTEM_METRICS,
+ smu_v15_0_8_get_system_metrics_size(), PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT);
metrics_table = kzalloc(gpu_metrcs_size, GFP_KERNEL);
if (!metrics_table)
@@ -207,6 +216,25 @@ static int smu_v15_0_8_tables_init(struct smu_context *smu)
gpu_metrics = (struct smu_v15_0_8_gpu_metrics *)smu_driver_table_ptr(smu,
SMU_DRIVER_TABLE_GPU_METRICS);
smu_v15_0_8_gpu_metrics_init(gpu_metrics, 1, 9);
+
+ ret = smu_table_cache_init(smu, SMU_TABLE_PMFW_SYSTEM_METRICS,
+ smu_v15_0_8_get_system_metrics_size(), 5);
+
+ if (ret)
+ return ret;
+
+ /* Initialize GPU board temperature metrics */
+ ret = smu_driver_table_init(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS,
+ sizeof(*gpuboard_temp_metrics), 50);
+ if (ret) {
+ smu_table_cache_fini(smu, SMU_TABLE_PMFW_SYSTEM_METRICS);
+ return ret;
+ }
+ gpuboard_temp_metrics = (struct smu_v15_0_8_gpuboard_temp_metrics *)
+ smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_v15_0_8_gpuboard_temp_metrics_init(gpuboard_temp_metrics, 1, 1);
+
smu_table->metrics_table = no_free_ptr(metrics_table);
smu_table->driver_pptable = no_free_ptr(driver_pptable);
@@ -252,6 +280,8 @@ static int smu_v15_0_8_tables_fini(struct smu_context *smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
+ smu_driver_table_fini(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_table_cache_fini(smu, SMU_TABLE_PMFW_SYSTEM_METRICS);
mutex_destroy(&smu_table->metrics_lock);
return 0;
@@ -487,6 +517,33 @@ static int smu_v15_0_8_thermal_get_temperature(struct smu_context *smu,
return ret;
}
+static int smu_v15_0_8_get_system_metrics_table(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *table = &smu_table->driver_table;
+ struct smu_table *tables = smu_table->tables;
+ struct smu_table *sys_table;
+ int ret;
+
+ sys_table = &tables[SMU_TABLE_PMFW_SYSTEM_METRICS];
+ if (smu_table_cache_is_valid(sys_table))
+ return 0;
+
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSystemMetricsTable, NULL);
+ if (ret) {
+ dev_info(smu->adev->dev,
+ "Failed to export system metrics table!\n");
+ return ret;
+ }
+
+ amdgpu_hdp_invalidate(smu->adev, NULL);
+ smu_table_cache_update_time(sys_table, jiffies);
+ memcpy(sys_table->cache.buffer, table->cpu_addr,
+ sizeof(SystemMetricsTable_t));
+
+ return 0;
+}
+
static int smu_v15_0_8_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor, void *data,
uint32_t *size)
@@ -1292,6 +1349,115 @@ static int smu_v15_0_8_mode2_reset(struct smu_context *smu)
return ret;
}
+static bool smu_v15_0_8_is_temp_metrics_supported(struct smu_context *smu,
+ enum smu_temp_metric_type type)
+{
+ switch (type) {
+ case SMU_TEMP_METRIC_GPUBOARD:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void smu_v15_0_8_fill_gpuboard_temp_metrics(
+ struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics,
+ const SystemMetricsTable_t *metrics)
+{
+ gpuboard_temp_metrics->accumulation_counter = metrics->AccumulationCounter;
+ gpuboard_temp_metrics->label_version = metrics->LabelVersion;
+ gpuboard_temp_metrics->node_id = metrics->NodeIdentifier;
+
+ gpuboard_temp_metrics->node_temp_retimer =
+ metrics->NodeTemperatures[NODE_TEMP_RETIMER];
+ gpuboard_temp_metrics->node_temp_ibc =
+ metrics->NodeTemperatures[NODE_TEMP_IBC_TEMP];
+ gpuboard_temp_metrics->node_temp_ibc_2 =
+ metrics->NodeTemperatures[NODE_TEMP_IBC_2_TEMP];
+ gpuboard_temp_metrics->node_temp_vdd18_vr =
+ metrics->NodeTemperatures[NODE_TEMP_VDD18_VR_TEMP];
+ gpuboard_temp_metrics->node_temp_04_hbm_b_vr =
+ metrics->NodeTemperatures[NODE_TEMP_04_HBM_B_VR_TEMP];
+ gpuboard_temp_metrics->node_temp_04_hbm_d_vr =
+ metrics->NodeTemperatures[NODE_TEMP_04_HBM_D_VR_TEMP];
+
+ gpuboard_temp_metrics->vr_temp_vddcr_socio_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_SOCIO_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_socio_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_SOCIO_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_x0 =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_X0_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_x1 =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_X1_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_04_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_04_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_04_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_04_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_075_hbm_b =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_075_HBM_B_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_075_hbm_d =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_075_HBM_D_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_11_gta_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_11_GTA_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_11_gta_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_11_GTA_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddan_075_gta_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDAN_075_GTA_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddan_075_gta_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDAN_075_GTA_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddcr_075_ucie =
+ metrics->VrTemperatures[SVI_PLANE_VDDCR_075_UCIE_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_065_ucieaa =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_065_UCIEAA_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_065_ucieam_a =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_065_UCIEAM_A_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddio_065_ucieam_c =
+ metrics->VrTemperatures[SVI_PLANE_VDDIO_065_UCIEAM_C_TEMP];
+ gpuboard_temp_metrics->vr_temp_vddan_075 =
+ metrics->VrTemperatures[SVI_PLANE_VDDAN_075_TEMP];
+}
+
+static ssize_t smu_v15_0_8_get_temp_metrics(struct smu_context *smu,
+ enum smu_temp_metric_type type,
+ void *table)
+{
+ struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics;
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+ enum smu_driver_table_id table_id;
+ SystemMetricsTable_t *metrics;
+ struct smu_table *sys_table;
+ ssize_t size;
+ int ret;
+
+ table_id = SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS;
+ gpuboard_temp_metrics =
+ (struct smu_v15_0_8_gpuboard_temp_metrics *)
+ smu_driver_table_ptr(smu, table_id);
+ size = sizeof(*gpuboard_temp_metrics);
+
+ ret = smu_v15_0_8_get_system_metrics_table(smu);
+ if (ret)
+ return ret;
+
+ sys_table = &tables[SMU_TABLE_PMFW_SYSTEM_METRICS];
+ metrics = (SystemMetricsTable_t *)sys_table->cache.buffer;
+ smu_driver_table_update_cache_time(smu, table_id);
+
+ smu_v15_0_8_fill_gpuboard_temp_metrics(gpuboard_temp_metrics,
+ metrics);
+ memcpy(table, gpuboard_temp_metrics, size);
+ return size;
+}
+
static ssize_t smu_v15_0_8_get_gpu_metrics(struct smu_context *smu, void **table)
{
struct smu_table_context *smu_table = &smu->smu_table;
@@ -1954,6 +2120,11 @@ static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
ctl->message_map = message_map;
}
+static const struct smu_temp_funcs smu_v15_0_8_temp_funcs = {
+ .temp_metrics_is_supported = smu_v15_0_8_is_temp_metrics_supported,
+ .get_temp_metrics = smu_v15_0_8_get_temp_metrics,
+};
+
void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu)
{
smu->ppt_funcs = &smu_v15_0_8_ppt_funcs;
@@ -1961,5 +2132,6 @@ void smu_v15_0_8_set_ppt_funcs(struct smu_context *smu)
smu->feature_map = smu_v15_0_8_feature_mask_map;
smu->table_map = smu_v15_0_8_table_map;
smu_v15_0_8_init_msg_ctl(smu, smu_v15_0_8_message_map);
+ smu->smu_temp.temp_funcs = &smu_v15_0_8_temp_funcs;
smu->smc_driver_if_version = SMU15_DRIVER_IF_VERSION_SMU_V15_0_8;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
index 8fc16796788b5..0856d11d8e55e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
@@ -180,5 +180,76 @@ typedef struct {
SMU_15_0_8_MAX_XCC);
DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpu_metrics, SMU_15_0_8_METRICS_FIELDS);
+
+/* Maximum temperature sensor counts for system metrics */
+#define SMU_15_0_8_MAX_NODE_TEMP_ENTRIES 12
+#define SMU_15_0_8_MAX_VR_TEMP_ENTRIES 22
+
+/* SMUv 15.0.8 GPU board temperature metrics */
+#define SMU_15_0_8_GPUBOARD_TEMP_METRICS_FIELDS(SMU_SCALAR, SMU_ARRAY) \
+ SMU_SCALAR(SMU_MATTR(ACCUMULATION_COUNTER), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), accumulation_counter); \
+ SMU_SCALAR(SMU_MATTR(LABEL_VERSION), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), label_version); \
+ SMU_SCALAR(SMU_MATTR(NODE_ID), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), node_id); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_RETIMER), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_retimer); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_IBC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_ibc); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_IBC_2), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_ibc_2); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_VDD18_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_vdd18_vr); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_04_HBM_B_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_04_hbm_b_vr); \
+ SMU_SCALAR(SMU_MATTR(NODE_TEMP_04_HBM_D_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), node_temp_04_hbm_d_vr); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_SOCIO_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_socio_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_SOCIO_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_socio_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_X0), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_x0); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_X1), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_x1); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_04_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_04_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_04_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_04_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_075_HBM_B), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_075_hbm_b); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_075_HBM_D), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_075_hbm_d); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_11_GTA_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_11_gta_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_11_GTA_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_11_gta_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDAN_075_GTA_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddan_075_gta_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDAN_075_GTA_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddan_075_gta_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDCR_075_UCIE), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddcr_075_ucie); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_065_UCIEAA), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_065_ucieaa); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_065_UCIEAM_A), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_065_ucieam_a); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDIO_065_UCIEAM_C), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddio_065_ucieam_c); \
+ SMU_SCALAR(SMU_MATTR(VR_TEMP_VDDAN_075), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), vr_temp_vddan_075);
+
+DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpuboard_temp_metrics,
+ SMU_15_0_8_GPUBOARD_TEMP_METRICS_FIELDS);
+
#endif
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 22/25] drm/amd/pm: Add baseboard temperature metrics support
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (19 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 21/25] drm/amd/pm: Add gpuboard temperature metrics support Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 23/25] drm/amd/pm: Add NPM support for smu_v15_0_8 Alex Deucher
` (2 subsequent siblings)
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add baseboard temperature metrics support via system metrics table for
smu_v15_0_8
v4: Add separate function to fill baseboard temperature, use 16, remove
casting
v5: Optimize to use single switch case (Lijo)
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../gpu/drm/amd/include/kgd_pp_interface.h | 29 +++++
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 110 +++++++++++++++---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h | 58 +++++++++
3 files changed, 184 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 04efa127a3dd9..83bd621691829 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -617,6 +617,29 @@ enum amdgpu_metrics_attr_id {
AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAM_A,
AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDIO_065_UCIEAM_C,
AMDGPU_METRICS_ATTR_ID_VR_TEMP_VDDAN_075,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FPGA,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FRONT,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_BACK,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_OAM7,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_IBC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_UFPGA,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_OAM1,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_0_1_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_2_3_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_4_5_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_6_7_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FPGA_0V72_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_UBB_FPGA_3V3_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_0_1_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_4_5_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_2_3_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_RETIMER_6_7_0V9_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_IBC_HSC,
+ AMDGPU_METRICS_ATTR_ID_SYSTEM_TEMP_IBC,
AMDGPU_METRICS_ATTR_ID_MAX,
};
@@ -1875,4 +1898,10 @@ struct amdgpu_gpuboard_temp_metrics_v1_1 {
struct gpu_metrics_attr metrics_attrs[];
};
+struct amdgpu_baseboard_temp_metrics_v1_1 {
+ struct metrics_table_header common_header;
+ int attr_count;
+ struct gpu_metrics_attr metrics_attrs[];
+};
+
#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index e6895e03aa3a8..aec0b6872f924 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -178,6 +178,7 @@ static size_t smu_v15_0_8_get_system_metrics_size(void)
static int smu_v15_0_8_tables_init(struct smu_context *smu)
{
+ struct smu_v15_0_8_baseboard_temp_metrics *baseboard_temp_metrics;
struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics;
struct smu_table_context *smu_table = &smu->smu_table;
int ret, gpu_metrcs_size = sizeof(MetricsTable_t);
@@ -223,11 +224,23 @@ static int smu_v15_0_8_tables_init(struct smu_context *smu)
if (ret)
return ret;
+ /* Initialize base board temperature metrics */
+ ret = smu_driver_table_init(smu,
+ SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS,
+ sizeof(*baseboard_temp_metrics), 50);
+ if (ret)
+ return ret;
+ baseboard_temp_metrics = (struct smu_v15_0_8_baseboard_temp_metrics *)
+ smu_driver_table_ptr(smu,
+ SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ smu_v15_0_8_baseboard_temp_metrics_init(baseboard_temp_metrics, 1, 1);
/* Initialize GPU board temperature metrics */
ret = smu_driver_table_init(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS,
sizeof(*gpuboard_temp_metrics), 50);
if (ret) {
smu_table_cache_fini(smu, SMU_TABLE_PMFW_SYSTEM_METRICS);
+ smu_driver_table_fini(smu,
+ SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
return ret;
}
gpuboard_temp_metrics = (struct smu_v15_0_8_gpuboard_temp_metrics *)
@@ -280,6 +293,7 @@ static int smu_v15_0_8_tables_fini(struct smu_context *smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
+ smu_driver_table_fini(smu, SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
smu_driver_table_fini(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
smu_table_cache_fini(smu, SMU_TABLE_PMFW_SYSTEM_METRICS);
mutex_destroy(&smu_table->metrics_lock);
@@ -1353,6 +1367,10 @@ static bool smu_v15_0_8_is_temp_metrics_supported(struct smu_context *smu,
enum smu_temp_metric_type type)
{
switch (type) {
+ case SMU_TEMP_METRIC_BASEBOARD:
+ if (smu->adev->gmc.xgmi.physical_node_id == 0)
+ return true;
+ return false;
case SMU_TEMP_METRIC_GPUBOARD:
return true;
default:
@@ -1360,6 +1378,62 @@ static bool smu_v15_0_8_is_temp_metrics_supported(struct smu_context *smu,
}
}
+static void smu_v15_0_8_fill_baseboard_temp_metrics(
+ struct smu_v15_0_8_baseboard_temp_metrics *baseboard_temp_metrics,
+ const SystemMetricsTable_t *metrics)
+{
+ baseboard_temp_metrics->accumulation_counter = metrics->AccumulationCounter;
+ baseboard_temp_metrics->label_version = metrics->LabelVersion;
+ baseboard_temp_metrics->node_id = metrics->NodeIdentifier;
+
+ baseboard_temp_metrics->system_temp_ubb_fpga =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FPGA];
+ baseboard_temp_metrics->system_temp_ubb_front =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FRONT];
+ baseboard_temp_metrics->system_temp_ubb_back =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_BACK];
+ baseboard_temp_metrics->system_temp_ubb_oam7 =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_OAM7];
+ baseboard_temp_metrics->system_temp_ubb_ibc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_IBC];
+ baseboard_temp_metrics->system_temp_ubb_ufpga =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_UFPGA];
+ baseboard_temp_metrics->system_temp_ubb_oam1 =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_OAM1];
+ baseboard_temp_metrics->system_temp_oam_0_1_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_0_1_HSC];
+ baseboard_temp_metrics->system_temp_oam_2_3_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_2_3_HSC];
+ baseboard_temp_metrics->system_temp_oam_4_5_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_4_5_HSC];
+ baseboard_temp_metrics->system_temp_oam_6_7_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_6_7_HSC];
+ baseboard_temp_metrics->system_temp_ubb_fpga_0v72_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FPGA_0V72_VR];
+ baseboard_temp_metrics->system_temp_ubb_fpga_3v3_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_UBB_FPGA_3V3_VR];
+ baseboard_temp_metrics->system_temp_retimer_0_1_2_3_1v2_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR];
+ baseboard_temp_metrics->system_temp_retimer_4_5_6_7_1v2_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR];
+ baseboard_temp_metrics->system_temp_retimer_0_1_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_0_1_0V9_VR];
+ baseboard_temp_metrics->system_temp_retimer_4_5_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_4_5_0V9_VR];
+ baseboard_temp_metrics->system_temp_retimer_2_3_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_2_3_0V9_VR];
+ baseboard_temp_metrics->system_temp_retimer_6_7_0v9_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_RETIMER_6_7_0V9_VR];
+ baseboard_temp_metrics->system_temp_oam_0_1_2_3_3v3_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR];
+ baseboard_temp_metrics->system_temp_oam_4_5_6_7_3v3_vr =
+ metrics->SystemTemperatures[SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR];
+ baseboard_temp_metrics->system_temp_ibc_hsc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_IBC_HSC];
+ baseboard_temp_metrics->system_temp_ibc =
+ metrics->SystemTemperatures[SYSTEM_TEMP_IBC];
+}
+
static void smu_v15_0_8_fill_gpuboard_temp_metrics(
struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics,
const SystemMetricsTable_t *metrics)
@@ -1429,33 +1503,43 @@ static ssize_t smu_v15_0_8_get_temp_metrics(struct smu_context *smu,
enum smu_temp_metric_type type,
void *table)
{
+ struct smu_v15_0_8_baseboard_temp_metrics *baseboard_temp_metrics;
struct smu_v15_0_8_gpuboard_temp_metrics *gpuboard_temp_metrics;
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *tables = smu_table->tables;
- enum smu_driver_table_id table_id;
SystemMetricsTable_t *metrics;
struct smu_table *sys_table;
- ssize_t size;
int ret;
- table_id = SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS;
- gpuboard_temp_metrics =
- (struct smu_v15_0_8_gpuboard_temp_metrics *)
- smu_driver_table_ptr(smu, table_id);
- size = sizeof(*gpuboard_temp_metrics);
-
ret = smu_v15_0_8_get_system_metrics_table(smu);
if (ret)
return ret;
sys_table = &tables[SMU_TABLE_PMFW_SYSTEM_METRICS];
metrics = (SystemMetricsTable_t *)sys_table->cache.buffer;
- smu_driver_table_update_cache_time(smu, table_id);
- smu_v15_0_8_fill_gpuboard_temp_metrics(gpuboard_temp_metrics,
- metrics);
- memcpy(table, gpuboard_temp_metrics, size);
- return size;
+ switch (type) {
+ case SMU_TEMP_METRIC_GPUBOARD:
+ gpuboard_temp_metrics =
+ (struct smu_v15_0_8_gpuboard_temp_metrics *)
+ smu_driver_table_ptr(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_driver_table_update_cache_time(smu, SMU_DRIVER_TABLE_GPUBOARD_TEMP_METRICS);
+ smu_v15_0_8_fill_gpuboard_temp_metrics(gpuboard_temp_metrics,
+ metrics);
+ memcpy(table, gpuboard_temp_metrics, sizeof(*gpuboard_temp_metrics));
+ return sizeof(*gpuboard_temp_metrics);
+ case SMU_TEMP_METRIC_BASEBOARD:
+ baseboard_temp_metrics =
+ (struct smu_v15_0_8_baseboard_temp_metrics *)
+ smu_driver_table_ptr(smu, SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ smu_driver_table_update_cache_time(smu, SMU_DRIVER_TABLE_BASEBOARD_TEMP_METRICS);
+ smu_v15_0_8_fill_baseboard_temp_metrics(baseboard_temp_metrics,
+ metrics);
+ memcpy(table, baseboard_temp_metrics, sizeof(*baseboard_temp_metrics));
+ return sizeof(*baseboard_temp_metrics);
+ default:
+ return -EINVAL;
+ }
}
static ssize_t smu_v15_0_8_get_gpu_metrics(struct smu_context *smu, void **table)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
index 0856d11d8e55e..398ce44821741 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.h
@@ -182,6 +182,7 @@ typedef struct {
DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpu_metrics, SMU_15_0_8_METRICS_FIELDS);
/* Maximum temperature sensor counts for system metrics */
+#define SMU_15_0_8_MAX_SYSTEM_TEMP_ENTRIES 32
#define SMU_15_0_8_MAX_NODE_TEMP_ENTRIES 12
#define SMU_15_0_8_MAX_VR_TEMP_ENTRIES 22
@@ -251,5 +252,62 @@ DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpu_metrics, SMU_15_0_8_METRICS_FIELDS);
DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_gpuboard_temp_metrics,
SMU_15_0_8_GPUBOARD_TEMP_METRICS_FIELDS);
+/* SMUv 15.0.8 Baseboard temperature metrics - ID-based approach */
+#define SMU_15_0_8_BASEBOARD_TEMP_METRICS_FIELDS(SMU_SCALAR, SMU_ARRAY) \
+ SMU_SCALAR(SMU_MATTR(ACCUMULATION_COUNTER), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U64), accumulation_counter); \
+ SMU_SCALAR(SMU_MATTR(LABEL_VERSION), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), label_version); \
+ SMU_SCALAR(SMU_MATTR(NODE_ID), SMU_MUNIT(NONE), \
+ SMU_MTYPE(U16), node_id); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FPGA), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_fpga); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FRONT), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_front); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_BACK), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_back); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_OAM7), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_oam7); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_IBC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_ibc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_UFPGA), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_ufpga); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_OAM1), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_oam1); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_0_1_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_0_1_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_2_3_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_2_3_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_4_5_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_4_5_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_6_7_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_6_7_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FPGA_0V72_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_fpga_0v72_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_UBB_FPGA_3V3_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ubb_fpga_3v3_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_0_1_2_3_1V2_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_0_1_2_3_1v2_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_4_5_6_7_1V2_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_4_5_6_7_1v2_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_0_1_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_0_1_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_4_5_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_4_5_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_2_3_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_2_3_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_RETIMER_6_7_0V9_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_retimer_6_7_0v9_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_0_1_2_3_3V3_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_0_1_2_3_3v3_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_OAM_4_5_6_7_3V3_VR), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_oam_4_5_6_7_3v3_vr); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_IBC_HSC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ibc_hsc); \
+ SMU_SCALAR(SMU_MATTR(SYSTEM_TEMP_IBC), SMU_MUNIT(TEMP_1), \
+ SMU_MTYPE(S16), system_temp_ibc);
+
+DECLARE_SMU_METRICS_CLASS(smu_v15_0_8_baseboard_temp_metrics,
+ SMU_15_0_8_BASEBOARD_TEMP_METRICS_FIELDS);
#endif
#endif
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 23/25] drm/amd/pm: Add NPM support for smu_v15_0_8
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (20 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 22/25] drm/amd/pm: Add baseboard " Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 24/25] drm/amdgpu: Add smu v15_0_8 ip block Alex Deucher
2026-03-17 20:12 ` [PATCH 25/25] drm/amd/pm: Enable user specified gfx clock ranges Alex Deucher
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Add node power management support for smu_v15_0_8
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
.../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index aec0b6872f924..c8c9784c99241 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -558,6 +558,46 @@ static int smu_v15_0_8_get_system_metrics_table(struct smu_context *smu)
return 0;
}
+static int smu_v15_0_8_get_npm_data(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+ SystemMetricsTable_t *metrics;
+ struct smu_table *sys_table;
+ int ret;
+
+ if (sensor == AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT) {
+ /*TBD as of now put 0 */
+ *value = 0;
+ return 0;
+ }
+
+ ret = smu_v15_0_8_get_system_metrics_table(smu);
+ if (ret)
+ return ret;
+
+ sys_table = &tables[SMU_TABLE_PMFW_SYSTEM_METRICS];
+ metrics = (SystemMetricsTable_t *)sys_table->cache.buffer;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_NODEPOWERLIMIT:
+ *value = SMUQ10_ROUND(metrics->NodePowerLimit);
+ break;
+ case AMDGPU_PP_SENSOR_NODEPOWER:
+ *value = SMUQ10_ROUND(metrics->NodePower);
+ break;
+ case AMDGPU_PP_SENSOR_GPPTRESIDENCY:
+ *value = SMUQ10_ROUND(metrics->GlobalPPTResidencyAcc);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int smu_v15_0_8_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor, void *data,
uint32_t *size)
@@ -607,6 +647,15 @@ static int smu_v15_0_8_read_sensor(struct smu_context *smu,
*(uint32_t *)data = dpm_context->board_volt;
*size = 4;
break;
+ case AMDGPU_PP_SENSOR_NODEPOWERLIMIT:
+ case AMDGPU_PP_SENSOR_NODEPOWER:
+ case AMDGPU_PP_SENSOR_GPPTRESIDENCY:
+ case AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT:
+ ret = smu_v15_0_8_get_npm_data(smu, sensor, (uint32_t *)data);
+ if (ret)
+ return ret;
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
default:
ret = -EOPNOTSUPP;
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 24/25] drm/amdgpu: Add smu v15_0_8 ip block
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (21 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 23/25] drm/amd/pm: Add NPM support for smu_v15_0_8 Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
2026-03-17 20:12 ` [PATCH 25/25] drm/amd/pm: Enable user specified gfx clock ranges Alex Deucher
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Hawking Zhang, Likun Gao, Alex Deucher
From: Hawking Zhang <Hawking.Zhang@amd.com>
Add smu v15_0_8 ip block
Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Likun Gao <Likun.Gao@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 +
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index f7f37d93d0ce0..1cbe386c86c0e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -2337,6 +2337,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
break;
case IP_VERSION(15, 0, 0):
+ case IP_VERSION(15, 0, 8):
amdgpu_device_ip_block_add(adev, &smu_v15_0_ip_block);
break;
default:
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 6b31b5d173e71..de82eb0f59934 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -803,6 +803,9 @@ static int smu_set_funcs(struct amdgpu_device *adev)
case IP_VERSION(15, 0, 0):
smu_v15_0_0_set_ppt_funcs(smu);
break;
+ case IP_VERSION(15, 0, 8):
+ smu_v15_0_8_set_ppt_funcs(smu);
+ break;
default:
return -EINVAL;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH 25/25] drm/amd/pm: Enable user specified gfx clock ranges
2026-03-17 20:12 [PATCH 01/25] drm/amd/pm: Add smu v15_0_8 driver interface header Alex Deucher
` (22 preceding siblings ...)
2026-03-17 20:12 ` [PATCH 24/25] drm/amdgpu: Add smu v15_0_8 ip block Alex Deucher
@ 2026-03-17 20:12 ` Alex Deucher
23 siblings, 0 replies; 25+ messages in thread
From: Alex Deucher @ 2026-03-17 20:12 UTC (permalink / raw)
To: amd-gfx; +Cc: Asad Kamal, Lijo Lazar, Alex Deucher
From: Asad Kamal <asad.kamal@amd.com>
Enable user specified gfx clock ranges for smu_15_0_8
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index de82eb0f59934..0748c42ec7d5d 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -805,6 +805,7 @@ static int smu_set_funcs(struct amdgpu_device *adev)
break;
case IP_VERSION(15, 0, 8):
smu_v15_0_8_set_ppt_funcs(smu);
+ smu->od_enabled = true;
break;
default:
return -EINVAL;
--
2.53.0
^ permalink raw reply related [flat|nested] 25+ messages in thread