On iMac20,2 the Radeon Pro 5700 (1002:731b, Apple subsystem 106b:021a) fails to initialize on approximately half of all boots. The SMU replies to GetSmuVersion and GetDriverIfVersion, then does not reply to EnableAllSmuFeatures:
amdgpu 0000:03:00.0: SMU: No response msg_reg: 6 resp_reg: 0 amdgpu 0000:03:00.0: Failed to enable requested dpm features! amdgpu 0000:03:00.0: hw_init of IP block <smu> failed -62 A second bind of the driver recovers the GPU each time (86 of 86 failures). The failed probe has loaded the PSP. On the second probe, nv_need_reset_on_init() reads a sign of life in MP0_SMN_C2PMSG_81, so the driver does a mode1 reset and a vPOST before it initializes the IP blocks. A reset on init is not possible on the first probe. If the driver tries a reset on init, psp_v11_0_mode1_reset() times out on MBOX_TOS_READY_FLAG, because Apple's firmware does not load the PSP, and the probe fails. The PSP is then still not loaded, and a later bind cannot recover the GPU. Because of this, on this board, return -EPROBE_DEFER when amdgpu_device_ip_init() fails with -ETIME, this attempt did no reset on init, and the ASIC now reports that it needs one. The failed init unwinds as before. When the driver core probes the device again, the probe takes the existing reset-on-init path. The decision uses only local state: the retry has reset the ASIC, so it cannot defer again, and a first attempt that did not load the PSP does not defer. The retry is not done in amdgpu_pci_probe(). adev is devm allocated and amdgpu_device_init() is not re-entrant, so a retry there needs a second adev for the same pci_dev while the first is torn down. The driver core probes a deferred device again only when another driver binds, or when the deferred probe timeout expires. On this board other drivers bind during the SMU timeout, so the retry starts almost immediately. If no driver binds, the GPU stays deferred and the kernel writes no "probe failed" line. dev_err_probe() records the reason, and /sys/kernel/debug/devices_deferred shows it. Tested on iMac20,2 with v7.2.3, built against the 7.2.3 headers: 30 of 30 boots initialized the GPU without user space intervention. The first probe timed out on 14 of them, and each deferred retry succeeded after a mode1 reset. Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5726 Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Teemu Haila <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index fa67de6..600479d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3746,6 +3746,40 @@ amdgpu_device_should_register_switcheroo(struct amdgpu_device *adev, bool px) apple_gmux_detect(NULL, NULL))); } +/* + * On some Apple boards, the first probe after the pre-OS driver times out in + * SMU hw_init. A reset on init recovers the ASIC, but the PSP does the reset, + * and the PSP is not loaded on the first probe. The failed probe loads the + * PSP, so a retry resets the ASIC and succeeds. Because of this, defer the + * probe on these boards instead of failing it. + */ +struct amdgpu_probe_retry_quirk { + u16 device; + u16 subsystem_vendor; + u16 subsystem_device; + u8 revision; +}; + +static const struct amdgpu_probe_retry_quirk amdgpu_probe_retry_quirks[] = { + { 0x731b, PCI_VENDOR_ID_APPLE, 0x021a, 0x40 }, /* Radeon Pro 5700, iMac20,2 */ +}; + +static bool amdgpu_device_probe_retry_quirk(struct amdgpu_device *adev) +{ + struct pci_dev *pdev = adev->pdev; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(amdgpu_probe_retry_quirks); i++) { + if (pdev->device == amdgpu_probe_retry_quirks[i].device && + pdev->subsystem_vendor == amdgpu_probe_retry_quirks[i].subsystem_vendor && + pdev->subsystem_device == amdgpu_probe_retry_quirks[i].subsystem_device && + pdev->revision == amdgpu_probe_retry_quirks[i].revision) + return true; + } + + return false; +} + /** * amdgpu_device_init - initialize the driver * @@ -3761,6 +3795,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, { struct pci_dev *pdev = adev->pdev; int r, i; + bool reset_on_init = false; bool px = false; u32 max_MBps; int tmp; @@ -4037,6 +4072,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, * E.g., driver was not cleanly unloaded previously, etc. */ if (!amdgpu_sriov_vf(adev) && amdgpu_asic_need_reset_on_init(adev)) { + reset_on_init = true; if (adev->gmc.xgmi.num_physical_nodes) { dev_info(adev->dev, "Pending hive reset.\n"); amdgpu_set_init_level(adev, @@ -4110,6 +4146,14 @@ fence_driver_init: if (r) { dev_err(adev->dev, "amdgpu_device_ip_init failed\n"); amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0); + if (r == -ETIME && !reset_on_init && + amdgpu_device_probe_retry_quirk(adev) && + amdgpu_asic_need_reset_on_init(adev)) { + dev_warn(adev->dev, + "init timed out before the ASIC could be reset, deferring the probe to retry with a reset on init\n"); + r = dev_err_probe(adev->dev, -EPROBE_DEFER, + "init timed out before the ASIC could be reset, deferring the probe to retry with a reset on init\n"); + } goto release_ras_con; } base-commit: a24db07159cdd27eba171278366670e9a6c9643f -- 2.55.0
