diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 66f2acacd516..327e5fe7dfff 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1132,6 +1132,21 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) pci_disable_device(pdev); + return 0; + +fail: + enable_rpm_wakeref_asserts(rpm); + if (!dev_priv->uncore.user_forcewake_count) + intel_runtime_pm_driver_release(rpm); + + return ret; +} + +static int i915_drm_suspend_noirq(struct drm_device *dev, bool hibernation) +{ + struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + /* * During hibernation on some platforms the BIOS may try to access * the device even though it's already in D3 and hang the machine. So @@ -1152,13 +1167,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) pci_set_power_state(pdev, PCI_D3hot); return 0; - -fail: - enable_rpm_wakeref_asserts(rpm); - if (!dev_priv->uncore.user_forcewake_count) - intel_runtime_pm_driver_release(rpm); - - return ret; } int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, @@ -1177,7 +1185,15 @@ int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, if (error) return error; - return i915_drm_suspend_late(&i915->drm, false); + error = i915_drm_suspend_late(&i915->drm, false); + if (error) + return error; + + error = i915_drm_suspend_noirq(&i915->drm, false); + if (error) + return error; + + return 0; } static int i915_drm_resume(struct drm_device *dev) @@ -1283,23 +1299,6 @@ static int i915_drm_resume_early(struct drm_device *dev) * similar so that power domains can be employed. */ - /* - * Note that we need to set the power state explicitly, since we - * powered off the device during freeze and the PCI core won't power - * it back up for us during thaw. Powering off the device during - * freeze is not a hard requirement though, and during the - * suspend/resume phases the PCI core makes sure we get here with the - * device powered on. So in case we change our freeze logic and keep - * the device powered we can also remove the following set power state - * call. - */ - ret = pci_set_power_state(pdev, PCI_D0); - if (ret) { - drm_err(&dev_priv->drm, - "failed to set PCI D0 power state (%d)\n", ret); - return ret; - } - /* * Note that pci_enable_device() first enables any parent bridge * device and only then sets the power state for this device. The @@ -1337,11 +1336,16 @@ static int i915_drm_resume_early(struct drm_device *dev) int i915_driver_resume_switcheroo(struct drm_i915_private *i915) { + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); int ret; if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF) return 0; + ret = pci_set_power_state(pdev, PCI_D0); + if (ret) + return ret; + ret = i915_drm_resume_early(&i915->drm); if (ret) return ret; @@ -1398,6 +1402,16 @@ static int i915_pm_suspend_late(struct device *kdev) return i915_drm_suspend_late(&i915->drm, false); } +static int i915_pm_suspend_noirq(struct device *kdev) +{ + struct drm_i915_private *i915 = kdev_to_i915(kdev); + + if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF) + return 0; + + return i915_drm_suspend_noirq(&i915->drm, false); +} + static int i915_pm_poweroff_late(struct device *kdev) { struct drm_i915_private *i915 = kdev_to_i915(kdev); @@ -1408,6 +1422,16 @@ static int i915_pm_poweroff_late(struct device *kdev) return i915_drm_suspend_late(&i915->drm, true); } +static int i915_pm_poweroff_noirq(struct device *kdev) +{ + struct drm_i915_private *i915 = kdev_to_i915(kdev); + + if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF) + return 0; + + return i915_drm_suspend_noirq(&i915->drm, true); +} + static int i915_pm_resume_early(struct device *kdev) { struct drm_i915_private *i915 = kdev_to_i915(kdev); @@ -1673,6 +1697,7 @@ const struct dev_pm_ops i915_pm_ops = { .prepare = i915_pm_prepare, .suspend = i915_pm_suspend, .suspend_late = i915_pm_suspend_late, + .suspend_noirq = i915_pm_suspend_noirq, .resume_early = i915_pm_resume_early, .resume = i915_pm_resume, .complete = i915_pm_complete, @@ -1698,6 +1723,7 @@ const struct dev_pm_ops i915_pm_ops = { .thaw = i915_pm_thaw, .poweroff = i915_pm_suspend, .poweroff_late = i915_pm_poweroff_late, + .poweroff_noirq = i915_pm_poweroff_noirq, .restore_early = i915_pm_restore_early, .restore = i915_pm_restore,