On the Apple 1002:7340/106b:0218 revision 41 board, enabling UCLK DPM with EnableAllSmuFeatures can time out and leave amdgpu without a DRM device. Omitting only UCLK avoids that timeout; enabling it separately immediately afterwards still timed out in a local experiment.
Defer UCLK enablement to the Navi post-init callback, then verify the firmware bit and refresh the supported-feature bit, memory DPM table and sustainable clock limits before the UMC workaround and UMD setup. Validate the PPT memory states consumed by DCN20 before that callback. Keep both memory-voltage features enabled and respect PP_MCLK_DPM_MASK. Limit the change to the board and revision tested locally. Based on Atharva Tiwari's delayed-UCLK proposal for Apple board 0219. This adaptation uses the Navi callback and updates driver clock state; it does not change T2's existing 0219 allowed-mask workaround. Link: https://www.mail-archive.com/[email protected]/msg149770.html Link: https://github.com/t2linux/kernel/issues/19#issuecomment-5537823876 Assisted-by: LLM Signed-off-by: Ed Schofield <[email protected]> --- This is a board-specific follow-up to Atharva Tiwari's August 25 delayed-UCLK proposal for Apple 0219: https://www.mail-archive.com/[email protected]/msg149770.html T2 review: https://github.com/t2linux/linux-t2-patches/pull/60 Hardware report follow-up: https://github.com/t2linux/kernel/issues/19#issuecomment-5579537553 The affected machine here is iMac20,1, PCI 1002:7340 / 106b:0218, revision 41, with SMU firmware 53.38.0, interface 38. The original-policy control times out in EnableAllSmuFeatures (message 6, -62). Omitting only UCLK avoids that timeout. Enabling it immediately afterwards also failed in an earlier local experiment; Navi's post-init callback is the point tested successfully. The patch refreshes driver state after enabling UCLK because initial table setup ran while that feature was disabled. DCN20 also consumes the PPT memory states before post-init, so their count and nonzero frequencies are checked. Both memory-voltage features remain enabled, and the public MCLK-DPM policy still takes precedence over the workaround. A direct control on this AMD staging base used the same kernel image, configuration, firmware, boot parameters and 6,434 companion modules, with only amdgpu rebuilt from the pristine upstream source. Comparing the two extracted initramfs images found exactly one changed file: amdgpu.ko.zst. The first unpatched warm boot passed rendering and video checks. The second reproduced the EnableAllSmuFeatures timeout (message 6, -62) and left no bound AMDGPU driver. Linux remained reachable over SSH. Warnings in amdgpu_irq_put followed during GPU error cleanup. The control series stopped at that point. Restoring the exact patched module/initramfs recovered GPU initialization, hardware rendering and all 60 VAAPI/software frame comparisons on the next warm boot. This demonstrates an intermittent GPU initialization fault on the upstream base, not an inability of every unpatched kernel boot to reach Linux. The experimental implementation passed 40 warm and ten cold boots on this machine. The extracted production implementation has separate T2 7.2.3 warm, rendering, video, sustained-render and public-policy checks. The production T2 patch also passed prescribed AC-connected and AC-unplugged cold starts, with operator-confirmed 60-second intervals and rendering/video validation. An intervening start was corrected to AC-connected when the operator clarified that he had not unplugged it; the actual unplugged test followed. The T2 build also passed a ten-minute, 2 GiB-budget Vulkan memory test with a load/idle/load transition and a normal boot after system updates and initramfs regeneration. This AMD staging variant has a successful W=1 object build, full kernel build and extracted-C ASan/UBSan checks; it has now passed ten warm boots: two attended boots, including recovery after the failed unpatched control, and eight further unattended boots. SMU initialization, SSH, hardware rendering and all 60 VAAPI H.264 frame comparisons against software decoding passed on every boot. Console login was visually confirmed on the two attended boots. All four memory states (98, 500, 625 and 875 MHz) were available, with both memory-voltage features enabled. This build has only the proposed GPU fix on AMD staging, without the T2 patch collection. Rust was disabled after an unrelated Rust DRM preparation failure. This is AMD staging hardware coverage, not a boot of Linus's current tree. No AMD staging cold, suspend/resume or full desktop test is claimed. The staging boot also logged an applesmc probe failure (-5), Bluetooth initialization errors and the previously observed boot-time MCEs. The T2-patched SMC driver initialized successfully after returning to the protected production kernel. USB storage and wired Ethernet provided the boot and SSH path; this test does not establish full T2 device support. Is the Navi post-init callback the right place for this sequencing quirk, and are there additional clock-state consumers that should be refreshed? The predicate is deliberately limited to the tested subsystem and revision. The related 0219 board has an existing T2 allowed-mask override and needs separate evidence before combining the cases. Codex assisted with investigating the initialization sequence, writing the patch and tests, and preparing this message. The session progressed from reproducing the GPU boot failure to isolating UCLK timing and extracting a board-specific fix with public policy and error handling preserved. The patch contains an Assisted-by trailer. The host checks use extracted C with mocked firmware; the T2 hardware results are recorded separately above. .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 81 +++++++++++++++++++ 1 file changed, 81 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..4e8fb9e7c 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,18 @@ 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 && + (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 +368,11 @@ navi10_init_allowed_features(struct smu_context *smu) smu_feature_list_set_bit(smu, SMU_FEATURE_LIST_ALLOWED, FEATURE_MEM_MVDD_SCALING_BIT); } + /* This board times 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 +487,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 +526,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 +3259,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 +3302,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
