Commit cb17aa52 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-fixes-2018-03-27' of...

Merge tag 'drm-intel-next-fixes-2018-03-27' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

- Display fixes for booting with MST hub lid closed and display
  freezing after hibernation (fd.o bugs 105470 & 105196)
- Fix for a very rare interrupt handling race resulting in GPU hang

* tag 'drm-intel-next-fixes-2018-03-27' of git://anongit.freedesktop.org/drm/drm-intel:
  drm/i915: Fix hibernation with ACPI S0 target state
  drm/i915/execlists: Use a locked clear_bit() for synchronisation with interrupt
  drm/i915: Specify which engines to reset following semaphore/event lockups
  drm/i915/dp: Write to SET_POWER dpcd to enable MST hub.
parents 2b4f44ee 300efa9e
...@@ -1611,15 +1611,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) ...@@ -1611,15 +1611,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev; struct pci_dev *pdev = dev_priv->drm.pdev;
bool fw_csr;
int ret; int ret;
disable_rpm_wakeref_asserts(dev_priv); disable_rpm_wakeref_asserts(dev_priv);
intel_display_set_init_power(dev_priv, false); intel_display_set_init_power(dev_priv, false);
fw_csr = !IS_GEN9_LP(dev_priv) && !hibernation &&
suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
/* /*
* In case of firmware assisted context save/restore don't manually * In case of firmware assisted context save/restore don't manually
* deinit the power domains. This also means the CSR/DMC firmware will * deinit the power domains. This also means the CSR/DMC firmware will
...@@ -1627,8 +1624,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) ...@@ -1627,8 +1624,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
* also enable deeper system power states that would be blocked if the * also enable deeper system power states that would be blocked if the
* firmware was inactive. * firmware was inactive.
*/ */
if (!fw_csr) if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
dev_priv->csr.dmc_payload == NULL) {
intel_power_domains_suspend(dev_priv); intel_power_domains_suspend(dev_priv);
dev_priv->power_domains_suspended = true;
}
ret = 0; ret = 0;
if (IS_GEN9_LP(dev_priv)) if (IS_GEN9_LP(dev_priv))
...@@ -1640,8 +1640,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) ...@@ -1640,8 +1640,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
if (ret) { if (ret) {
DRM_ERROR("Suspend complete failed: %d\n", ret); DRM_ERROR("Suspend complete failed: %d\n", ret);
if (!fw_csr) if (dev_priv->power_domains_suspended) {
intel_power_domains_init_hw(dev_priv, true); intel_power_domains_init_hw(dev_priv, true);
dev_priv->power_domains_suspended = false;
}
goto out; goto out;
} }
...@@ -1662,8 +1664,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) ...@@ -1662,8 +1664,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
if (!(hibernation && INTEL_GEN(dev_priv) < 6)) if (!(hibernation && INTEL_GEN(dev_priv) < 6))
pci_set_power_state(pdev, PCI_D3hot); pci_set_power_state(pdev, PCI_D3hot);
dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
out: out:
enable_rpm_wakeref_asserts(dev_priv); enable_rpm_wakeref_asserts(dev_priv);
...@@ -1830,8 +1830,7 @@ static int i915_drm_resume_early(struct drm_device *dev) ...@@ -1830,8 +1830,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
intel_uncore_resume_early(dev_priv); intel_uncore_resume_early(dev_priv);
if (IS_GEN9_LP(dev_priv)) { if (IS_GEN9_LP(dev_priv)) {
if (!dev_priv->suspended_to_idle) gen9_sanitize_dc_state(dev_priv);
gen9_sanitize_dc_state(dev_priv);
bxt_disable_dc9(dev_priv); bxt_disable_dc9(dev_priv);
} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
hsw_disable_pc8(dev_priv); hsw_disable_pc8(dev_priv);
...@@ -1839,8 +1838,7 @@ static int i915_drm_resume_early(struct drm_device *dev) ...@@ -1839,8 +1838,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
intel_uncore_sanitize(dev_priv); intel_uncore_sanitize(dev_priv);
if (IS_GEN9_LP(dev_priv) || if (dev_priv->power_domains_suspended)
!(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
intel_power_domains_init_hw(dev_priv, true); intel_power_domains_init_hw(dev_priv, true);
else else
intel_display_set_init_power(dev_priv, true); intel_display_set_init_power(dev_priv, true);
...@@ -1850,7 +1848,7 @@ static int i915_drm_resume_early(struct drm_device *dev) ...@@ -1850,7 +1848,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
enable_rpm_wakeref_asserts(dev_priv); enable_rpm_wakeref_asserts(dev_priv);
out: out:
dev_priv->suspended_to_idle = false; dev_priv->power_domains_suspended = false;
return ret; return ret;
} }
......
...@@ -2119,7 +2119,7 @@ struct drm_i915_private { ...@@ -2119,7 +2119,7 @@ struct drm_i915_private {
u32 bxt_phy_grc; u32 bxt_phy_grc;
u32 suspend_count; u32 suspend_count;
bool suspended_to_idle; bool power_domains_suspended;
struct i915_suspend_saved_registers regfile; struct i915_suspend_saved_registers regfile;
struct vlv_s0ix_state vlv_s0ix_state; struct vlv_s0ix_state vlv_s0ix_state;
......
...@@ -831,7 +831,8 @@ static void execlists_submission_tasklet(unsigned long data) ...@@ -831,7 +831,8 @@ static void execlists_submission_tasklet(unsigned long data)
struct drm_i915_private *dev_priv = engine->i915; struct drm_i915_private *dev_priv = engine->i915;
bool fw = false; bool fw = false;
/* We can skip acquiring intel_runtime_pm_get() here as it was taken /*
* We can skip acquiring intel_runtime_pm_get() here as it was taken
* on our behalf by the request (see i915_gem_mark_busy()) and it will * on our behalf by the request (see i915_gem_mark_busy()) and it will
* not be relinquished until the device is idle (see * not be relinquished until the device is idle (see
* i915_gem_idle_work_handler()). As a precaution, we make sure * i915_gem_idle_work_handler()). As a precaution, we make sure
...@@ -840,7 +841,8 @@ static void execlists_submission_tasklet(unsigned long data) ...@@ -840,7 +841,8 @@ static void execlists_submission_tasklet(unsigned long data)
*/ */
GEM_BUG_ON(!dev_priv->gt.awake); GEM_BUG_ON(!dev_priv->gt.awake);
/* Prefer doing test_and_clear_bit() as a two stage operation to avoid /*
* Prefer doing test_and_clear_bit() as a two stage operation to avoid
* imposing the cost of a locked atomic transaction when submitting a * imposing the cost of a locked atomic transaction when submitting a
* new request (outside of the context-switch interrupt). * new request (outside of the context-switch interrupt).
*/ */
...@@ -856,17 +858,10 @@ static void execlists_submission_tasklet(unsigned long data) ...@@ -856,17 +858,10 @@ static void execlists_submission_tasklet(unsigned long data)
execlists->csb_head = -1; /* force mmio read of CSB ptrs */ execlists->csb_head = -1; /* force mmio read of CSB ptrs */
} }
/* The write will be ordered by the uncached read (itself /* Clear before reading to catch new interrupts */
* a memory barrier), so we do not need another in the form clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
* of a locked instruction. The race between the interrupt smp_mb__after_atomic();
* handler and the split test/clear is harmless as we order
* our clear before the CSB read. If the interrupt arrived
* first between the test and the clear, we read the updated
* CSB and clear the bit. If the interrupt arrives as we read
* the CSB or later (i.e. after we had cleared the bit) the bit
* is set and we do a new loop.
*/
__clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
if (unlikely(execlists->csb_head == -1)) { /* following a reset */ if (unlikely(execlists->csb_head == -1)) { /* following a reset */
if (!fw) { if (!fw) {
intel_uncore_forcewake_get(dev_priv, intel_uncore_forcewake_get(dev_priv,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment