From fe0f1e3bfdfeb53e18f1206aea4f40b9bd1f291c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 1 Oct 2020 18:16:35 +0300 Subject: [PATCH] drm/i915: Shut down displays gracefully on reboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement the pci .shutdown() hook in order to quiesce the hardware prior to reboot. The main purpose here is to turn all displays off. Some displays/other drivers tend to get confused if the state after reboot isn't exactly as they expected. One specific example was the Dell UP2414Q in MST mode. It would require me to pull the power cord after a reboot or else it would just not come back to life. Sadly I don't have that at hand anymore so not sure if it's still misbehaving without the graceful shutdown, or if we managed to fix something else since I last tested it. For good measure we do a gem suspend as well, so that we match the suspend flow more closely. Also stopping all DMA and whatnot is probably a good idea for kexec. I would expect that some kind of GT reset happens on normal reboot so probably not totally necessary there. v2: Use the pci .shutdown() hook instead of a reboot notifier (Lukas) Do the gem suspend for kexec (Chris) Cc: Lukas Wunner Cc: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201001151640.14590-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 16 ++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_pci.c | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f601f3ae0794..4e4527acda4d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1037,6 +1037,22 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv) drm_modeset_unlock_all(dev); } +void i915_driver_shutdown(struct drm_i915_private *i915) +{ + i915_gem_suspend(i915); + + drm_kms_helper_poll_disable(&i915->drm); + + drm_atomic_helper_shutdown(&i915->drm); + + intel_dp_mst_suspend(i915); + + intel_runtime_pm_disable_interrupts(i915); + intel_hpd_cancel_work(i915); + + intel_suspend_encoders(i915); +} + static bool suspend_to_idle(struct drm_i915_private *dev_priv) { #if IS_ENABLED(CONFIG_ACPI_SLEEP) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 72a9449b674e..31bc8455dfff 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1779,6 +1779,7 @@ extern const struct dev_pm_ops i915_pm_ops; int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent); void i915_driver_remove(struct drm_i915_private *i915); +void i915_driver_shutdown(struct drm_i915_private *i915); int i915_resume_switcheroo(struct drm_i915_private *i915); int i915_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 366ddfc8df6b..249730561b6c 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1090,11 +1090,19 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; } +static void i915_pci_shutdown(struct pci_dev *pdev) +{ + struct drm_i915_private *i915 = pci_get_drvdata(pdev); + + i915_driver_shutdown(i915); +} + static struct pci_driver i915_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, .probe = i915_pci_probe, .remove = i915_pci_remove, + .shutdown = i915_pci_shutdown, .driver.pm = &i915_pm_ops, };