static int intel_runtime_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = dev->dev_private; int ret = 0; if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev))) return -ENODEV; DRM_DEBUG_KMS("Resuming device\n"); WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); disable_rpm_wakeref_asserts(dev_priv); intel_opregion_notify_adapter(dev, PCI_D0); dev_priv->pm.suspended = false; if (intel_uncore_unclaimed_mmio(dev_priv)) DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n"); intel_guc_resume(dev); if (IS_GEN6(dev_priv)) intel_init_pch_refclk(dev); if (IS_BROXTON(dev)) ret = bxt_resume_prepare(dev_priv); else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_disable_pc8(dev_priv); else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) ret = vlv_resume_prepare(dev_priv, true); /* * No point of rolling back things in case of an error, as the best * we can do is to hope that things will still work (and disable RPM). */ i915_gem_init_swizzling(dev); gen6_update_ring_freq(dev); intel_runtime_pm_enable_interrupts(dev_priv); /* * On VLV/CHV display interrupts are part of the display * power well, so hpd is reinitialized from there. For * everyone else do it here. */ if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) intel_hpd_init(dev_priv); intel_enable_gt_powersave(dev); enable_rpm_wakeref_asserts(dev_priv); if (ret) DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret); else DRM_DEBUG_KMS("Device resumed\n"); return ret; }
static int i915_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = dev->dev_private; WARN_ON(!HAS_RUNTIME_PM(dev)); DRM_DEBUG_KMS("Suspending device\n"); i915_gem_release_all_mmaps(dev_priv); del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); dev_priv->pm.suspended = true; /* * current versions of firmware which depend on this opregion * notification have repurposed the D1 definition to mean * "runtime suspended" vs. what you would normally expect (D3) * to distinguish it from notifications that might be sent * via the suspend path. */ intel_opregion_notify_adapter(dev, PCI_D1); return 0; }
static int i915_runtime_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = dev->dev_private; WARN_ON(!HAS_RUNTIME_PM(dev)); DRM_DEBUG_KMS("Resuming device\n"); intel_opregion_notify_adapter(dev, PCI_D0); dev_priv->pm.suspended = false; return 0; }
static int intel_runtime_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = dev->dev_private; int ret; WARN_ON(!HAS_RUNTIME_PM(dev)); DRM_DEBUG_KMS("Resuming device\n"); intel_opregion_notify_adapter(dev, PCI_D0); dev_priv->pm.suspended = false; if (IS_GEN6(dev)) { ret = snb_runtime_resume(dev_priv); } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { ret = hsw_runtime_resume(dev_priv); } else if (IS_VALLEYVIEW(dev)) { ret = vlv_runtime_resume(dev_priv); } else { WARN_ON(1); ret = -ENODEV; } /* * No point of rolling back things in case of an error, as the best * we can do is to hope that things will still work (and disable RPM). */ i915_gem_init_swizzling(dev); gen6_update_ring_freq(dev); intel_runtime_pm_restore_interrupts(dev); intel_reset_gt_powersave(dev); if (ret) DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret); else DRM_DEBUG_KMS("Device resumed\n"); return ret; }
static int i915_drm_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; disable_rpm_wakeref_asserts(dev_priv); mutex_lock(&dev->struct_mutex); i915_gem_restore_gtt_mappings(dev); mutex_unlock(&dev->struct_mutex); i915_restore_state(dev); intel_opregion_setup(dev); intel_init_pch_refclk(dev); drm_mode_config_reset(dev); /* * Interrupts have to be enabled before any batches are run. If not the * GPU will hang. i915_gem_init_hw() will initiate batches to * update/restore the context. * * Modeset enabling in intel_modeset_init_hw() also needs working * interrupts. */ intel_runtime_pm_enable_interrupts(dev_priv); mutex_lock(&dev->struct_mutex); if (i915_gem_init_hw(dev)) { DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter); } mutex_unlock(&dev->struct_mutex); intel_guc_resume(dev); intel_modeset_init_hw(dev); spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display.hpd_irq_setup) dev_priv->display.hpd_irq_setup(dev); spin_unlock_irq(&dev_priv->irq_lock); intel_dp_mst_resume(dev); intel_display_resume(dev); /* * ... but also need to make sure that hotplug processing * doesn't cause havoc. Like in the driver load code we don't * bother with the tiny race here where we might loose hotplug * notifications. * */ intel_hpd_init(dev_priv); /* Config may have changed between suspend and resume */ drm_helper_hpd_irq_event(dev); intel_opregion_init(dev); intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false); mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_DONE; mutex_unlock(&dev_priv->modeset_restore_lock); intel_opregion_notify_adapter(dev, PCI_D0); drm_kms_helper_poll_enable(dev); enable_rpm_wakeref_asserts(dev_priv); return 0; }
static int i915_drm_suspend(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; pci_power_t opregion_target_state; int error; /* ignore lid events during suspend */ mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_SUSPENDED; mutex_unlock(&dev_priv->modeset_restore_lock); disable_rpm_wakeref_asserts(dev_priv); /* We do a lot of poking in a lot of registers, make sure they work * properly. */ intel_display_set_init_power(dev_priv, true); drm_kms_helper_poll_disable(dev); pci_save_state(dev->pdev); error = i915_gem_suspend(dev); if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); goto out; } intel_guc_suspend(dev); intel_suspend_gt_powersave(dev); intel_display_suspend(dev); intel_dp_mst_suspend(dev); intel_runtime_pm_disable_interrupts(dev_priv); intel_hpd_cancel_work(dev_priv); intel_suspend_encoders(dev_priv); intel_suspend_hw(dev); i915_gem_suspend_gtt_mappings(dev); i915_save_state(dev); opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold; intel_opregion_notify_adapter(dev, opregion_target_state); intel_uncore_forcewake_reset(dev, false); intel_opregion_fini(dev); intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true); dev_priv->suspend_count++; intel_display_set_init_power(dev_priv, false); if (HAS_CSR(dev_priv)) flush_work(&dev_priv->csr.work); out: enable_rpm_wakeref_asserts(dev_priv); return error; }
static int intel_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = dev->dev_private; int ret; if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev)))) return -ENODEV; if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev))) return -ENODEV; DRM_DEBUG_KMS("Suspending device\n"); /* * We could deadlock here in case another thread holding struct_mutex * calls RPM suspend concurrently, since the RPM suspend will wait * first for this RPM suspend to finish. In this case the concurrent * RPM resume will be followed by its RPM suspend counterpart. Still * for consistency return -EAGAIN, which will reschedule this suspend. */ if (!mutex_trylock(&dev->struct_mutex)) { DRM_DEBUG_KMS("device lock contention, deffering suspend\n"); /* * Bump the expiration timestamp, otherwise the suspend won't * be rescheduled. */ pm_runtime_mark_last_busy(device); return -EAGAIN; } disable_rpm_wakeref_asserts(dev_priv); /* * We are safe here against re-faults, since the fault handler takes * an RPM reference. */ i915_gem_release_all_mmaps(dev_priv); mutex_unlock(&dev->struct_mutex); cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); intel_guc_suspend(dev); intel_suspend_gt_powersave(dev); intel_runtime_pm_disable_interrupts(dev_priv); ret = intel_suspend_complete(dev_priv); if (ret) { DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret); intel_runtime_pm_enable_interrupts(dev_priv); enable_rpm_wakeref_asserts(dev_priv); return ret; } intel_uncore_forcewake_reset(dev, false); enable_rpm_wakeref_asserts(dev_priv); WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); if (intel_uncore_arm_unclaimed_mmio_detection(dev_priv)) DRM_ERROR("Unclaimed access detected prior to suspending\n"); dev_priv->pm.suspended = true; /* * FIXME: We really should find a document that references the arguments * used below! */ if (IS_BROADWELL(dev)) { /* * On Broadwell, if we use PCI_D1 the PCH DDI ports will stop * being detected, and the call we do at intel_runtime_resume() * won't be able to restore them. Since PCI_D3hot matches the * actual specification and appears to be working, use it. */ intel_opregion_notify_adapter(dev, PCI_D3hot); } else { /* * current versions of firmware which depend on this opregion * notification have repurposed the D1 definition to mean * "runtime suspended" vs. what you would normally expect (D3) * to distinguish it from notifications that might be sent via * the suspend path. */ intel_opregion_notify_adapter(dev, PCI_D1); } assert_forcewakes_inactive(dev_priv); DRM_DEBUG_KMS("Device suspended\n"); return 0; }
static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) { struct drm_i915_private *dev_priv = dev->dev_private; if (drm_core_check_feature(dev, DRIVER_MODESET) && restore_gtt_mappings) { mutex_lock(&dev->struct_mutex); i915_gem_restore_gtt_mappings(dev); mutex_unlock(&dev->struct_mutex); } i915_restore_state(dev); intel_opregion_setup(dev); /* KMS EnterVT equivalent */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_init_pch_refclk(dev); drm_mode_config_reset(dev); mutex_lock(&dev->struct_mutex); if (i915_gem_init_hw(dev)) { DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); atomic_set_mask(I915_WEDGED, &dev_priv->gpu_error.reset_counter); } mutex_unlock(&dev->struct_mutex); intel_runtime_pm_restore_interrupts(dev); intel_modeset_init_hw(dev); { unsigned long irqflags; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (dev_priv->display.hpd_irq_setup) dev_priv->display.hpd_irq_setup(dev); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } intel_dp_mst_resume(dev); drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, true); drm_modeset_unlock_all(dev); /* * ... but also need to make sure that hotplug processing * doesn't cause havoc. Like in the driver load code we don't * bother with the tiny race here where we might loose hotplug * notifications. * */ intel_hpd_init(dev); /* Config may have changed between suspend and resume */ drm_helper_hpd_irq_event(dev); } intel_opregion_init(dev); /* * The console lock can be pretty contented on resume due * to all the printk activity. Try to keep it out of the hot * path of resume if possible. */ if (console_trylock()) { intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING); console_unlock(); } else { schedule_work(&dev_priv->console_resume_work); } mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_DONE; mutex_unlock(&dev_priv->modeset_restore_lock); intel_opregion_notify_adapter(dev, PCI_D0); return 0; }
static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; pci_power_t opregion_target_state; /* ignore lid events during suspend */ mutex_lock(&dev_priv->modeset_restore_lock); dev_priv->modeset_restore = MODESET_SUSPENDED; mutex_unlock(&dev_priv->modeset_restore_lock); /* We do a lot of poking in a lot of registers, make sure they work * properly. */ intel_display_set_init_power(dev_priv, true); drm_kms_helper_poll_disable(dev); pci_save_state(dev->pdev); /* If KMS is active, we do the leavevt stuff here */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { int error; error = i915_gem_suspend(dev); if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); return error; } /* * Disable CRTCs directly since we want to preserve sw state * for _thaw. Also, power gate the CRTC power wells. */ drm_modeset_lock_all(dev); for_each_crtc(dev, crtc) intel_crtc_control(crtc, false); drm_modeset_unlock_all(dev); intel_dp_mst_suspend(dev); flush_delayed_work(&dev_priv->rps.delayed_resume_work); intel_runtime_pm_disable_interrupts(dev); intel_suspend_gt_powersave(dev); intel_modeset_suspend_hw(dev); } i915_gem_suspend_gtt_mappings(dev); i915_save_state(dev); opregion_target_state = PCI_D3cold; #if IS_ENABLED(CONFIG_ACPI_SLEEP) if (acpi_target_system_state() < ACPI_STATE_S3) opregion_target_state = PCI_D1; #endif intel_opregion_notify_adapter(dev, opregion_target_state); intel_uncore_forcewake_reset(dev, false); intel_opregion_fini(dev); console_lock(); intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED); console_unlock(); dev_priv->suspend_count++; intel_display_set_init_power(dev_priv, false); return 0; }
static int intel_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = dev->dev_private; int ret; if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev)))) return -ENODEV; WARN_ON(!HAS_RUNTIME_PM(dev)); assert_force_wake_inactive(dev_priv); DRM_DEBUG_KMS("Suspending device\n"); /* * We could deadlock here in case another thread holding struct_mutex * calls RPM suspend concurrently, since the RPM suspend will wait * first for this RPM suspend to finish. In this case the concurrent * RPM resume will be followed by its RPM suspend counterpart. Still * for consistency return -EAGAIN, which will reschedule this suspend. */ if (!mutex_trylock(&dev->struct_mutex)) { DRM_DEBUG_KMS("device lock contention, deffering suspend\n"); /* * Bump the expiration timestamp, otherwise the suspend won't * be rescheduled. */ pm_runtime_mark_last_busy(device); return -EAGAIN; } /* * We are safe here against re-faults, since the fault handler takes * an RPM reference. */ i915_gem_release_all_mmaps(dev_priv); mutex_unlock(&dev->struct_mutex); /* * rps.work can't be rearmed here, since we get here only after making * sure the GPU is idle and the RPS freq is set to the minimum. See * intel_mark_idle(). */ cancel_work_sync(&dev_priv->rps.work); intel_runtime_pm_disable_interrupts(dev); if (IS_GEN6(dev)) { ret = 0; } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { ret = hsw_runtime_suspend(dev_priv); } else if (IS_VALLEYVIEW(dev)) { ret = vlv_runtime_suspend(dev_priv); } else { ret = -ENODEV; WARN_ON(1); } if (ret) { DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret); intel_runtime_pm_restore_interrupts(dev); return ret; } del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); dev_priv->pm.suspended = true; /* * current versions of firmware which depend on this opregion * notification have repurposed the D1 definition to mean * "runtime suspended" vs. what you would normally expect (D3) * to distinguish it from notifications that might be sent * via the suspend path. */ intel_opregion_notify_adapter(dev, PCI_D1); DRM_DEBUG_KMS("Device suspended\n"); return 0; }