diff --git a/drivers/gpu/drm/apple/iomfb_template.c b/drivers/gpu/drm/apple/iomfb_template.c index cf40e273a2f43c..77eb2dbf42f693 100644 --- a/drivers/gpu/drm/apple/iomfb_template.c +++ b/drivers/gpu/drm/apple/iomfb_template.c @@ -926,16 +926,33 @@ void DCP_FW_NAME(iomfb_poweroff)(struct apple_dcp *dcp) dcp_swap_start(dcp, false, &swap_req, dcp_swap_clear_started, cookie); - ret = wait_for_completion_timeout(&cookie->done, msecs_to_jiffies(50)); + /* + * On DP unplug DCP firmware first tears down the link itself (HPD + * removal, M3 power down, set_device_enabled 1 -> 0), which can take + * more than 50 ms. Only processes the clear swap afterwards. + * + * A timeout here is not a crash: firmware crashes are reported via + * dcp_rtk_crashed(), and dcp->crashed permanently rejects every atomic + * check on this CRTC. Warn and power off anyway, like the + * setPowerState(0) wait below does. A late reply is safe, the cookie is + * refcounted. + */ + ret = wait_for_completion_timeout(&cookie->done, msecs_to_jiffies(1000)); swap_id = cookie->swap_id; kref_put(&cookie->refcount, release_swap_cookie); - if (ret <= 0) { - dcp->crashed = true; - return; + if (ret == 0) { + /* crashed while we waited, RTKit refuses any further messages */ + if (dcp->crashed) { + dev_warn(dcp->dev, "%s: DCP crashed during clear swap\n", + __func__); + return; + } + dev_warn(dcp->dev, "%s: clear swap timeout %u ms\n", __func__, 1000); + } else { + dev_dbg(dcp->dev, "%s: clear swap submitted: %u after %u ms\n", + __func__, swap_id, 1000 - jiffies_to_msecs(ret)); } - dev_dbg(dcp->dev, "%s: clear swap submitted: %u\n", __func__, swap_id); - poff_cookie = kzalloc(sizeof(*poff_cookie), GFP_KERNEL); if (!poff_cookie) return;