Re: [PATCH v2] drm/amd/pm: defer UCLK DPM enablement on Apple Navi 14

From: Alex Deucher

Date: Thu Sep 10 2026 - 09:31:46 EST


Applied. Thanks!

On Thu, Sep 10, 2026 at 6:40 AM Feng, Kenneth <Kenneth.Feng@xxxxxxx> wrote:
>
> AMD General
>
> Reviewed-by: Kenneth Feng <kenneth.feng@xxxxxxx>
>
> -----Original Message-----
> From: Ed Schofield <ed@xxxxxxxxxxxxxx>
> Sent: Wednesday, September 9, 2026 8:35 PM
> To: Feng, Kenneth <Kenneth.Feng@xxxxxxx>
> Cc: atharvatiwarilinuxdev@xxxxxxxxx; 062bel313@xxxxxxxxx; amd-gfx@xxxxxxxxxxxxxxxxxxxxx; Deucher, Alexander <Alexander.Deucher@xxxxxxx>; Koenig, Christian <Christian.Koenig@xxxxxxx>; airlied@xxxxxxxxx; simona@xxxxxxxx; dri-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
> Subject: [PATCH v2] drm/amd/pm: defer UCLK DPM enablement on Apple Navi 14
>
> Apple Navi 14 boards 1002:7340/106b:0218 (revision 0x41) and
> 1002:7340/106b:0219 can time out when EnableAllSmuFeatures includes UCLK DPM, leaving amdgpu without a DRM device.
>
> Exclude only UCLK DPM from the initial allowed features and enable it separately in the Navi post-init callback. On 0218, enabling UCLK just after EnableAllSmuFeatures or at the start of default DPM table setup still timed out. The earlier 0218-only patch passed ten warm boots with UCLK enabled in post-init. The earliest safe point remains unknown.
>
> Check the enabled firmware bit, update the supported-feature bit and rebuild the memory DPM table and sustainable clock limits before the UMC workaround and UMD clock setup. Validate the PPT memory states that
> DCN20 consumes before post-init. Preserve both memory-voltage features and honor PP_MCLK_DPM_MASK.
>
> Combine Atharva Tiwari's delayed-UCLK proposal for 0219 with the Navi post-init implementation for 0218. Retain the revision restriction for
> 0218 and the revision-independent 0219 match from Atharva's proposal.
>
> The combined patch passed ten warm boots on 0218, with rendering and
> H.264 video decoding checks on every boot. Testing on 0219 is still pending.
>
> Link: https://www.mail-archive.com/amd-gfx@xxxxxxxxxxxxxxxxxxxxx/msg149770.html
> Link: https://github.com/t2linux/kernel/issues/19#issuecomment-5537823876
> Assisted-by: Codex:GPT-6
> Signed-off-by: Ed Schofield <ed@xxxxxxxxxxxxxx>
> ---
> Changes since the 0218-only RFC:
> - Add the 0219 board match from Atharva's proposal, without a revision
> restriction. Keep the 0218 match limited to revision 0x41.
> - Keep the Navi post-init implementation and clock-state updates from
> the RFC. Atharva's proposal enabled UCLK at the end of smu_late_init().
> - Record the failed tests at the start of default DPM table setup and
> ten successful warm boots of the combined patch on 0218.
>
> .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 82 +++++++++++++++++++
> 1 file changed, 82 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
> index f8ca5eb9a..d7cc41a5d 100644
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
> @@ -60,6 +60,19 @@
>
> static int navi10_init_ppt_limits(struct smu_context *smu);
>
> +static bool navi14_needs_late_uclk(struct amdgpu_device *adev) {
> + struct pci_dev *pdev = adev->pdev;
> +
> + return pdev->vendor == PCI_VENDOR_ID_ATI &&
> + pdev->device == 0x7340 &&
> + pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
> + ((pdev->subsystem_device == 0x0218 &&
> + pdev->revision == 0x41) ||
> + pdev->subsystem_device == 0x0219) &&
> + (adev->pm.pp_feature & PP_MCLK_DPM_MASK); }
> +
> static const struct smu_feature_bits navi10_dpm_features = {
> .bits = {
> SMU_FEATURE_BIT_INIT(FEATURE_DPM_PREFETCHER_BIT),
> @@ -356,6 +369,11 @@ navi10_init_allowed_features(struct smu_context *smu)
> smu_feature_list_set_bit(smu, SMU_FEATURE_LIST_ALLOWED, FEATURE_MEM_MVDD_SCALING_BIT);
> }
>
> + /* These boards time out if EnableAllSmuFeatures includes UCLK DPM. */
> + if (navi14_needs_late_uclk(adev))
> + smu_feature_list_clear_bit(smu, SMU_FEATURE_LIST_ALLOWED,
> + FEATURE_DPM_UCLK_BIT);
> +
> if (is_asic_secure(smu) &&
> (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 0)) &&
> (adev->rev_id == 0))
> @@ -470,6 +488,25 @@ static int navi10_store_powerplay_table(struct smu_context *smu)
> return 0;
> }
>
> +/* DCN20 consumes these PPT states before the post-init UCLK enable. */
> +static int navi14_imac_check_uclk_states(struct smu_context *smu) {
> + PPTable_t *ppt = smu->smu_table.driver_pptable;
> + unsigned int count, i;
> +
> + if (!navi14_needs_late_uclk(smu->adev))
> + return 0;
> +
> + count = ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels;
> + if (!count || count > ARRAY_SIZE(ppt->FreqTableUclk))
> + return -EINVAL;
> + for (i = 0; i < count; i++) {
> + if (!ppt->FreqTableUclk[i])
> + return -EINVAL;
> + }
> + return 0;
> +}
> +
> static int navi10_setup_pptable(struct smu_context *smu) {
> int ret = 0;
> @@ -490,6 +527,10 @@ static int navi10_setup_pptable(struct smu_context *smu)
> if (ret)
> return ret;
>
> + ret = navi14_imac_check_uclk_states(smu);
> + if (ret)
> + return ret;
> +
> return navi10_init_ppt_limits(smu);
> }
>
> @@ -3219,6 +3260,41 @@ static int navi10_enable_mgpu_fan_boost(struct smu_context *smu)
> NULL);
> }
>
> +/* Rebuild memory clocks before the UMC workaround and UMD clock setup.
> +*/ static int navi14_imac_late_uclk_enable(struct smu_context *smu) {
> + struct smu_11_0_dpm_context *dpm = smu->smu_dpm.dpm_context;
> + struct smu_dpm_table *table = &dpm->dpm_tables.uclk_table;
> + PPTable_t *ppt = smu->smu_table.driver_pptable;
> + struct smu_feature_bits enabled;
> + int ret;
> +
> + if (!navi14_needs_late_uclk(smu->adev))
> + return 0;
> +
> + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT, true);
> + if (ret)
> + return ret;
> + ret = smu_cmn_get_enabled_mask(smu, &enabled);
> + if (ret)
> + return ret;
> + if (!smu_feature_bits_is_set(&enabled, FEATURE_DPM_UCLK_BIT))
> + return -EIO;
> +
> + smu_feature_list_set_bit(smu, SMU_FEATURE_LIST_SUPPORTED,
> + FEATURE_DPM_UCLK_BIT);
> + table->clk_type = SMU_UCLK;
> + ret = smu_v11_0_set_single_dpm_table(smu, SMU_UCLK, table);
> + if (ret)
> + return ret;
> + if (!table->count)
> + return -EINVAL;
> + if (!ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete)
> + table->flags |= SMU_DPM_TABLE_FINE_GRAINED;
> +
> + return smu_v11_0_init_max_sustainable_clocks(smu);
> +}
> +
> static int navi10_post_smu_init(struct smu_context *smu) {
> struct amdgpu_device *adev = smu->adev; @@ -3227,6 +3303,12 @@ static int navi10_post_smu_init(struct smu_context *smu)
> if (amdgpu_sriov_vf(adev))
> return 0;
>
> + ret = navi14_imac_late_uclk_enable(smu);
> + if (ret) {
> + dev_err(adev->dev, "Failed to enable late UCLK DPM: %d\n", ret);
> + return ret;
> + }
> +
> ret = navi10_run_umc_cdr_workaround(smu);
> if (ret)
> dev_err(adev->dev, "Failed to apply umc cdr workaround!\n");
>
> base-commit: c22f9a61e288580824edbbc3ae5a29c9a338594f
> --
> 2.55.0