Skip to content

Commit f95af4a

Browse files
committed
drm/amdgpu: don't runtime suspend if there are displays attached (v3)
We normally runtime suspend when there are displays attached if they are in the DPMS off state, however, if something wakes the GPU we send a hotplug event on resume (in case any displays were connected while the GPU was in suspend) which can cause userspace to light up the displays again soon after they were turned off. Prior to commit 087451f ("drm/amdgpu: use generic fb helpers instead of setting up AMD own's."), the driver took a runtime pm reference when the fbdev emulation was enabled because we didn't implement proper shadowing support for vram access when the device was off so the device never runtime suspended when there was a console bound. Once that commit landed, we now utilize the core fb helper implementation which properly handles the emulation, so runtime pm now suspends in cases where it did not before. Ultimately, we need to sort out why runtime suspend in not working in this case for some users, but this should restore similar behavior to before. v2: move check into runtime_suspend v3: wake ups -> wakeups in comment, retain pm_runtime behavior in runtime_idle callback Fixes: 087451f ("drm/amdgpu: use generic fb helpers instead of setting up AMD own's.") Link: https://lore.kernel.org/r/20220403132322.51c90903@darkstar.example.org/ Tested-by: Michele Ballabio <ballabio.m@gmail.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
1 parent f567656 commit f95af4a

1 file changed

Lines changed: 70 additions & 35 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c

Lines changed: 70 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2395,6 +2395,71 @@ static int amdgpu_pmops_restore(struct device *dev)
23952395
return amdgpu_device_resume(drm_dev, true);
23962396
}
23972397

2398+
static int amdgpu_runtime_idle_check_display(struct device *dev)
2399+
{
2400+
struct pci_dev *pdev = to_pci_dev(dev);
2401+
struct drm_device *drm_dev = pci_get_drvdata(pdev);
2402+
struct amdgpu_device *adev = drm_to_adev(drm_dev);
2403+
2404+
if (adev->mode_info.num_crtc) {
2405+
struct drm_connector *list_connector;
2406+
struct drm_connector_list_iter iter;
2407+
int ret = 0;
2408+
2409+
/* XXX: Return busy if any displays are connected to avoid
2410+
* possible display wakeups after runtime resume due to
2411+
* hotplug events in case any displays were connected while
2412+
* the GPU was in suspend. Remove this once that is fixed.
2413+
*/
2414+
mutex_lock(&drm_dev->mode_config.mutex);
2415+
drm_connector_list_iter_begin(drm_dev, &iter);
2416+
drm_for_each_connector_iter(list_connector, &iter) {
2417+
if (list_connector->status == connector_status_connected) {
2418+
ret = -EBUSY;
2419+
break;
2420+
}
2421+
}
2422+
drm_connector_list_iter_end(&iter);
2423+
mutex_unlock(&drm_dev->mode_config.mutex);
2424+
2425+
if (ret)
2426+
return ret;
2427+
2428+
if (amdgpu_device_has_dc_support(adev)) {
2429+
struct drm_crtc *crtc;
2430+
2431+
drm_for_each_crtc(crtc, drm_dev) {
2432+
drm_modeset_lock(&crtc->mutex, NULL);
2433+
if (crtc->state->active)
2434+
ret = -EBUSY;
2435+
drm_modeset_unlock(&crtc->mutex);
2436+
if (ret < 0)
2437+
break;
2438+
}
2439+
} else {
2440+
mutex_lock(&drm_dev->mode_config.mutex);
2441+
drm_modeset_lock(&drm_dev->mode_config.connection_mutex, NULL);
2442+
2443+
drm_connector_list_iter_begin(drm_dev, &iter);
2444+
drm_for_each_connector_iter(list_connector, &iter) {
2445+
if (list_connector->dpms == DRM_MODE_DPMS_ON) {
2446+
ret = -EBUSY;
2447+
break;
2448+
}
2449+
}
2450+
2451+
drm_connector_list_iter_end(&iter);
2452+
2453+
drm_modeset_unlock(&drm_dev->mode_config.connection_mutex);
2454+
mutex_unlock(&drm_dev->mode_config.mutex);
2455+
}
2456+
if (ret)
2457+
return ret;
2458+
}
2459+
2460+
return 0;
2461+
}
2462+
23982463
static int amdgpu_pmops_runtime_suspend(struct device *dev)
23992464
{
24002465
struct pci_dev *pdev = to_pci_dev(dev);
@@ -2407,6 +2472,10 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
24072472
return -EBUSY;
24082473
}
24092474

2475+
ret = amdgpu_runtime_idle_check_display(dev);
2476+
if (ret)
2477+
return ret;
2478+
24102479
/* wait for all rings to drain before suspending */
24112480
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
24122481
struct amdgpu_ring *ring = adev->rings[i];
@@ -2516,41 +2585,7 @@ static int amdgpu_pmops_runtime_idle(struct device *dev)
25162585
return -EBUSY;
25172586
}
25182587

2519-
if (amdgpu_device_has_dc_support(adev)) {
2520-
struct drm_crtc *crtc;
2521-
2522-
drm_for_each_crtc(crtc, drm_dev) {
2523-
drm_modeset_lock(&crtc->mutex, NULL);
2524-
if (crtc->state->active)
2525-
ret = -EBUSY;
2526-
drm_modeset_unlock(&crtc->mutex);
2527-
if (ret < 0)
2528-
break;
2529-
}
2530-
2531-
} else {
2532-
struct drm_connector *list_connector;
2533-
struct drm_connector_list_iter iter;
2534-
2535-
mutex_lock(&drm_dev->mode_config.mutex);
2536-
drm_modeset_lock(&drm_dev->mode_config.connection_mutex, NULL);
2537-
2538-
drm_connector_list_iter_begin(drm_dev, &iter);
2539-
drm_for_each_connector_iter(list_connector, &iter) {
2540-
if (list_connector->dpms == DRM_MODE_DPMS_ON) {
2541-
ret = -EBUSY;
2542-
break;
2543-
}
2544-
}
2545-
2546-
drm_connector_list_iter_end(&iter);
2547-
2548-
drm_modeset_unlock(&drm_dev->mode_config.connection_mutex);
2549-
mutex_unlock(&drm_dev->mode_config.mutex);
2550-
}
2551-
2552-
if (ret == -EBUSY)
2553-
DRM_DEBUG_DRIVER("failing to power off - crtc active\n");
2588+
ret = amdgpu_runtime_idle_check_display(dev);
25542589

25552590
pm_runtime_mark_last_busy(dev);
25562591
pm_runtime_autosuspend(dev);

0 commit comments

Comments
 (0)