All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] Haswell runtime PM support + D3
@ 2013-11-21 15:47 Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8 Paulo Zanoni
                   ` (18 more replies)
  0 siblings, 19 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Hi

This series adds Haswell runtime PM support, which will put the graphics device
in D3 state, saving a lot of power. Fore more information, see the previous
cover letter:
  http://lists.freedesktop.org/archives/intel-gfx/2013-October/034910.html

What changes from the previous series?

Previously, the runtime PM test suite was separate from the PC8 test suite. Now,
pm_pc8.c is able to recognize both features, so we can run all tests on both
PC8-only or PC8+D3 cases. This code is all upstream. One of the consequences is
that some of the new D3 tests triggered bugs in cases where we only had PC8, so
patches 2, 3 and 4 solve these problems.

Patches 5-14 add the runtime PM support on Haswell. They are basically the same
thing as before, with a few new additions to catch the bugs I could reproduce
with the test suite. The other difference is that even though runtime PM is not
enabled by default, all you need to enable it is to "echo auto" to a sysfs file
(or just run powertop and switch things to "good"). No more Kernel parameter is
necessary. I could add it back if we want, no problem.

Patches 15-19 are not really part of the runtime PM feature, but they are on top
of that work, so I decided to send them anyway. While writing patch 9 I
identified some problems on the VDD code, so I decided to fix them on patches
15-19. The big benefit is that we avoid some msleep() calls with these patches,
so all eDP modesets get faster.

In short:
  - Patches 1-4: fixes for PC8 code
  - Patches 5-14: add the runtime PM support
  - Patches 15-19: some fixes for eDP VDD on top of everything

What are we still missing?

 - Merge PC8 and runtime D3: since PC8 without D3 doesn't make much sense, I
   plan to merge both features so they become a single thing. This will also
   make it easier for other platforms to add runtime PM support.
 - Support for PC8/D3 on DPMS. Jesse already started studying this problem, but
   there's a lot of rework we need to do on the modeset code before we reach
   this problem.
 - Support other platforms: adding support for another platform (e.g., VLV or
   IVB) will help us identify the code that needs to be shared and the code
   that's gen-specific.

Still, none of these missing things is a blocker: IMHO we can merge the Haswell
support now and worry about the other features later.

Thanks,
Paulo


Paulo Zanoni (19):
  drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8
  drm/i915: use the correct force_wake function at the PC8 code
  drm/i915: get a PC8 reference when enabling the power well
  drm/i915: get/put PC8 when we get/put a CRTC
  drm/i915: add initial Runtime PM functions
  drm/i915: do adapter power state notification at runtime PM
  drm/i915: add runtime put/get calls at the basic places
  drm/i915: add some runtime PM get/put calls
  drm/i915: get a runtime PM reference when the panel VDD is on
  drm/i915: do not assert DE_PCH_EVENT_IVB enabled
  drm/i915: disable interrupts when enabling PC8
  drm/i915: release the GTT mmaps when going into D3
  drm: do not steal the display if we have a master
  drm/i915: add runtime PM support on Haswell
  drm/i915: don't enable VDD just to enable the panel
  drm/i915: don't touch the VDD when disabling the panel
  drm/i915: fix VDD override off wait
  drm/i915: save some time when waiting the eDP timings
  drm/i915: init the DP panel power seq regs earlier

 drivers/gpu/drm/drm_fb_helper.c            |  6 +++
 drivers/gpu/drm/i915/i915_debugfs.c        | 45 ++++++++++++++++--
 drivers/gpu/drm/i915/i915_dma.c            |  6 +++
 drivers/gpu/drm/i915/i915_drv.c            | 46 ++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h            |  8 ++++
 drivers/gpu/drm/i915/i915_gem.c            | 61 ++++++++++++++++--------
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 +++
 drivers/gpu/drm/i915/i915_irq.c            | 32 ++++++-------
 drivers/gpu/drm/i915/i915_sysfs.c          | 14 +++++-
 drivers/gpu/drm/i915/intel_ddi.c           |  3 --
 drivers/gpu/drm/i915/intel_display.c       | 41 +++++++++++++---
 drivers/gpu/drm/i915/intel_dp.c            | 75 +++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_drv.h           |  7 +++
 drivers/gpu/drm/i915/intel_panel.c         |  3 ++
 drivers/gpu/drm/i915/intel_pm.c            | 70 +++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_uncore.c        | 13 ++++++
 16 files changed, 366 insertions(+), 70 deletions(-)

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 97+ messages in thread

* [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-29 11:11   ` Rodrigo Vivi
  2013-11-21 15:47 ` [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code Paulo Zanoni
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

We already have some checks and shouldn't be reaching these places on
!HAS_PC8 platforms, but add a WARN,  just in case.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e85d838..5566de5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6623,6 +6623,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
 	struct drm_device *dev = dev_priv->dev;
 	uint32_t val;
 
+	WARN_ON(!HAS_PC8(dev));
+
 	if (dev_priv->pc8.enabled)
 		return;
 
@@ -6668,6 +6670,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
 	if (dev_priv->pc8.disable_count != 1)
 		return;
 
+	WARN_ON(!HAS_PC8(dev));
+
 	cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
 	if (!dev_priv->pc8.enabled)
 		return;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8 Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-27 19:57   ` Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well Paulo Zanoni
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, stable

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

When I submitted the first patch adding these force wake functions,
Chris Wilson observed that I was using the wrong functions, so I sent
a second version of the patch to correct this problem. The problem is
that v1 was merged instead of v2.

I was able to notice the problem when running the
debugfs-forcewake-user subtest of pm_pc8 from intel-gpu-tools.

Cc: stable@vger.kernel.org
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5566de5..5ea32a8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6578,7 +6578,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
 	/* Make sure we're not on PC8 state before disabling PC8, otherwise
 	 * we'll hang the machine! */
-	dev_priv->uncore.funcs.force_wake_get(dev_priv);
+	gen6_gt_force_wake_get(dev_priv);
 
 	if (val & LCPLL_POWER_DOWN_ALLOW) {
 		val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6612,7 +6612,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 			DRM_ERROR("Switching back to LCPLL failed\n");
 	}
 
-	dev_priv->uncore.funcs.force_wake_put(dev_priv);
+	gen6_gt_force_wake_put(dev_priv);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8 Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-27 19:59   ` Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC Paulo Zanoni
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

In the current code, at haswell_modeset_global_resources, first we
decide if we want to enable/disable the power well, then we decide if
we want to enable/disable PC8. On the case where we're enabling PC8
this works fine, but on the case where we disable PC8 due to a non-eDP
monitor being enabled, we first enable the power well and then disable
PC8. Although wrong, this doesn't seem to be causing any problems now,
and we don't even see anything in dmesg. But the patches for runtime
D3 turn this problem into a real bug, so we need to fix it.

This fixes the "modeset-non-lpsp" test from both "pc8" and
"runtime_pm" tests from intel-gpu-tools.

v2: - Rebase (i915_disable_power_well).

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 04e9863..6bd0fc6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5652,6 +5652,8 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 	unsigned long irqflags;
 	uint32_t tmp;
 
+	WARN_ON(dev_priv->pc8.enabled);
+
 	tmp = I915_READ(HSW_PWR_WELL_DRIVER);
 	is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
 	enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
@@ -5711,16 +5713,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 static void __intel_power_well_get(struct drm_device *dev,
 				   struct i915_power_well *power_well)
 {
-	if (!power_well->count++)
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!power_well->count++) {
+		hsw_disable_package_c8(dev_priv);
 		__intel_set_power_well(dev, true);
+	}
 }
 
 static void __intel_power_well_put(struct drm_device *dev,
 				   struct i915_power_well *power_well)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
 	WARN_ON(!power_well->count);
-	if (!--power_well->count && i915_disable_power_well)
+	if (!--power_well->count && i915_disable_power_well) {
 		__intel_set_power_well(dev, false);
+		hsw_enable_package_c8(dev_priv);
+	}
 }
 
 void intel_display_power_get(struct drm_device *dev,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (2 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-21 16:12   ` Chris Wilson
  2013-12-04  9:01   ` Daniel Vetter
  2013-11-21 15:47 ` [PATCH 05/19] drm/i915: add initial Runtime PM functions Paulo Zanoni
                   ` (14 subsequent siblings)
  18 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Currently, PC8 is enabled at modeset_global_resources, which is called
after intel_modeset_update_state. Due to this, there's a small race
condition on the case where we start enabling PC8, then do a modeset
while PC8 is still being enabled. The racing condition triggers a WARN
because intel_modeset_update_state will mark the CRTC as enabled, then
the thread that's still enabling PC8 might look at the data structure
and think that PC8 is being enabled while a pipe is enabled. Despite
the WARN, this is not really a bug since we'll wait for the
PC8-enabling thread to finish when we call modeset_global_resources.

So this patch makes sure we get/put PC8 before we update
drm_crtc->enabled, because if a get() call triggers a PC8 disable,
we'll call cancel_delayed_work_sync(), which will wait for the thread
that's enabling PC8, then, after this, we'll disable PC8.

The side-effect benefit of this patch is that we have a nice place to
track enabled/disabled CRTCs, so we may want to move some code from
modeset_global_resources to intel_crtc_set_state in the future.

The problem fixed by this patch can be reproduced by the
modeset-lpsp-stress-no-wait subtest from the pc8 test of
intel-gpu-tools.

v2: - No need for pc8.lock since we already have
      cancel_delayed_work_sync().

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5ea32a8..846f2de 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9124,6 +9124,24 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
 	return false;
 }
 
+/* Sets crtc->base.enabled and gets/puts whatever resources are needed by the
+ * CRTC. */
+static void intel_crtc_set_state(struct intel_crtc *crtc, bool enabled)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (enabled == crtc->base.enabled)
+		return;
+
+	if (enabled)
+		hsw_disable_package_c8(dev_priv);
+	else
+		hsw_enable_package_c8(dev_priv);
+
+	crtc->base.enabled = enabled;
+}
+
 static void
 intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 {
@@ -9147,7 +9165,8 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 	/* Update computed state. */
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
 			    base.head) {
-		intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
+		intel_crtc_set_state(intel_crtc,
+				     intel_crtc_in_use(&intel_crtc->base));
 	}
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -10956,7 +10975,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 		}
 
 		WARN_ON(crtc->active);
-		crtc->base.enabled = false;
+		intel_crtc_set_state(crtc, false);
 	}
 
 	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
@@ -10983,7 +11002,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 			      crtc->base.enabled ? "enabled" : "disabled",
 			      crtc->active ? "enabled" : "disabled");
 
-		crtc->base.enabled = crtc->active;
+		intel_crtc_set_state(crtc, crtc->active);
 
 		/* Because we only establish the connector -> encoder ->
 		 * crtc links if something is active, this means the
@@ -11080,7 +11099,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 		crtc->active = dev_priv->display.get_pipe_config(crtc,
 								 &crtc->config);
 
-		crtc->base.enabled = crtc->active;
+		intel_crtc_set_state(crtc, crtc->active);
 		crtc->primary_enabled = crtc->active;
 
 		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (3 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-27 20:10   ` Paulo Zanoni
  2013-12-02 12:23   ` Imre Deak
  2013-11-21 15:47 ` [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM Paulo Zanoni
                   ` (13 subsequent siblings)
  18 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This patch adds the initial infrastructure to allow a Runtime PM
implementation that sets the device to its D3 state. The patch just
adds the necessary callbacks and the initial infrastructure.

We still don't have any platform that actually uses this
infrastructure, we still don't call get/put in all the places we need
to, and we don't have any function to save/restore the state of the
registers. This is not a problem since no platform uses the code added
by this patch. We have a few people simultaneously working on runtime
PM, so this initial code could help everybody make their plans.

V2: - Move some functions to intel_pm.c
    - Remove useless pm_runtime_allow() call at init
    - Remove useless pm_runtime_mark_last_busy() call at get
    - Use pm_runtime_get_sync() instead of 2 calls
    - Add a WARN to check if we're really awake

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
 drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
 drivers/gpu/drm/i915/intel_drv.h    |  4 +++
 drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
 6 files changed, 124 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 25acbb5..0ce9e38 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -42,6 +42,8 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -1664,6 +1666,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (IS_GEN5(dev))
 		intel_gpu_ips_init(dev_priv);
 
+	intel_init_runtime_pm(dev_priv);
+
 	return 0;
 
 out_power_well:
@@ -1704,6 +1708,8 @@ int i915_driver_unload(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	intel_fini_runtime_pm(dev_priv);
+
 	intel_gpu_ips_teardown();
 
 	if (HAS_POWER_WELL(dev)) {
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c2e00ed..d7ff095 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -500,6 +500,8 @@ static int i915_drm_freeze(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* ignore lid events during suspend */
 	mutex_lock(&dev_priv->modeset_restore_lock);
 	dev_priv->modeset_restore = MODESET_SUSPENDED;
@@ -684,6 +686,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
 	mutex_lock(&dev_priv->modeset_restore_lock);
 	dev_priv->modeset_restore = MODESET_DONE;
 	mutex_unlock(&dev_priv->modeset_restore_lock);
+
+	intel_runtime_pm_put(dev_priv);
 	return error;
 }
 
@@ -898,6 +902,42 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 }
 
+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");
+
+	dev_priv->pm.suspended = true;
+
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, PCI_D3cold);
+
+	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");
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	dev_priv->pm.suspended = false;
+
+	return 0;
+}
+
 static const struct dev_pm_ops i915_pm_ops = {
 	.suspend = i915_pm_suspend,
 	.resume = i915_pm_resume,
@@ -905,6 +945,8 @@ static const struct dev_pm_ops i915_pm_ops = {
 	.thaw = i915_pm_thaw,
 	.poweroff = i915_pm_poweroff,
 	.restore = i915_pm_resume,
+	.runtime_suspend = i915_runtime_suspend,
+	.runtime_resume = i915_runtime_resume,
 };
 
 static const struct vm_operations_struct i915_gem_vm_ops = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 14f250a..3877a68 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1275,6 +1275,10 @@ struct i915_package_c8 {
 	} regsave;
 };
 
+struct i915_runtime_pm {
+	bool suspended;
+};
+
 enum intel_pipe_crc_source {
 	INTEL_PIPE_CRC_SOURCE_NONE,
 	INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -1505,6 +1509,8 @@ typedef struct drm_i915_private {
 
 	struct i915_package_c8 pc8;
 
+	struct i915_runtime_pm pm;
+
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
 	 * here! */
 	struct i915_dri1_state dri1;
@@ -1830,6 +1836,7 @@ struct drm_i915_file_private {
 #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_PC8(dev)		(IS_HASWELL(dev)) /* XXX HSW:ULX */
+#define HAS_RUNTIME_PM(dev)	false
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0231281..5596498 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -856,6 +856,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6bd0fc6..ef5e274 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -31,6 +31,7 @@
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
 #include <drm/i915_powerwell.h>
+#include <linux/pm_runtime.h>
 
 /**
  * RC6 is a special power stage which allows the GPU to enter an very
@@ -5878,6 +5879,61 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
 	hsw_enable_package_c8(dev_priv);
 }
 
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_get_sync(device);
+	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
+}
+
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_mark_last_busy(device);
+	pm_runtime_put_autosuspend(device);
+}
+
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	dev_priv->pm.suspended = false;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_set_active(device);
+	pm_runtime_enable(device);
+
+	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
+	pm_runtime_mark_last_busy(device);
+	pm_runtime_use_autosuspend(device);
+}
+
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	/* Make sure we're not suspended first. */
+	pm_runtime_get_sync(device);
+	pm_runtime_disable(device);
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index eac5661..ddd9084 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -346,6 +346,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
 	}
 }
 
+static void
+assert_device_not_suspended(struct drm_i915_private *dev_priv)
+{
+	WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
+	     "Device suspended\n");
+}
+
 #define REG_READ_HEADER(x) \
 	unsigned long irqflags; \
 	u##x val = 0; \
@@ -438,6 +445,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
+	assert_device_not_suspended(dev_priv); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	if (unlikely(__fifo_ret)) { \
 		gen6_gt_check_fifodbg(dev_priv); \
@@ -453,6 +461,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
+	assert_device_not_suspended(dev_priv); \
 	hsw_unclaimed_reg_clear(dev_priv, reg); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	if (unlikely(__fifo_ret)) { \
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (4 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 05/19] drm/i915: add initial Runtime PM functions Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-21 16:14   ` Chris Wilson
  2013-11-21 15:47 ` [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places Paulo Zanoni
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula, Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Now that we are actually setting the device to the D3 state, we should
issue the notification.

Jani originally wrote a similar patch for PC8, but then we discovered
that we were not really changing the PCI D states when
enabling/disabling PC8, so we had to postpone his patch.

Cc: Jani Nikula <jani.nikula@intel.com>
Credits-to: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d7ff095..b133836 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -914,6 +914,7 @@ static int i915_runtime_suspend(struct device *device)
 
 	dev_priv->pm.suspended = true;
 
+	intel_opregion_notify_adapter(dev, PCI_D3cold);
 	pci_save_state(pdev);
 	pci_set_power_state(pdev, PCI_D3cold);
 
@@ -932,6 +933,7 @@ static int i915_runtime_resume(struct device *device)
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
+	intel_opregion_notify_adapter(dev, PCI_D0);
 
 	dev_priv->pm.suspended = false;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (5 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-21 16:07   ` Chris Wilson
  2013-11-21 15:47 ` [PATCH 08/19] drm/i915: add some runtime PM get/put calls Paulo Zanoni
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

If I add code to enable runtime PM on my Haswell machine, start a
desktop environment, then enable runtime PM, these functions will
complain that they're trying to read/write registers while the
graphics card is suspended.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c            | 53 +++++++++++++++++++-----------
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 ++++
 drivers/gpu/drm/i915/i915_irq.c            |  6 ++++
 3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 40d9dcf..94c2a38 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1377,36 +1377,38 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	pgoff_t page_offset;
 	unsigned long pfn;
-	int ret = 0;
+	int rc = 0, ret;
 	bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* We don't use vmf->pgoff since that has the fake offset */
 	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
 		PAGE_SHIFT;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
+	rc = i915_mutex_lock_interruptible(dev);
+	if (rc)
 		goto out;
 
 	trace_i915_gem_object_fault(obj, page_offset, true, write);
 
 	/* Access to snoopable pages through the GTT is incoherent. */
 	if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) {
-		ret = -EINVAL;
+		rc = -EINVAL;
 		goto unlock;
 	}
 
 	/* Now bind it into the GTT if needed */
-	ret = i915_gem_obj_ggtt_pin(obj,  0, true, false);
-	if (ret)
+	rc = i915_gem_obj_ggtt_pin(obj,  0, true, false);
+	if (rc)
 		goto unlock;
 
-	ret = i915_gem_object_set_to_gtt_domain(obj, write);
-	if (ret)
+	rc = i915_gem_object_set_to_gtt_domain(obj, write);
+	if (rc)
 		goto unpin;
 
-	ret = i915_gem_object_get_fence(obj);
-	if (ret)
+	rc = i915_gem_object_get_fence(obj);
+	if (rc)
 		goto unpin;
 
 	obj->fault_mappable = true;
@@ -1416,19 +1418,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	pfn += page_offset;
 
 	/* Finally, remap it using the new GTT offset */
-	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+	rc = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 unpin:
 	i915_gem_object_unpin(obj);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 out:
-	switch (ret) {
+	switch (rc) {
 	case -EIO:
 		/* If this -EIO is due to a gpu hang, give the reset code a
 		 * chance to clean up the mess. Otherwise return the proper
 		 * SIGBUS. */
-		if (i915_terminally_wedged(&dev_priv->gpu_error))
-			return VM_FAULT_SIGBUS;
+		if (i915_terminally_wedged(&dev_priv->gpu_error)) {
+			ret = VM_FAULT_SIGBUS;
+			break;
+		}
 	case -EAGAIN:
 		/*
 		 * EAGAIN means the gpu is hung and we'll wait for the error
@@ -1443,15 +1447,22 @@ out:
 		 * EBUSY is ok: this just means that another thread
 		 * already did the job.
 		 */
-		return VM_FAULT_NOPAGE;
+		ret = VM_FAULT_NOPAGE;
+		break;
 	case -ENOMEM:
-		return VM_FAULT_OOM;
+		ret = VM_FAULT_OOM;
+		break;
 	case -ENOSPC:
-		return VM_FAULT_SIGBUS;
+		ret = VM_FAULT_SIGBUS;
+		break;
 	default:
-		WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
-		return VM_FAULT_SIGBUS;
+		WARN_ONCE(rc, "unhandled error in i915_gem_fault: %i\n", rc);
+		ret = VM_FAULT_SIGBUS;
+		break;
 	}
+
+	intel_runtime_pm_put(dev_priv);
+	return ret;
 }
 
 /**
@@ -4165,6 +4176,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct i915_vma *vma, *next;
 
+	intel_runtime_pm_get(dev_priv);
+
 	trace_i915_gem_object_destroy(obj);
 
 	if (obj->phys_obj)
@@ -4209,6 +4222,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 
 	kfree(obj->bit_17);
 	i915_gem_object_free(obj);
+
+	intel_runtime_pm_put(dev_priv);
 }
 
 struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 885d595..2c35a9d 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1092,6 +1092,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		}
 	}
 
+	intel_runtime_pm_get(dev_priv);
+
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		goto pre_mutex_err;
@@ -1226,6 +1228,10 @@ err:
 
 pre_mutex_err:
 	kfree(cliprects);
+
+	/* intel_gpu_busy should also get a ref, so it will free when the device
+	 * is really idle. */
+	intel_runtime_pm_put(dev_priv);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2715600..70c4cef 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2477,6 +2477,12 @@ static void i915_hangcheck_elapsed(unsigned long data)
 	if (!i915_enable_hangcheck)
 		return;
 
+	/* Just postpone in case we're completely idle... */
+	if (dev_priv->pm.suspended) {
+		i915_queue_hangcheck(dev);
+		return;
+	}
+
 	for_each_ring(ring, dev_priv, i) {
 		u32 seqno, acthd;
 		bool busy = true;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 08/19] drm/i915: add some runtime PM get/put calls
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (6 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-27 20:21   ` Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on Paulo Zanoni
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

These are needed when we cat the debugfs and sysfs files.

V2: - Rebase
V3: - Rebase

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_sysfs.c   | 14 ++++++++++--
 drivers/gpu/drm/i915/intel_dp.c     | 11 +++++++--
 drivers/gpu/drm/i915/intel_panel.c  |  3 +++
 drivers/gpu/drm/i915/intel_uncore.c |  4 ++++
 5 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d1491f8..a1cb6fa 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	for_each_ring(ring, dev_priv, i)
 		i915_ring_seqno_info(m, ring);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	if (INTEL_INFO(dev)->gen >= 8) {
 		int i;
@@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 		}
 		i915_ring_seqno_info(m, ring);
 	}
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	crstanddelay = I915_READ16(CRSTANDVID);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
@@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	int ret;
+	int ret = 0;
+
+	intel_runtime_pm_get(dev_priv);
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
@@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 		/* RPSTAT1 is in the GT power well */
 		ret = mutex_lock_interruptible(&dev->struct_mutex);
 		if (ret)
-			return ret;
+			goto out;
 
 		gen6_gt_force_wake_get(dev_priv);
 
@@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 		seq_puts(m, "no P-state info available\n");
 	}
 
-	return 0;
+out:
+	intel_runtime_pm_put(dev_priv);
+	return ret;
 }
 
 static int i915_delayfreq_table(struct seq_file *m, void *unused)
@@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	for (i = 0; i < 16; i++) {
 		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
 			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
 	}
 
+	intel_runtime_pm_put(dev_priv);
+
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	for (i = 1; i <= 32; i++) {
 		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
 		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
 	}
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	rgvmodectl = I915_READ(MEMMODECTL);
 	rstdbyctl = I915_READ(RSTDBYCTL);
 	crstandvid = I915_READ16(CRSTANDVID);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
@@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	spin_lock_irq(&dev_priv->uncore.lock);
 	forcewake_count = dev_priv->uncore.forcewake_count;
@@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
 	sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
+	intel_runtime_pm_put(dev_priv);
+
 	seq_printf(m, "Video Turbo Mode: %s\n",
 		   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
 	seq_printf(m, "HW control enabled: %s\n",
@@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
@@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 			   ((ia_freq >> 8) & 0xff) * 100);
 	}
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+	intel_runtime_pm_put(dev_priv);
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -1609,6 +1633,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
 		   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
@@ -1640,6 +1665,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 		seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
 			   I915_READ(DISP_ARB_CTL));
 	}
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1700,16 +1726,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	int ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	if (INTEL_INFO(dev)->gen >= 8)
 		gen8_ppgtt_info(m, dev);
 	else if (INTEL_INFO(dev)->gen >= 6)
 		gen6_ppgtt_info(m, dev);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1783,6 +1812,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	u32 psrperf = 0;
 	bool enabled = false;
 
+	intel_runtime_pm_get(dev_priv);
+
 	seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
 	seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
 
@@ -1795,6 +1826,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 			EDP_PSR_PERF_CNT_MASK;
 	seq_printf(m, "Performance_Counter: %u\n", psrperf);
 
+	intel_runtime_pm_put(dev_priv);
 	return 0;
 }
 
@@ -2938,8 +2970,11 @@ i915_cache_sharing_get(void *data, u64 *val)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 
 	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
@@ -2960,6 +2995,7 @@ i915_cache_sharing_set(void *data, u64 val)
 	if (val > 3)
 		return -EINVAL;
 
+	intel_runtime_pm_get(dev_priv);
 	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
 
 	/* Update the cache sharing policy here as well */
@@ -2968,6 +3004,7 @@ i915_cache_sharing_set(void *data, u64 val)
 	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
+	intel_runtime_pm_put(dev_priv);
 	return 0;
 }
 
@@ -2983,6 +3020,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
 	if (INTEL_INFO(dev)->gen < 6)
 		return 0;
 
+	intel_runtime_pm_get(dev_priv);
 	gen6_gt_force_wake_get(dev_priv);
 
 	return 0;
@@ -2997,6 +3035,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
 		return 0;
 
 	gen6_gt_force_wake_put(dev_priv);
+	intel_runtime_pm_put(dev_priv);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 05d8b16..33bcae3 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u64 raw_time; /* 32b value may overflow during fixed point math */
 	u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
+	u32 ret;
 
 	if (!intel_enable_rc6(dev))
 		return 0;
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* On VLV, residency time is in CZ units rather than 1.28us */
 	if (IS_VALLEYVIEW(dev)) {
 		u32 clkctl2;
@@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
 			CLK_CTL2_CZCOUNT_30NS_SHIFT;
 		if (!clkctl2) {
 			WARN(!clkctl2, "bogus CZ count value");
-			return 0;
+			ret = 0;
+			goto out;
 		}
 		units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
 		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
@@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
 	}
 
 	raw_time = I915_READ(reg) * units;
-	return DIV_ROUND_UP_ULL(raw_time, div);
+	ret = DIV_ROUND_UP_ULL(raw_time, div);
+
+out:
+	intel_runtime_pm_put(dev_priv);
+	return ret;
 }
 
 static ssize_t
@@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	if (attr == &dev_attr_gt_RP0_freq_mhz) {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1e372d5..28fc070 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3082,9 +3082,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum drm_connector_status status;
 	struct edid *edid = NULL;
 
+	intel_runtime_pm_get(dev_priv);
+
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, drm_get_connector_name(connector));
 
@@ -3096,7 +3099,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 		status = g4x_dp_detect(intel_dp);
 
 	if (status != connector_status_connected)
-		return status;
+		goto out;
 
 	intel_dp_probe_oui(intel_dp);
 
@@ -3112,7 +3115,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-	return connector_status_connected;
+	status = connector_status_connected;
+
+out:
+	intel_runtime_pm_put(dev_priv);
+	return status;
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index e480cf4..4b7925b 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 {
 	struct intel_connector *connector = bl_get_data(bd);
 	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	intel_runtime_pm_get(dev_priv);
 	mutex_lock(&dev->mode_config.mutex);
 	ret = intel_panel_get_backlight(connector);
 	mutex_unlock(&dev->mode_config.mutex);
+	intel_runtime_pm_put(dev_priv);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index ddd9084..af07325 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -288,6 +288,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 	if (!dev_priv->uncore.funcs.force_wake_get)
 		return;
 
+	intel_runtime_pm_get(dev_priv);
+
 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 	if (dev_priv->uncore.forcewake_count++ == 0)
 		dev_priv->uncore.funcs.force_wake_get(dev_priv);
@@ -312,6 +314,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 				 1);
 	}
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
+	intel_runtime_pm_put(dev_priv);
 }
 
 /* We give fast paths for the really cool registers */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (7 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 08/19] drm/i915: add some runtime PM get/put calls Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-29 13:50   ` Rodrigo Vivi
  2013-11-21 15:47 ` [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled Paulo Zanoni
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

And put it when it's off. Otherwise, when you run pm_pc8 from
intel-gpu-tools, and the delayed function that disables VDD runs,
we'll get some messages saying we're touching registers while the HW
is suspended.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 28fc070..9e9e3d6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1092,6 +1092,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 	if (ironlake_edp_have_panel_vdd(intel_dp))
 		return;
 
+	intel_runtime_pm_get(dev_priv);
+
 	DRM_DEBUG_KMS("Turning eDP VDD on\n");
 
 	if (!ironlake_edp_have_panel_power(intel_dp))
@@ -1141,6 +1143,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 		DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
 		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
 		msleep(intel_dp->panel_power_down_delay);
+
+		intel_runtime_pm_put(dev_priv);
 	}
 }
 
@@ -1248,6 +1252,9 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 	intel_dp->want_panel_vdd = false;
 
 	ironlake_wait_panel_off(intel_dp);
+
+	/* We got a reference when we enabled the VDD. */
+	intel_runtime_pm_put(dev_priv);
 }
 
 void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (8 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-29 14:30   ` Rodrigo Vivi
  2013-12-10 21:54   ` Daniel Vetter
  2013-11-21 15:47 ` [PATCH 11/19] drm/i915: disable interrupts when enabling PC8 Paulo Zanoni
                   ` (8 subsequent siblings)
  18 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

The current code was checking if all bits of "val" were enabled and
DE_PCH_EVENT_IVB was disabled. The new code doesn't care about the
state of DE_PCH_EVENT_IVB: it just checks if everything else is 1.

The goal is that future patches may completely disable interrupts, and
the LCPLL-disabling code shouldn't care about the state of
DE_PCH_EVENT_IVB.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 846f2de..95e8831 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6499,7 +6499,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 	val = I915_READ(DEIMR);
-	WARN((val & ~DE_PCH_EVENT_IVB) != val,
+	WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,
 	     "Unexpected DEIMR bits enabled: 0x%x\n", val);
 	val = I915_READ(SDEIMR);
 	WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 11/19] drm/i915: disable interrupts when enabling PC8
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (9 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-12-02 13:33   ` Rodrigo Vivi
  2013-12-10 21:59   ` Daniel Vetter
  2013-11-21 15:47 ` [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3 Paulo Zanoni
                   ` (7 subsequent siblings)
  18 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

The plan is to merge PC8 and D3 into a single feature, and when we're
in D3 we won't get any hotplug interrupt anyway, so leaving them
enable doesn't make sense, and it also brings us a problem. The
problem is that we get a hotplug interrupt right when we we wake up
from D3, when we're still waking up everything. If we fully disable
interrupts we won't get this hotplug interrupt, so we won't have
problems.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 70c4cef..d0f4e61 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3902,8 +3902,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
 	dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
 	dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
 
-	ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
-	ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
+	ironlake_disable_display_irq(dev_priv, 0xffffffff);
+	ibx_disable_display_interrupt(dev_priv, 0xffffffff);
 	ilk_disable_gt_irq(dev_priv, 0xffffffff);
 	snb_disable_pm_irq(dev_priv, 0xffffffff);
 
@@ -3917,34 +3917,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
-	uint32_t val, expected;
+	uint32_t val;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
 	val = I915_READ(DEIMR);
-	expected = ~DE_PCH_EVENT_IVB;
-	WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
+	WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
 
-	val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
-	expected = ~SDE_HOTPLUG_MASK_CPT;
-	WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
-	     val, expected);
+	val = I915_READ(SDEIMR);
+	WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
 
 	val = I915_READ(GTIMR);
-	expected = 0xffffffff;
-	WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
+	WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
 
 	val = I915_READ(GEN6_PMIMR);
-	expected = 0xffffffff;
-	WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
-	     expected);
+	WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
 
 	dev_priv->pc8.irqs_disabled = false;
 
 	ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
-	ibx_enable_display_interrupt(dev_priv,
-				     ~dev_priv->pc8.regsave.sdeimr &
-				     ~SDE_HOTPLUG_MASK_CPT);
+	ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
 	ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
 	snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
 	I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (10 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 11/19] drm/i915: disable interrupts when enabling PC8 Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-21 16:02   ` Chris Wilson
  2013-12-10 22:03   ` Daniel Vetter
  2013-11-21 15:47 ` [PATCH 13/19] drm: do not steal the display if we have a master Paulo Zanoni
                   ` (6 subsequent siblings)
  18 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

So we'll get a fault when someone tries to access the mmap, then we'll
wake up from D3.

This fixes the gem-mmap-gtt subtest from pm_pc8 from intel-gpu-tools.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 2 ++
 drivers/gpu/drm/i915/i915_drv.h | 1 +
 drivers/gpu/drm/i915/i915_gem.c | 8 ++++++++
 3 files changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b133836..6510483 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -912,6 +912,8 @@ static int i915_runtime_suspend(struct device *device)
 
 	DRM_DEBUG_KMS("Suspending device\n");
 
+	i915_gem_release_all_mmaps(dev_priv);
+
 	dev_priv->pm.suspended = true;
 
 	intel_opregion_notify_adapter(dev, PCI_D3cold);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3877a68..3702746 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2003,6 +2003,7 @@ void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
 int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
+void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 94c2a38..68fa7c7 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1465,6 +1465,14 @@ out:
 	return ret;
 }
 
+void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
+{
+	struct drm_i915_gem_object *obj;
+
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
+		i915_gem_release_mmap(obj);
+}
+
 /**
  * i915_gem_release_mmap - remove physical page mappings
  * @obj: obj in question
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 13/19] drm: do not steal the display if we have a master
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (11 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3 Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-21 16:04   ` Chris Wilson
  2013-11-21 15:47 ` [PATCH 14/19] drm/i915: add runtime PM support on Haswell Paulo Zanoni
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Sometimes we want to disable all the screens on a system, because that
will allow the graphics card to be put into low-power states. The
problem is that, for example, while all screens are disabled, if we
get a hotplug interrupt, fbcon will decide to set a mode instead of
keeping everything disabled, which will remove us from our low power
states.

Let's assume that if there's a DRM master, it will be able to do
whatever is appropriate when we get the hotplug.

This problem can be reproduced by the runtime PM test program from
intel-gpu-tools: we disable all the screens so the graphics device can
be put into D3, then something triggers a hotplug interrupt, fbcon
sets a mode and breaks our test suite. The problem can be reproduced
more easily by the "i2c" subtest.

Other approaches considered for the problem:
    - Return "false" if "bound == 0" and the caller of
      drm_fb_helper_is_bound is a hotplug handler. This would break
      the case where the machine boots with no outputs connected, then
      the user plugs a monitor.
    - Add a new IOCTL to force fbcon to not set modes. This would keep
      all the current applications behaving the same, but adding a new
      IOCTL is not always the greatest idea.

Thanks to Daniel Vetter for the investigation, ideas and the
implementation of the hotplug alternative.

Credits-to: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/drm_fb_helper.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0a19401..199d0c0 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -368,6 +368,12 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 
 	if (bound < crtcs_bound)
 		return false;
+
+	/* Sometimes user space wants everything disabled, so don't steal the
+	 * display if there's a master. */
+	if (bound == 0 && dev->primary->master)
+		return false;
+
 	return true;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 14/19] drm/i915: add runtime PM support on Haswell
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (12 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 13/19] drm: do not steal the display if we have a master Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-12-02 13:37   ` Rodrigo Vivi
  2013-12-10 22:06   ` Daniel Vetter
  2013-11-21 15:47 ` [PATCH 15/19] drm/i915: don't enable VDD just to enable the panel Paulo Zanoni
                   ` (4 subsequent siblings)
  18 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

The code to enable/disable PC8 already takes care of saving and
restoring all the registers we need to save/restore, so do a put()
call when we enable PC8 and a get() call when we disable it.

Ideally, in order to make it easier to add runtime PM support to other
platforms, we should move some things from the PC8 code to the runtime
PM code, but let's do this later, since we can make Haswell work right
now.

V2: - Rebase

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      | 2 +-
 drivers/gpu/drm/i915/intel_display.c | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3702746..002b99d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1836,7 +1836,7 @@ struct drm_i915_file_private {
 #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_PC8(dev)		(IS_HASWELL(dev)) /* XXX HSW:ULX */
-#define HAS_RUNTIME_PM(dev)	false
+#define HAS_RUNTIME_PM(dev)	(IS_HASWELL(dev))
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 95e8831..820013a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6641,6 +6641,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
 	lpt_disable_clkout_dp(dev);
 	hsw_pc8_disable_interrupts(dev);
 	hsw_disable_lcpll(dev_priv, true, true);
+
+	intel_runtime_pm_put(dev_priv);
 }
 
 static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
@@ -6678,6 +6680,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
 
 	DRM_DEBUG_KMS("Disabling package C8+\n");
 
+	intel_runtime_pm_get(dev_priv);
+
 	hsw_restore_lcpll(dev_priv);
 	hsw_pc8_restore_interrupts(dev);
 	lpt_init_pch_refclk(dev);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 15/19] drm/i915: don't enable VDD just to enable the panel
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (13 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 14/19] drm/i915: add runtime PM support on Haswell Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-29 14:40   ` Rodrigo Vivi
  2013-11-21 15:47 ` [PATCH 16/19] drm/i915: don't touch the VDD when disabling " Paulo Zanoni
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

We just don't need this. This saves 250ms from every modeset on my
machine.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 731a919..e868f5f 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1122,9 +1122,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-		ironlake_edp_panel_vdd_on(intel_dp);
 		ironlake_edp_panel_on(intel_dp);
-		ironlake_edp_panel_vdd_off(intel_dp, true);
 	}
 
 	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 16/19] drm/i915: don't touch the VDD when disabling the panel
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (14 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 15/19] drm/i915: don't enable VDD just to enable the panel Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-29 14:41   ` Rodrigo Vivi
  2013-11-21 15:47 ` [PATCH 17/19] drm/i915: fix VDD override off wait Paulo Zanoni
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

I don't see a reason to touch VDD when we're disabling the panel:
since the panel is enabled, we don't need VDD. This saves a few sleep
calls from the vdd_on and vdd_off functions at every modeset.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c |  1 -
 drivers/gpu/drm/i915/intel_dp.c  | 10 +---------
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index e868f5f..5fc4b9e 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1165,7 +1165,6 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-		ironlake_edp_panel_vdd_on(intel_dp);
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
 		ironlake_edp_panel_off(intel_dp);
 	}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9e9e3d6..c2a89b2 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1237,24 +1237,17 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
-	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
-
 	pp = ironlake_get_pp_control(intel_dp);
 	/* We need to switch off panel power _and_ force vdd, for otherwise some
 	 * panels get very unhappy and cease to work. */
-	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+	pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 
-	intel_dp->want_panel_vdd = false;
-
 	ironlake_wait_panel_off(intel_dp);
-
-	/* We got a reference when we enabled the VDD. */
-	intel_runtime_pm_put(dev_priv);
 }
 
 void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1779,7 +1772,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 
 	/* Make sure the panel is off before trying to change the mode. But also
 	 * ensure that we have vdd while we switch off the panel. */
-	ironlake_edp_panel_vdd_on(intel_dp);
 	ironlake_edp_backlight_off(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
 	ironlake_edp_panel_off(intel_dp);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 17/19] drm/i915: fix VDD override off wait
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (15 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 16/19] drm/i915: don't touch the VDD when disabling " Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 18/19] drm/i915: save some time when waiting the eDP timings Paulo Zanoni
  2013-11-21 15:47 ` [PATCH 19/19] drm/i915: init the DP panel power seq regs earlier Paulo Zanoni
  18 siblings, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

If we're disabling the VDD override bit and the panel is enabled, we
don't need to wait for anything. If the panel is disabled, then we
need to actually wait for panel_power_cycle_delay, not
panel_power_down_delay, because the power down delay was already
respected when we disabled the panel.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c2a89b2..b438e76 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1142,7 +1142,9 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 		/* Make sure sequencer is idle before allowing subsequent activity */
 		DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
 		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
-		msleep(intel_dp->panel_power_down_delay);
+
+		if ((pp & POWER_TARGET_ON) == 0)
+			msleep(intel_dp->panel_power_cycle_delay);
 
 		intel_runtime_pm_put(dev_priv);
 	}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 18/19] drm/i915: save some time when waiting the eDP timings
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (16 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 17/19] drm/i915: fix VDD override off wait Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-11-21 16:00   ` Chris Wilson
  2013-11-21 15:47 ` [PATCH 19/19] drm/i915: init the DP panel power seq regs earlier Paulo Zanoni
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

The eDP spec defines some points where after you do action A, you have
to wait some time before action B. The thing is that in our driver
action B does not happen exactly after action A, but we still use
msleep() calls directly. What this patch happens is that we record the
timestamp of when action A happened, then, just before action B, we
look at how much time has passed and only sleep the remaining amount
needed.

With this change, I am able to save about 5-20ms (out of the total
200ms) of the backlight_off delay and completely skip the 1ms
backlight_on delay. The 600ms vdd_off delay doesn't happen during
normal usage anymore due to a previous patch.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 38 +++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_drv.h |  3 +++
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b438e76..3a1ca80 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1051,12 +1051,41 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
 	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
 }
 
+static void ironlake_wait_jiffies_delay(unsigned long timestamp,
+					int to_wait_ms)
+{
+	unsigned long target = timestamp + msecs_to_jiffies(to_wait_ms);
+	unsigned long diff;
+
+	if (time_after(target, jiffies)) {
+		diff = (long)target - (long)jiffies;
+		msleep(diff);
+	}
+}
+
 static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
 {
 	DRM_DEBUG_KMS("Wait for panel power cycle\n");
+
+	/* When we disable the VDD override bit last we have to do the manual
+	 * wait. */
+	ironlake_wait_jiffies_delay(intel_dp->last_power_cycle,
+				    intel_dp->panel_power_cycle_delay);
+
 	ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
 }
 
+static void ironlake_wait_backlight_on(struct intel_dp *intel_dp)
+{
+	ironlake_wait_jiffies_delay(intel_dp->last_power_on,
+				    intel_dp->backlight_on_delay);
+}
+
+static void ironlake_edp_wait_backlight_off(struct intel_dp *intel_dp)
+{
+	ironlake_wait_jiffies_delay(intel_dp->last_backlight_off,
+				    intel_dp->backlight_off_delay);
+}
 
 /* Read the current pp_control value, unlocking the register if it
  * is locked
@@ -1144,7 +1173,7 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
 
 		if ((pp & POWER_TARGET_ON) == 0)
-			msleep(intel_dp->panel_power_cycle_delay);
+			intel_dp->last_power_cycle = jiffies;
 
 		intel_runtime_pm_put(dev_priv);
 	}
@@ -1219,6 +1248,7 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 	POSTING_READ(pp_ctrl_reg);
 
 	ironlake_wait_panel_on(intel_dp);
+	intel_dp->last_power_on = jiffies;
 
 	if (IS_GEN5(dev)) {
 		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
@@ -1239,6 +1269,8 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
+	ironlake_edp_wait_backlight_off(intel_dp);
+
 	pp = ironlake_get_pp_control(intel_dp);
 	/* We need to switch off panel power _and_ force vdd, for otherwise some
 	 * panels get very unhappy and cease to work. */
@@ -1270,7 +1302,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 	 * link.  So delay a bit to make sure the image is solid before
 	 * allowing it to appear.
 	 */
-	msleep(intel_dp->backlight_on_delay);
+	ironlake_wait_backlight_on(intel_dp);
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
 
@@ -1302,7 +1334,7 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
-	msleep(intel_dp->backlight_off_delay);
+	intel_dp->last_backlight_off = jiffies;
 }
 
 static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5596498..778a7be 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -484,6 +484,9 @@ struct intel_dp {
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
 	bool want_panel_vdd;
+	unsigned long last_power_cycle;
+	unsigned long last_power_on;
+	unsigned long last_backlight_off;
 	bool psr_setup_done;
 	struct intel_connector *attached_connector;
 };
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 19/19] drm/i915: init the DP panel power seq regs earlier
  2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
                   ` (17 preceding siblings ...)
  2013-11-21 15:47 ` [PATCH 18/19] drm/i915: save some time when waiting the eDP timings Paulo Zanoni
@ 2013-11-21 15:47 ` Paulo Zanoni
  2013-12-05 15:00   ` Jani Nikula
  18 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 15:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

When we call intel_dp_i2c_init we already get some I2C calls, which
will trigger a VDD enable, which will make use of the panel power
sequencing registers, so we need to have them ready by this time.

The good side is that we were reading the values, but were not using
them for anything (because we were just skipping the msleep(0) calls),
so this "fix" shouldn't fix any real existing bugs. I was only able to
identify the problem because I added some debug code to check how much
time time we were saving with my previous patch.

Regression introduced by:
    commit ed92f0b239ac971edc509169ae3d6955fbe0a188
    Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
    Date:   Wed Jun 12 17:27:24 2013 -0300
        drm/i915: extract intel_edp_init_connector

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3a1ca80..23927a0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3565,14 +3565,14 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 }
 
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
-				     struct intel_connector *intel_connector)
+				     struct intel_connector *intel_connector,
+				     struct edp_power_seq *power_seq)
 {
 	struct drm_connector *connector = &intel_connector->base;
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_display_mode *fixed_mode = NULL;
-	struct edp_power_seq power_seq = { 0 };
 	bool has_dpcd;
 	struct drm_display_mode *scan;
 	struct edid *edid;
@@ -3580,8 +3580,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	if (!is_edp(intel_dp))
 		return true;
 
-	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-
 	/* Cache DPCD and EDID for edp. */
 	ironlake_edp_panel_vdd_on(intel_dp);
 	has_dpcd = intel_dp_get_dpcd(intel_dp);
@@ -3599,8 +3597,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	/* We now know it's not a ghost, init power sequence regs. */
-	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-						      &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
 
 	edid = drm_get_edid(connector, &intel_dp->adapter);
 	if (edid) {
@@ -3649,6 +3646,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum port port = intel_dig_port->port;
+	struct edp_power_seq power_seq = { 0 };
 	const char *name = NULL;
 	int type, error;
 
@@ -3748,13 +3746,16 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		BUG();
 	}
 
+	if (is_edp(intel_dp))
+		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+
 	error = intel_dp_i2c_init(intel_dp, intel_connector, name);
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
 
 	intel_dp->psr_setup_done = false;
 
-	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
+	if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
 		i2c_del_adapter(&intel_dp->adapter);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH 18/19] drm/i915: save some time when waiting the eDP timings
  2013-11-21 15:47 ` [PATCH 18/19] drm/i915: save some time when waiting the eDP timings Paulo Zanoni
@ 2013-11-21 16:00   ` Chris Wilson
  2013-11-25 22:17     ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-21 16:00 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:32PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> The eDP spec defines some points where after you do action A, you have
> to wait some time before action B. The thing is that in our driver
> action B does not happen exactly after action A, but we still use
> msleep() calls directly. What this patch happens is that we record the
> timestamp of when action A happened, then, just before action B, we
> look at how much time has passed and only sleep the remaining amount
> needed.
> 
> With this change, I am able to save about 5-20ms (out of the total
> 200ms) of the backlight_off delay and completely skip the 1ms
> backlight_on delay. The 600ms vdd_off delay doesn't happen during
> normal usage anymore due to a previous patch.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c  | 38 +++++++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/intel_drv.h |  3 +++
>  2 files changed, 38 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index b438e76..3a1ca80 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1051,12 +1051,41 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
>  	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
>  }
>  
> +static void ironlake_wait_jiffies_delay(unsigned long timestamp,
> +					int to_wait_ms)
This is not hw specific, so just
intel_wait_until_after(timestamp_jiffies, to_wait_ms)

> +{
> +	unsigned long target = timestamp + msecs_to_jiffies(to_wait_ms);
> +	unsigned long diff;
> +
> +	if (time_after(target, jiffies)) {
> +		diff = (long)target - (long)jiffies;
> +		msleep(diff);

msleep() expects a duration in ms, diff is in jiffies.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3
  2013-11-21 15:47 ` [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3 Paulo Zanoni
@ 2013-11-21 16:02   ` Chris Wilson
  2013-11-21 16:27     ` Paulo Zanoni
  2013-12-10 22:03   ` Daniel Vetter
  1 sibling, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-21 16:02 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:26PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> So we'll get a fault when someone tries to access the mmap, then we'll
> wake up from D3.

Harsh. Very harsh. Is the GTT completely off-limits under pc8, or is it
only the GTT access to the display engine? i.e. could we get away with
only killing some of the mmaps?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 13/19] drm: do not steal the display if we have a master
  2013-11-21 15:47 ` [PATCH 13/19] drm: do not steal the display if we have a master Paulo Zanoni
@ 2013-11-21 16:04   ` Chris Wilson
  2013-11-27 20:24     ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-21 16:04 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:27PM -0200, Paulo Zanoni wrote:
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 0a19401..199d0c0 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -368,6 +368,12 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
>  
>  	if (bound < crtcs_bound)
>  		return false;
> +
> +	/* Sometimes user space wants everything disabled, so don't steal the
> +	 * display if there's a master. */
> +	if (bound == 0 && dev->primary->master)
> +		return false;

Just do this check first (irrespective of bound).
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-21 15:47 ` [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places Paulo Zanoni
@ 2013-11-21 16:07   ` Chris Wilson
  2013-11-25 20:55     ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-21 16:07 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:21PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> If I add code to enable runtime PM on my Haswell machine, start a
> desktop environment, then enable runtime PM, these functions will
> complain that they're trying to read/write registers while the
> graphics card is suspended.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c            | 53 +++++++++++++++++++-----------
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 ++++
>  drivers/gpu/drm/i915/i915_irq.c            |  6 ++++
>  3 files changed, 46 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 40d9dcf..94c2a38 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1377,36 +1377,38 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>  	drm_i915_private_t *dev_priv = dev->dev_private;
>  	pgoff_t page_offset;
>  	unsigned long pfn;
> -	int ret = 0;
> +	int rc = 0, ret;

Ugh. Just keep ret and don't add rc.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-11-21 15:47 ` [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC Paulo Zanoni
@ 2013-11-21 16:12   ` Chris Wilson
  2013-11-27 20:01     ` Paulo Zanoni
  2013-12-04  9:01   ` Daniel Vetter
  1 sibling, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-21 16:12 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:18PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Currently, PC8 is enabled at modeset_global_resources, which is called
> after intel_modeset_update_state. Due to this, there's a small race
> condition on the case where we start enabling PC8, then do a modeset
> while PC8 is still being enabled. The racing condition triggers a WARN
> because intel_modeset_update_state will mark the CRTC as enabled, then
> the thread that's still enabling PC8 might look at the data structure
> and think that PC8 is being enabled while a pipe is enabled. Despite
> the WARN, this is not really a bug since we'll wait for the
> PC8-enabling thread to finish when we call modeset_global_resources.
> 
> So this patch makes sure we get/put PC8 before we update
> drm_crtc->enabled, because if a get() call triggers a PC8 disable,
> we'll call cancel_delayed_work_sync(), which will wait for the thread
> that's enabling PC8, then, after this, we'll disable PC8.
> 
> The side-effect benefit of this patch is that we have a nice place to
> track enabled/disabled CRTCs, so we may want to move some code from
> modeset_global_resources to intel_crtc_set_state in the future.
> 
> The problem fixed by this patch can be reproduced by the
> modeset-lpsp-stress-no-wait subtest from the pc8 test of
> intel-gpu-tools.
> 
> v2: - No need for pc8.lock since we already have
>       cancel_delayed_work_sync().
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++++++++++++++----
>  1 file changed, 23 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 5ea32a8..846f2de 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -9124,6 +9124,24 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
>  	return false;
>  }
>  
> +/* Sets crtc->base.enabled and gets/puts whatever resources are needed by the
> + * CRTC. */
> +static void intel_crtc_set_state(struct intel_crtc *crtc, bool enabled)
set_state is too generic a term, intel_crtc_set_enabled()

> +{
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (enabled == crtc->base.enabled)
> +		return;
> +
> +	if (enabled)
> +		hsw_disable_package_c8(dev_priv);
> +	else
> +		hsw_enable_package_c8(dev_priv);

We can reduce the code slightly if this was also
hsw_package_c8_set_enabled().
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM
  2013-11-21 15:47 ` [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM Paulo Zanoni
@ 2013-11-21 16:14   ` Chris Wilson
  2013-11-27 20:13     ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-21 16:14 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Jani Nikula, intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:20PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Now that we are actually setting the device to the D3 state, we should
> issue the notification.

Can you please add a snippet to justify the ordering? Is there anything
to say what state the callee expects the device to be in when we send
the notificiation?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3
  2013-11-21 16:02   ` Chris Wilson
@ 2013-11-21 16:27     ` Paulo Zanoni
  0 siblings, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-21 16:27 UTC (permalink / raw)
  To: Chris Wilson, Paulo Zanoni, Intel Graphics Development, Paulo Zanoni

2013/11/21 Chris Wilson <chris@chris-wilson.co.uk>:
> On Thu, Nov 21, 2013 at 01:47:26PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> So we'll get a fault when someone tries to access the mmap, then we'll
>> wake up from D3.
>
> Harsh. Very harsh. Is the GTT completely off-limits under pc8

Under D3, not PC8.

> , or is it
> only the GTT access to the display engine? i.e. could we get away with
> only killing some of the mmaps?

I don't have any documentation describing what should work and what
shouldn't: all I know comes from our test suite, function
gem_mmap_subtest:
http://cgit.freedesktop.org/xorg/app/intel-gpu-tools/tree/tests/pm_pc8.c#n927
. On that test, we don't use the buffers on the display engine. We
just do gem_create(), then gem_mmap__gtt(), write values to the buff,
put the device in D3, then try to read the buffer contents and see if
it is what we wrote. So I imagine the answer to your question is
probably "no".

If you have more ideas of tests I could write that would help
answering your questions, please tell me:)

> -Chris
>
> --
> Chris Wilson, Intel Open Source Technology Centre



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-21 16:07   ` Chris Wilson
@ 2013-11-25 20:55     ` Paulo Zanoni
  2013-11-25 21:21       ` Chris Wilson
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-25 20:55 UTC (permalink / raw)
  To: Chris Wilson, Paulo Zanoni, Intel Graphics Development, Paulo Zanoni

2013/11/21 Chris Wilson <chris@chris-wilson.co.uk>:
> On Thu, Nov 21, 2013 at 01:47:21PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> If I add code to enable runtime PM on my Haswell machine, start a
>> desktop environment, then enable runtime PM, these functions will
>> complain that they're trying to read/write registers while the
>> graphics card is suspended.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_gem.c            | 53 +++++++++++++++++++-----------
>>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 ++++
>>  drivers/gpu/drm/i915/i915_irq.c            |  6 ++++
>>  3 files changed, 46 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index 40d9dcf..94c2a38 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -1377,36 +1377,38 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>>       drm_i915_private_t *dev_priv = dev->dev_private;
>>       pgoff_t page_offset;
>>       unsigned long pfn;
>> -     int ret = 0;
>> +     int rc = 0, ret;
>
> Ugh. Just keep ret and don't add rc.

My idea was that "rc" would contain the return codes for the functions
we call, and "ret" would contain the value we want to return. With
this, at the end of the function we "switch (rc)" and then decide what
we'll assign to "ret". IMHO it's confusing to mix both: we'll "switch
(ret)" and then assign new values to "ret" inside the switch
statement. Also, we don't have to worry about mixing values like
EAGAIN and VM_FAULT_SIGBUS on the same variable. But I'll do the
change, no problem: the commit diff looks much simpler with the change
you proposed.

Thanks for the reviews!

> -Chris
>
> --
> Chris Wilson, Intel Open Source Technology Centre



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-25 20:55     ` Paulo Zanoni
@ 2013-11-25 21:21       ` Chris Wilson
  2013-11-27 20:20         ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-25 21:21 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni

On Mon, Nov 25, 2013 at 06:55:52PM -0200, Paulo Zanoni wrote:
> 2013/11/21 Chris Wilson <chris@chris-wilson.co.uk>:
> > On Thu, Nov 21, 2013 at 01:47:21PM -0200, Paulo Zanoni wrote:
> >> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >>
> >> If I add code to enable runtime PM on my Haswell machine, start a
> >> desktop environment, then enable runtime PM, these functions will
> >> complain that they're trying to read/write registers while the
> >> graphics card is suspended.
> >>
> >> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/i915_gem.c            | 53 +++++++++++++++++++-----------
> >>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 ++++
> >>  drivers/gpu/drm/i915/i915_irq.c            |  6 ++++
> >>  3 files changed, 46 insertions(+), 19 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> >> index 40d9dcf..94c2a38 100644
> >> --- a/drivers/gpu/drm/i915/i915_gem.c
> >> +++ b/drivers/gpu/drm/i915/i915_gem.c
> >> @@ -1377,36 +1377,38 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> >>       drm_i915_private_t *dev_priv = dev->dev_private;
> >>       pgoff_t page_offset;
> >>       unsigned long pfn;
> >> -     int ret = 0;
> >> +     int rc = 0, ret;
> >
> > Ugh. Just keep ret and don't add rc.
> 
> My idea was that "rc" would contain the return codes for the functions
> we call, and "ret" would contain the value we want to return. With
> this, at the end of the function we "switch (rc)" and then decide what
> we'll assign to "ret". IMHO it's confusing to mix both: we'll "switch
> (ret)" and then assign new values to "ret" inside the switch
> statement. Also, we don't have to worry about mixing values like
> EAGAIN and VM_FAULT_SIGBUS on the same variable. But I'll do the
> change, no problem: the commit diff looks much simpler with the change
> you proposed.

The way I think about it is that this function is exceptional. We
typically use a common error code that we percolate all the way back
through the stack, and so ret = callee(); if (ret) return ret; is a
clean idiom. The difference here is just that we need to translate from
one enum to another, rather like a ERR_PTR() cast. Instead of a tidy
inline function, we have the conversion as an explicit switch, but if
you think of it just as return ERR_FAULT(ret), you can see how it fits
into our typical idiom.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 18/19] drm/i915: save some time when waiting the eDP timings
  2013-11-21 16:00   ` Chris Wilson
@ 2013-11-25 22:17     ` Ben Widawsky
  2013-11-25 23:25       ` Chris Wilson
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2013-11-25 22:17 UTC (permalink / raw)
  To: Chris Wilson, Paulo Zanoni, intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 04:00:17PM +0000, Chris Wilson wrote:
> On Thu, Nov 21, 2013 at 01:47:32PM -0200, Paulo Zanoni wrote:
> > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > 
> > The eDP spec defines some points where after you do action A, you have
> > to wait some time before action B. The thing is that in our driver
> > action B does not happen exactly after action A, but we still use
> > msleep() calls directly. What this patch happens is that we record the
> > timestamp of when action A happened, then, just before action B, we
> > look at how much time has passed and only sleep the remaining amount
> > needed.
> > 
> > With this change, I am able to save about 5-20ms (out of the total
> > 200ms) of the backlight_off delay and completely skip the 1ms
> > backlight_on delay. The 600ms vdd_off delay doesn't happen during
> > normal usage anymore due to a previous patch.
> > 
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c  | 38 +++++++++++++++++++++++++++++++++++---
> >  drivers/gpu/drm/i915/intel_drv.h |  3 +++
> >  2 files changed, 38 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index b438e76..3a1ca80 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1051,12 +1051,41 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
> >  	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> >  }
> >  
> > +static void ironlake_wait_jiffies_delay(unsigned long timestamp,
> > +					int to_wait_ms)
> This is not hw specific, so just
> intel_wait_until_after(timestamp_jiffies, to_wait_ms)

Can't we do this with our existing wait_for, and get all the other junk
we've crammed in there?
wait_for(false, timestamp + to_wait_ms)

Or do I have this all wrong?

> 
> > +{
> > +	unsigned long target = timestamp + msecs_to_jiffies(to_wait_ms);
> > +	unsigned long diff;
> > +
> > +	if (time_after(target, jiffies)) {
> > +		diff = (long)target - (long)jiffies;
> > +		msleep(diff);
> 
> msleep() expects a duration in ms, diff is in jiffies.
> -Chris
> 
> -- 
> Chris Wilson, Intel Open Source Technology Centre
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ben Widawsky, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 18/19] drm/i915: save some time when waiting the eDP timings
  2013-11-25 22:17     ` Ben Widawsky
@ 2013-11-25 23:25       ` Chris Wilson
  2013-11-26  2:38         ` Ben Widawsky
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-25 23:25 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Paulo Zanoni

On Mon, Nov 25, 2013 at 02:17:55PM -0800, Ben Widawsky wrote:
> On Thu, Nov 21, 2013 at 04:00:17PM +0000, Chris Wilson wrote:
> > On Thu, Nov 21, 2013 at 01:47:32PM -0200, Paulo Zanoni wrote:
> > > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > 
> > > The eDP spec defines some points where after you do action A, you have
> > > to wait some time before action B. The thing is that in our driver
> > > action B does not happen exactly after action A, but we still use
> > > msleep() calls directly. What this patch happens is that we record the
> > > timestamp of when action A happened, then, just before action B, we
> > > look at how much time has passed and only sleep the remaining amount
> > > needed.
> > > 
> > > With this change, I am able to save about 5-20ms (out of the total
> > > 200ms) of the backlight_off delay and completely skip the 1ms
> > > backlight_on delay. The 600ms vdd_off delay doesn't happen during
> > > normal usage anymore due to a previous patch.
> > > 
> > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_dp.c  | 38 +++++++++++++++++++++++++++++++++++---
> > >  drivers/gpu/drm/i915/intel_drv.h |  3 +++
> > >  2 files changed, 38 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index b438e76..3a1ca80 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -1051,12 +1051,41 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
> > >  	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> > >  }
> > >  
> > > +static void ironlake_wait_jiffies_delay(unsigned long timestamp,
> > > +					int to_wait_ms)
> > This is not hw specific, so just
> > intel_wait_until_after(timestamp_jiffies, to_wait_ms)
> 
> Can't we do this with our existing wait_for, and get all the other junk
> we've crammed in there?
> wait_for(false, timestamp + to_wait_ms)
> 
> Or do I have this all wrong?

It would be
wait_for(false, jiffies_to_ms(max(ms_to_jiffies(timestamp+to_wait_ms) - jiffies, 0))
or something pretty similar. Definitely macro abuse as you would be
hoping that the compiler turned
  while (!time_after(jiffies, timeout)) msleep(1);
into
  msleep(to_ms(timeout-jiffies));

So perhaps clearer would be:
intel_wait_until_after(unsigned long timestamp_jiffies,
                       int to_wait_ms)
 {
   timestamp_jiffies += msec_to_jiffes(to_wait_ms) + 1;
   if (time_after(timestamp_jiffies, jiffies) {
      timestamp_jiffies -= jiffies;
      while (timestamp_jiffies)
          timestamp_jiffies = schedule_timeout(timestamp_jiffies);
   }
 }
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 18/19] drm/i915: save some time when waiting the eDP timings
  2013-11-25 23:25       ` Chris Wilson
@ 2013-11-26  2:38         ` Ben Widawsky
  2013-11-26  9:14           ` Chris Wilson
  0 siblings, 1 reply; 97+ messages in thread
From: Ben Widawsky @ 2013-11-26  2:38 UTC (permalink / raw)
  To: Chris Wilson, Paulo Zanoni, intel-gfx, Paulo Zanoni

On Mon, Nov 25, 2013 at 11:25:10PM +0000, Chris Wilson wrote:
> On Mon, Nov 25, 2013 at 02:17:55PM -0800, Ben Widawsky wrote:
> > On Thu, Nov 21, 2013 at 04:00:17PM +0000, Chris Wilson wrote:
> > > On Thu, Nov 21, 2013 at 01:47:32PM -0200, Paulo Zanoni wrote:
> > > > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > > 
> > > > The eDP spec defines some points where after you do action A, you have
> > > > to wait some time before action B. The thing is that in our driver
> > > > action B does not happen exactly after action A, but we still use
> > > > msleep() calls directly. What this patch happens is that we record the
> > > > timestamp of when action A happened, then, just before action B, we
> > > > look at how much time has passed and only sleep the remaining amount
> > > > needed.
> > > > 
> > > > With this change, I am able to save about 5-20ms (out of the total
> > > > 200ms) of the backlight_off delay and completely skip the 1ms
> > > > backlight_on delay. The 600ms vdd_off delay doesn't happen during
> > > > normal usage anymore due to a previous patch.
> > > > 
> > > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_dp.c  | 38 +++++++++++++++++++++++++++++++++++---
> > > >  drivers/gpu/drm/i915/intel_drv.h |  3 +++
> > > >  2 files changed, 38 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > > index b438e76..3a1ca80 100644
> > > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > > @@ -1051,12 +1051,41 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
> > > >  	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> > > >  }
> > > >  
> > > > +static void ironlake_wait_jiffies_delay(unsigned long timestamp,
> > > > +					int to_wait_ms)
> > > This is not hw specific, so just
> > > intel_wait_until_after(timestamp_jiffies, to_wait_ms)
> > 
> > Can't we do this with our existing wait_for, and get all the other junk
> > we've crammed in there?
> > wait_for(false, timestamp + to_wait_ms)
> > 
> > Or do I have this all wrong?
> 
> It would be
> wait_for(false, jiffies_to_ms(max(ms_to_jiffies(timestamp+to_wait_ms) - jiffies, 0))
> or something pretty similar. Definitely macro abuse as you would be
> hoping that the compiler turned
>   while (!time_after(jiffies, timeout)) msleep(1);
> into
>   msleep(to_ms(timeout-jiffies));
> 
> So perhaps clearer would be:
> intel_wait_until_after(unsigned long timestamp_jiffies,
>                        int to_wait_ms)
>  {
>    timestamp_jiffies += msec_to_jiffes(to_wait_ms) + 1;
>    if (time_after(timestamp_jiffies, jiffies) {
>       timestamp_jiffies -= jiffies;
>       while (timestamp_jiffies)
>           timestamp_jiffies = schedule_timeout(timestamp_jiffies);
>    }
>  }
> -Chris
> 
> -- 
> Chris Wilson, Intel Open Source Technology Centre

Oops, I meant  "timestamp + to_wait_ms - jiffies_to_msecs(jiffies)"
I agree it does get a bit messy, but I think there is likely a cleaner
way that what you propose if we store things as jiffies.

I hate dealing with jiffies, and I feel like even your function has a
race with jiffies though.

let timestamp_jiffies: 2
let jiffies: 1

if jiffies increments by 2 after your timestamp_jiffies -=, you'll have
a problem.

>    if (time_after(timestamp_jiffies, jiffies) {
time_after(2, 1) // jiffies increments by 2
>       timestamp_jiffies -= jiffies;
timestamp_jiffies -= 3
>       while (timestamp_jiffies)
while (-1)
>           timestamp_jiffies = schedule_timeout(timestamp_jiffies);
schedule_timeout(-1)

-- 
Ben Widawsky, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 18/19] drm/i915: save some time when waiting the eDP timings
  2013-11-26  2:38         ` Ben Widawsky
@ 2013-11-26  9:14           ` Chris Wilson
  2013-11-26 15:53             ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Chris Wilson @ 2013-11-26  9:14 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx, Paulo Zanoni

On Mon, Nov 25, 2013 at 06:38:53PM -0800, Ben Widawsky wrote:
> On Mon, Nov 25, 2013 at 11:25:10PM +0000, Chris Wilson wrote:
> > On Mon, Nov 25, 2013 at 02:17:55PM -0800, Ben Widawsky wrote:
> > > On Thu, Nov 21, 2013 at 04:00:17PM +0000, Chris Wilson wrote:
> > > > On Thu, Nov 21, 2013 at 01:47:32PM -0200, Paulo Zanoni wrote:
> > > > > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > > > 
> > > > > The eDP spec defines some points where after you do action A, you have
> > > > > to wait some time before action B. The thing is that in our driver
> > > > > action B does not happen exactly after action A, but we still use
> > > > > msleep() calls directly. What this patch happens is that we record the
> > > > > timestamp of when action A happened, then, just before action B, we
> > > > > look at how much time has passed and only sleep the remaining amount
> > > > > needed.
> > > > > 
> > > > > With this change, I am able to save about 5-20ms (out of the total
> > > > > 200ms) of the backlight_off delay and completely skip the 1ms
> > > > > backlight_on delay. The 600ms vdd_off delay doesn't happen during
> > > > > normal usage anymore due to a previous patch.
> > > > > 
> > > > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/intel_dp.c  | 38 +++++++++++++++++++++++++++++++++++---
> > > > >  drivers/gpu/drm/i915/intel_drv.h |  3 +++
> > > > >  2 files changed, 38 insertions(+), 3 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > > > index b438e76..3a1ca80 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > > > @@ -1051,12 +1051,41 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
> > > > >  	ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> > > > >  }
> > > > >  
> > > > > +static void ironlake_wait_jiffies_delay(unsigned long timestamp,
> > > > > +					int to_wait_ms)
> > > > This is not hw specific, so just
> > > > intel_wait_until_after(timestamp_jiffies, to_wait_ms)
> > > 
> > > Can't we do this with our existing wait_for, and get all the other junk
> > > we've crammed in there?
> > > wait_for(false, timestamp + to_wait_ms)
> > > 
> > > Or do I have this all wrong?
> > 
> > It would be
> > wait_for(false, jiffies_to_ms(max(ms_to_jiffies(timestamp+to_wait_ms) - jiffies, 0))
> > or something pretty similar. Definitely macro abuse as you would be
> > hoping that the compiler turned
> >   while (!time_after(jiffies, timeout)) msleep(1);
> > into
> >   msleep(to_ms(timeout-jiffies));
> > 
> > So perhaps clearer would be:
> > intel_wait_until_after(unsigned long timestamp_jiffies,
> >                        int to_wait_ms)
> >  {
> >    timestamp_jiffies += msec_to_jiffes(to_wait_ms) + 1;
> >    if (time_after(timestamp_jiffies, jiffies) {
> >       timestamp_jiffies -= jiffies;
> >       while (timestamp_jiffies)
> >           timestamp_jiffies = schedule_timeout(timestamp_jiffies);
> >    }
> >  }
> 
> Oops, I meant  "timestamp + to_wait_ms - jiffies_to_msecs(jiffies)"
> I agree it does get a bit messy, but I think there is likely a cleaner
> way that what you propose if we store things as jiffies.
> 
> I hate dealing with jiffies, and I feel like even your function has a
> race with jiffies though.

Sure, I was contemplating using an extra variable to only access jiffies
once, but I was lazy. Not mixing units here would make it less likely to
misuse. However, I think the point stands that we can write a simple
function that is clearer than abusing wait_for(). We will wait and see
what Paulo creates. :)
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 18/19] drm/i915: save some time when waiting the eDP timings
  2013-11-26  9:14           ` Chris Wilson
@ 2013-11-26 15:53             ` Paulo Zanoni
  0 siblings, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-26 15:53 UTC (permalink / raw)
  To: Chris Wilson, Ben Widawsky, Paulo Zanoni,
	Intel Graphics Development, Paulo Zanoni

2013/11/26 Chris Wilson <chris@chris-wilson.co.uk>:
> On Mon, Nov 25, 2013 at 06:38:53PM -0800, Ben Widawsky wrote:
>> On Mon, Nov 25, 2013 at 11:25:10PM +0000, Chris Wilson wrote:
>> > On Mon, Nov 25, 2013 at 02:17:55PM -0800, Ben Widawsky wrote:
>> > > On Thu, Nov 21, 2013 at 04:00:17PM +0000, Chris Wilson wrote:
>> > > > On Thu, Nov 21, 2013 at 01:47:32PM -0200, Paulo Zanoni wrote:
>> > > > > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> > > > >
>> > > > > The eDP spec defines some points where after you do action A, you have
>> > > > > to wait some time before action B. The thing is that in our driver
>> > > > > action B does not happen exactly after action A, but we still use
>> > > > > msleep() calls directly. What this patch happens is that we record the
>> > > > > timestamp of when action A happened, then, just before action B, we
>> > > > > look at how much time has passed and only sleep the remaining amount
>> > > > > needed.
>> > > > >
>> > > > > With this change, I am able to save about 5-20ms (out of the total
>> > > > > 200ms) of the backlight_off delay and completely skip the 1ms
>> > > > > backlight_on delay. The 600ms vdd_off delay doesn't happen during
>> > > > > normal usage anymore due to a previous patch.
>> > > > >
>> > > > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> > > > > ---
>> > > > >  drivers/gpu/drm/i915/intel_dp.c  | 38 +++++++++++++++++++++++++++++++++++---
>> > > > >  drivers/gpu/drm/i915/intel_drv.h |  3 +++
>> > > > >  2 files changed, 38 insertions(+), 3 deletions(-)
>> > > > >
>> > > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> > > > > index b438e76..3a1ca80 100644
>> > > > > --- a/drivers/gpu/drm/i915/intel_dp.c
>> > > > > +++ b/drivers/gpu/drm/i915/intel_dp.c
>> > > > > @@ -1051,12 +1051,41 @@ static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
>> > > > >       ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
>> > > > >  }
>> > > > >
>> > > > > +static void ironlake_wait_jiffies_delay(unsigned long timestamp,
>> > > > > +                                     int to_wait_ms)
>> > > > This is not hw specific, so just
>> > > > intel_wait_until_after(timestamp_jiffies, to_wait_ms)
>> > >
>> > > Can't we do this with our existing wait_for, and get all the other junk
>> > > we've crammed in there?
>> > > wait_for(false, timestamp + to_wait_ms)
>> > >
>> > > Or do I have this all wrong?
>> >
>> > It would be
>> > wait_for(false, jiffies_to_ms(max(ms_to_jiffies(timestamp+to_wait_ms) - jiffies, 0))
>> > or something pretty similar. Definitely macro abuse as you would be
>> > hoping that the compiler turned
>> >   while (!time_after(jiffies, timeout)) msleep(1);
>> > into
>> >   msleep(to_ms(timeout-jiffies));
>> >
>> > So perhaps clearer would be:
>> > intel_wait_until_after(unsigned long timestamp_jiffies,
>> >                        int to_wait_ms)
>> >  {
>> >    timestamp_jiffies += msec_to_jiffes(to_wait_ms) + 1;
>> >    if (time_after(timestamp_jiffies, jiffies) {
>> >       timestamp_jiffies -= jiffies;
>> >       while (timestamp_jiffies)
>> >           timestamp_jiffies = schedule_timeout(timestamp_jiffies);
>> >    }
>> >  }
>>
>> Oops, I meant  "timestamp + to_wait_ms - jiffies_to_msecs(jiffies)"
>> I agree it does get a bit messy, but I think there is likely a cleaner
>> way that what you propose if we store things as jiffies.
>>
>> I hate dealing with jiffies, and I feel like even your function has a
>> race with jiffies though.
>
> Sure, I was contemplating using an extra variable to only access jiffies
> once, but I was lazy. Not mixing units here would make it less likely to
> misuse. However, I think the point stands that we can write a simple
> function that is clearer than abusing wait_for(). We will wait and see
> what Paulo creates. :)

I really don't think abusing wait_for is a good idea. I think wait_for
has a different purpose, and trying to invent clever ways to use it on
a non-standard use case will just make the code hard to read, without
any benefits. And with the risk that future changes to wait_for will
break our code.

Also, I think Chris' solution is very similar to my solution, but with
an open-coded msleep() instead of just the simple msleep() call.

So I'd really vote to apply the KISS design pattern and stick to the
original implementation + Chris' first suggestions (rename the
function, fix the msleep call), unless we can find another bug on it.
But since "applying whatever bikesheds we get" is always the fastest
(only?) way to gets patches merged, if you insist I will just do
whatever is requested.

Thanks,
Paulo

> -Chris
>
> --
> Chris Wilson, Intel Open Source Technology Centre



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code
  2013-11-21 15:47 ` [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code Paulo Zanoni
@ 2013-11-27 19:57   ` Paulo Zanoni
  2013-11-29 11:14     ` [Intel-gfx] " Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 19:57 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, stable

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

When I submitted the first patch adding these force wake functions,
Chris Wilson observed that I was using the wrong functions, so I sent
a second version of the patch to correct this problem. The problem is
that v1 was merged instead of v2.

I was able to notice the problem when running the
debugfs-forcewake-user subtest of pm_pc8 from intel-gpu-tools.

V2: - Rebase on the FORCEWAKE_ALL change.

Cc: stable@vger.kernel.org
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b0d4132..0eb7053 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6583,7 +6583,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
 	/* Make sure we're not on PC8 state before disabling PC8, otherwise
 	 * we'll hang the machine! */
-	dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
+	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
 	if (val & LCPLL_POWER_DOWN_ALLOW) {
 		val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6617,7 +6617,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 			DRM_ERROR("Switching back to LCPLL failed\n");
 	}
 
-	dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
+	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well
  2013-11-21 15:47 ` [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well Paulo Zanoni
@ 2013-11-27 19:59   ` Paulo Zanoni
  2013-11-29 12:35     ` Rodrigo Vivi
  2013-12-10 21:29     ` Daniel Vetter
  0 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 19:59 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

In the current code, at haswell_modeset_global_resources, first we
decide if we want to enable/disable the power well, then we decide if
we want to enable/disable PC8. On the case where we're enabling PC8
this works fine, but on the case where we disable PC8 due to a non-eDP
monitor being enabled, we first enable the power well and then disable
PC8. Although wrong, this doesn't seem to be causing any problems now,
and we don't even see anything in dmesg. But the patches for runtime
D3 turn this problem into a real bug, so we need to fix it.

This fixes the "modeset-non-lpsp" subtest from the "pm_pc8" test from
intel-gpu-tools.

v2: - Rebase (i915_disable_power_well).
v3: - More reabase.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 432ec13..1cb02b1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5677,6 +5677,8 @@ static void hsw_set_power_well(struct drm_device *dev,
 	unsigned long irqflags;
 	uint32_t tmp;
 
+	WARN_ON(dev_priv->pc8.enabled);
+
 	tmp = I915_READ(HSW_PWR_WELL_DRIVER);
 	is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
 	enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
@@ -5736,17 +5738,26 @@ static void hsw_set_power_well(struct drm_device *dev,
 static void __intel_power_well_get(struct drm_device *dev,
 				   struct i915_power_well *power_well)
 {
-	if (!power_well->count++ && power_well->set)
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!power_well->count++ && power_well->set) {
+		hsw_disable_package_c8(dev_priv);
 		power_well->set(dev, power_well, true);
+	}
 }
 
 static void __intel_power_well_put(struct drm_device *dev,
 				   struct i915_power_well *power_well)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
 	WARN_ON(!power_well->count);
 
-	if (!--power_well->count && power_well->set && i915_disable_power_well)
+	if (!--power_well->count && power_well->set &&
+	    i915_disable_power_well) {
 		power_well->set(dev, power_well, false);
+		hsw_enable_package_c8(dev_priv);
+	}
 }
 
 void intel_display_power_get(struct drm_device *dev,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-11-21 16:12   ` Chris Wilson
@ 2013-11-27 20:01     ` Paulo Zanoni
  2013-11-29 12:38       ` Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 20:01 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Currently, PC8 is enabled at modeset_global_resources, which is called
after intel_modeset_update_state. Due to this, there's a small race
condition on the case where we start enabling PC8, then do a modeset
while PC8 is still being enabled. The racing condition triggers a WARN
because intel_modeset_update_state will mark the CRTC as enabled, then
the thread that's still enabling PC8 might look at the data structure
and think that PC8 is being enabled while a pipe is enabled. Despite
the WARN, this is not really a bug since we'll wait for the
PC8-enabling thread to finish when we call modeset_global_resources.

So this patch makes sure we get/put PC8 before we update
drm_crtc->enabled, because if a get() call triggers a PC8 disable,
we'll call cancel_delayed_work_sync(), which will wait for the thread
that's enabling PC8, then, after this, we'll disable PC8.

The side-effect benefit of this patch is that we have a nice place to
track enabled/disabled CRTCs, so we may want to move some code from
modeset_global_resources to intel_crtc_set_enabled in the future.

The problem fixed by this patch can be reproduced by the
modeset-lpsp-stress-no-wait subtest from the pc8 test of
intel-gpu-tools.

v2: - No need for pc8.lock since we already have
      cancel_delayed_work_sync().
v3: - Rename to intel_crtc_set_enabled

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0eb7053..5adf540 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9129,6 +9129,24 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
 	return false;
 }
 
+/* Sets crtc->base.enabled and gets/puts whatever resources are needed by the
+ * CRTC. */
+static void intel_crtc_set_enabled(struct intel_crtc *crtc, bool enabled)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (enabled == crtc->base.enabled)
+		return;
+
+	if (enabled)
+		hsw_disable_package_c8(dev_priv);
+	else
+		hsw_enable_package_c8(dev_priv);
+
+	crtc->base.enabled = enabled;
+}
+
 static void
 intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 {
@@ -9152,7 +9170,8 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 	/* Update computed state. */
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
 			    base.head) {
-		intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
+		intel_crtc_set_enabled(intel_crtc,
+				       intel_crtc_in_use(&intel_crtc->base));
 	}
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -10961,7 +10980,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 		}
 
 		WARN_ON(crtc->active);
-		crtc->base.enabled = false;
+		intel_crtc_set_enabled(crtc, false);
 	}
 
 	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
@@ -10988,7 +11007,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 			      crtc->base.enabled ? "enabled" : "disabled",
 			      crtc->active ? "enabled" : "disabled");
 
-		crtc->base.enabled = crtc->active;
+		intel_crtc_set_enabled(crtc, crtc->active);
 
 		/* Because we only establish the connector -> encoder ->
 		 * crtc links if something is active, this means the
@@ -11085,7 +11104,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 		crtc->active = dev_priv->display.get_pipe_config(crtc,
 								 &crtc->config);
 
-		crtc->base.enabled = crtc->active;
+		intel_crtc_set_enabled(crtc, crtc->active);
 		crtc->primary_enabled = crtc->active;
 
 		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-11-21 15:47 ` [PATCH 05/19] drm/i915: add initial Runtime PM functions Paulo Zanoni
@ 2013-11-27 20:10   ` Paulo Zanoni
  2013-11-29 12:54     ` Rodrigo Vivi
  2013-11-29 14:05     ` Takashi Iwai
  2013-12-02 12:23   ` Imre Deak
  1 sibling, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 20:10 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This patch adds the initial infrastructure to allow a Runtime PM
implementation that sets the device to its D3 state. The patch just
adds the necessary callbacks and the initial infrastructure.

We still don't have any platform that actually uses this
infrastructure, we still don't call get/put in all the places we need
to, and we don't have any function to save/restore the state of the
registers. This is not a problem since no platform uses the code added
by this patch. We have a few people simultaneously working on runtime
PM, so this initial code could help everybody make their plans.

V2: - Move some functions to intel_pm.c
    - Remove useless pm_runtime_allow() call at init
    - Remove useless pm_runtime_mark_last_busy() call at get
    - Use pm_runtime_get_sync() instead of 2 calls
    - Add a WARN to check if we're really awake

V3: - Rebase.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
 drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
 drivers/gpu/drm/i915/intel_drv.h    |  4 +++
 drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
 6 files changed, 124 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 89e4cf1..4cdc1ee 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -42,6 +42,8 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (IS_GEN5(dev))
 		intel_gpu_ips_init(dev_priv);
 
+	intel_init_runtime_pm(dev_priv);
+
 	return 0;
 
 out_power_well:
@@ -1702,6 +1706,8 @@ int i915_driver_unload(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	intel_fini_runtime_pm(dev_priv);
+
 	intel_gpu_ips_teardown();
 
 	/* The i915.ko module is still not prepared to be loaded when
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 0ec0fb3..d5310a0 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* ignore lid events during suspend */
 	mutex_lock(&dev_priv->modeset_restore_lock);
 	dev_priv->modeset_restore = MODESET_SUSPENDED;
@@ -688,6 +690,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
 	mutex_lock(&dev_priv->modeset_restore_lock);
 	dev_priv->modeset_restore = MODESET_DONE;
 	mutex_unlock(&dev_priv->modeset_restore_lock);
+
+	intel_runtime_pm_put(dev_priv);
 	return error;
 }
 
@@ -902,6 +906,42 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 }
 
+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");
+
+	dev_priv->pm.suspended = true;
+
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, PCI_D3cold);
+
+	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");
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	dev_priv->pm.suspended = false;
+
+	return 0;
+}
+
 static const struct dev_pm_ops i915_pm_ops = {
 	.suspend = i915_pm_suspend,
 	.resume = i915_pm_resume,
@@ -909,6 +949,8 @@ static const struct dev_pm_ops i915_pm_ops = {
 	.thaw = i915_pm_thaw,
 	.poweroff = i915_pm_poweroff,
 	.restore = i915_pm_resume,
+	.runtime_suspend = i915_runtime_suspend,
+	.runtime_resume = i915_runtime_resume,
 };
 
 static const struct vm_operations_struct i915_gem_vm_ops = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 00a0217..309ac40 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1291,6 +1291,10 @@ struct i915_package_c8 {
 	} regsave;
 };
 
+struct i915_runtime_pm {
+	bool suspended;
+};
+
 enum intel_pipe_crc_source {
 	INTEL_PIPE_CRC_SOURCE_NONE,
 	INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -1521,6 +1525,8 @@ typedef struct drm_i915_private {
 
 	struct i915_package_c8 pc8;
 
+	struct i915_runtime_pm pm;
+
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
 	 * here! */
 	struct i915_dri1_state dri1;
@@ -1845,6 +1851,7 @@ struct drm_i915_file_private {
 #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_PC8(dev)		(IS_HASWELL(dev)) /* XXX HSW:ULX */
+#define HAS_RUNTIME_PM(dev)	false
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0231281..5596498 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -856,6 +856,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 1cb02b1..6374884 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -31,6 +31,7 @@
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
 #include <drm/i915_powerwell.h>
+#include <linux/pm_runtime.h>
 
 /**
  * RC6 is a special power stage which allows the GPU to enter an very
@@ -5953,6 +5954,61 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
 	hsw_enable_package_c8(dev_priv);
 }
 
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_get_sync(device);
+	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
+}
+
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_mark_last_busy(device);
+	pm_runtime_put_autosuspend(device);
+}
+
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	dev_priv->pm.suspended = false;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_set_active(device);
+	pm_runtime_enable(device);
+
+	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
+	pm_runtime_mark_last_busy(device);
+	pm_runtime_use_autosuspend(device);
+}
+
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	/* Make sure we're not suspended first. */
+	pm_runtime_get_sync(device);
+	pm_runtime_disable(device);
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 7619d87..00e5ced 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -433,6 +433,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
 	}
 }
 
+static void
+assert_device_not_suspended(struct drm_i915_private *dev_priv)
+{
+	WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
+	     "Device suspended\n");
+}
+
 #define REG_READ_HEADER(x) \
 	unsigned long irqflags; \
 	u##x val = 0; \
@@ -561,6 +568,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
+	assert_device_not_suspended(dev_priv); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	if (unlikely(__fifo_ret)) { \
 		gen6_gt_check_fifodbg(dev_priv); \
@@ -576,6 +584,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
+	assert_device_not_suspended(dev_priv); \
 	hsw_unclaimed_reg_clear(dev_priv, reg); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	if (unlikely(__fifo_ret)) { \
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM
  2013-11-21 16:14   ` Chris Wilson
@ 2013-11-27 20:13     ` Paulo Zanoni
  2013-11-29 12:56       ` Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 20:13 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula, Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Now that we are actually setting the device to the D3 state, we should
issue the notification.

The opregion spec says we should send the message before the adapter
is about to be placed in a lower power state, and after the adapter is
placed in a higher power state.

Jani originally wrote a similar patch for PC8, but then we discovered
that we were not really changing the PCI D states when
enabling/disabling PC8, so we had to postpone his patch.

v2: - Improve commit message, explaining the expected state.

Cc: Jani Nikula <jani.nikula@intel.com>
Credits-to: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d5310a0..6b92929 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -918,6 +918,7 @@ static int i915_runtime_suspend(struct device *device)
 
 	dev_priv->pm.suspended = true;
 
+	intel_opregion_notify_adapter(dev, PCI_D3cold);
 	pci_save_state(pdev);
 	pci_set_power_state(pdev, PCI_D3cold);
 
@@ -936,6 +937,7 @@ static int i915_runtime_resume(struct device *device)
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
+	intel_opregion_notify_adapter(dev, PCI_D0);
 
 	dev_priv->pm.suspended = false;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-25 21:21       ` Chris Wilson
@ 2013-11-27 20:20         ` Paulo Zanoni
  2013-11-29 13:03           ` Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 20:20 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

If I add code to enable runtime PM on my Haswell machine, start a
desktop environment, then enable runtime PM, these functions will
complain that they're trying to read/write registers while the
graphics card is suspended.

v2: - Simplify i915_gem_fault changes.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c            | 27 +++++++++++++++++++++------
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 ++++++
 drivers/gpu/drm/i915/i915_irq.c            |  6 ++++++
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 40d9dcf..430b875 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	int ret = 0;
 	bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* We don't use vmf->pgoff since that has the fake offset */
 	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
 		PAGE_SHIFT;
@@ -1427,8 +1429,10 @@ out:
 		/* If this -EIO is due to a gpu hang, give the reset code a
 		 * chance to clean up the mess. Otherwise return the proper
 		 * SIGBUS. */
-		if (i915_terminally_wedged(&dev_priv->gpu_error))
-			return VM_FAULT_SIGBUS;
+		if (i915_terminally_wedged(&dev_priv->gpu_error)) {
+			ret = VM_FAULT_SIGBUS;
+			break;
+		}
 	case -EAGAIN:
 		/*
 		 * EAGAIN means the gpu is hung and we'll wait for the error
@@ -1443,15 +1447,22 @@ out:
 		 * EBUSY is ok: this just means that another thread
 		 * already did the job.
 		 */
-		return VM_FAULT_NOPAGE;
+		ret = VM_FAULT_NOPAGE;
+		break;
 	case -ENOMEM:
-		return VM_FAULT_OOM;
+		ret = VM_FAULT_OOM;
+		break;
 	case -ENOSPC:
-		return VM_FAULT_SIGBUS;
+		ret = VM_FAULT_SIGBUS;
+		break;
 	default:
 		WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
-		return VM_FAULT_SIGBUS;
+		ret = VM_FAULT_SIGBUS;
+		break;
 	}
+
+	intel_runtime_pm_put(dev_priv);
+	return ret;
 }
 
 /**
@@ -4165,6 +4176,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct i915_vma *vma, *next;
 
+	intel_runtime_pm_get(dev_priv);
+
 	trace_i915_gem_object_destroy(obj);
 
 	if (obj->phys_obj)
@@ -4209,6 +4222,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 
 	kfree(obj->bit_17);
 	i915_gem_object_free(obj);
+
+	intel_runtime_pm_put(dev_priv);
 }
 
 struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 3c90dd1..260c147 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1095,6 +1095,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		}
 	}
 
+	intel_runtime_pm_get(dev_priv);
+
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		goto pre_mutex_err;
@@ -1229,6 +1231,10 @@ err:
 
 pre_mutex_err:
 	kfree(cliprects);
+
+	/* intel_gpu_busy should also get a ref, so it will free when the device
+	 * is really idle. */
+	intel_runtime_pm_put(dev_priv);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2715600..70c4cef 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2477,6 +2477,12 @@ static void i915_hangcheck_elapsed(unsigned long data)
 	if (!i915_enable_hangcheck)
 		return;
 
+	/* Just postpone in case we're completely idle... */
+	if (dev_priv->pm.suspended) {
+		i915_queue_hangcheck(dev);
+		return;
+	}
+
 	for_each_ring(ring, dev_priv, i) {
 		u32 seqno, acthd;
 		bool busy = true;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 08/19] drm/i915: add some runtime PM get/put calls
  2013-11-21 15:47 ` [PATCH 08/19] drm/i915: add some runtime PM get/put calls Paulo Zanoni
@ 2013-11-27 20:21   ` Paulo Zanoni
  2013-11-29 13:05     ` Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 20:21 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

These are needed when we cat the debugfs and sysfs files.

V2: - Rebase
V3: - Rebase
V4: - Rebase

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_sysfs.c   | 14 ++++++++++--
 drivers/gpu/drm/i915/intel_dp.c     | 11 +++++++--
 drivers/gpu/drm/i915/intel_panel.c  |  3 +++
 drivers/gpu/drm/i915/intel_uncore.c |  4 ++++
 5 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 13accf7..6badc15 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	for_each_ring(ring, dev_priv, i)
 		i915_ring_seqno_info(m, ring);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	if (INTEL_INFO(dev)->gen >= 8) {
 		int i;
@@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 		}
 		i915_ring_seqno_info(m, ring);
 	}
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	crstanddelay = I915_READ16(CRSTANDVID);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
@@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	int ret;
+	int ret = 0;
+
+	intel_runtime_pm_get(dev_priv);
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
@@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 		/* RPSTAT1 is in the GT power well */
 		ret = mutex_lock_interruptible(&dev->struct_mutex);
 		if (ret)
-			return ret;
+			goto out;
 
 		gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
@@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 		seq_puts(m, "no P-state info available\n");
 	}
 
-	return 0;
+out:
+	intel_runtime_pm_put(dev_priv);
+	return ret;
 }
 
 static int i915_delayfreq_table(struct seq_file *m, void *unused)
@@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	for (i = 0; i < 16; i++) {
 		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
 			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
 	}
 
+	intel_runtime_pm_put(dev_priv);
+
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	for (i = 1; i <= 32; i++) {
 		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
 		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
 	}
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	rgvmodectl = I915_READ(MEMMODECTL);
 	rstdbyctl = I915_READ(RSTDBYCTL);
 	crstandvid = I915_READ16(CRSTANDVID);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
@@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	spin_lock_irq(&dev_priv->uncore.lock);
 	forcewake_count = dev_priv->uncore.forcewake_count;
@@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
 	sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
+	intel_runtime_pm_put(dev_priv);
+
 	seq_printf(m, "Video Turbo Mode: %s\n",
 		   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
 	seq_printf(m, "HW control enabled: %s\n",
@@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
@@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 			   ((ia_freq >> 8) & 0xff) * 100);
 	}
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
 	return 0;
@@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+	intel_runtime_pm_put(dev_priv);
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -1617,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
 		   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
@@ -1648,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 		seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
 			   I915_READ(DISP_ARB_CTL));
 	}
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1708,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	int ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	if (INTEL_INFO(dev)->gen >= 8)
 		gen8_ppgtt_info(m, dev);
 	else if (INTEL_INFO(dev)->gen >= 6)
 		gen6_ppgtt_info(m, dev);
 
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
@@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	u32 psrperf = 0;
 	bool enabled = false;
 
+	intel_runtime_pm_get(dev_priv);
+
 	seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
 	seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
 
@@ -1803,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 			EDP_PSR_PERF_CNT_MASK;
 	seq_printf(m, "Performance_Counter: %u\n", psrperf);
 
+	intel_runtime_pm_put(dev_priv);
 	return 0;
 }
 
@@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 
 	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
@@ -3038,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val)
 	if (val > 3)
 		return -EINVAL;
 
+	intel_runtime_pm_get(dev_priv);
 	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
 
 	/* Update the cache sharing policy here as well */
@@ -3046,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val)
 	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
+	intel_runtime_pm_put(dev_priv);
 	return 0;
 }
 
@@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
 	if (INTEL_INFO(dev)->gen < 6)
 		return 0;
 
+	intel_runtime_pm_get(dev_priv);
 	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
 	return 0;
@@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
 		return 0;
 
 	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+	intel_runtime_pm_put(dev_priv);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 05d8b16..33bcae3 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u64 raw_time; /* 32b value may overflow during fixed point math */
 	u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
+	u32 ret;
 
 	if (!intel_enable_rc6(dev))
 		return 0;
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* On VLV, residency time is in CZ units rather than 1.28us */
 	if (IS_VALLEYVIEW(dev)) {
 		u32 clkctl2;
@@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
 			CLK_CTL2_CZCOUNT_30NS_SHIFT;
 		if (!clkctl2) {
 			WARN(!clkctl2, "bogus CZ count value");
-			return 0;
+			ret = 0;
+			goto out;
 		}
 		units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
 		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
@@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
 	}
 
 	raw_time = I915_READ(reg) * units;
-	return DIV_ROUND_UP_ULL(raw_time, div);
+	ret = DIV_ROUND_UP_ULL(raw_time, div);
+
+out:
+	intel_runtime_pm_put(dev_priv);
+	return ret;
 }
 
 static ssize_t
@@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
+	intel_runtime_pm_get(dev_priv);
 	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	if (attr == &dev_attr_gt_RP0_freq_mhz) {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1e372d5..28fc070 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3082,9 +3082,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum drm_connector_status status;
 	struct edid *edid = NULL;
 
+	intel_runtime_pm_get(dev_priv);
+
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, drm_get_connector_name(connector));
 
@@ -3096,7 +3099,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 		status = g4x_dp_detect(intel_dp);
 
 	if (status != connector_status_connected)
-		return status;
+		goto out;
 
 	intel_dp_probe_oui(intel_dp);
 
@@ -3112,7 +3115,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-	return connector_status_connected;
+	status = connector_status_connected;
+
+out:
+	intel_runtime_pm_put(dev_priv);
+	return status;
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index e480cf4..4b7925b 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 {
 	struct intel_connector *connector = bl_get_data(bd);
 	struct drm_device *dev = connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	intel_runtime_pm_get(dev_priv);
 	mutex_lock(&dev->mode_config.mutex);
 	ret = intel_panel_get_backlight(connector);
 	mutex_unlock(&dev->mode_config.mutex);
+	intel_runtime_pm_put(dev_priv);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 00e5ced..2d745a6 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -366,6 +366,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
 	if (!dev_priv->uncore.funcs.force_wake_get)
 		return;
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* Redirect to VLV specific routine */
 	if (IS_VALLEYVIEW(dev_priv->dev))
 		return vlv_force_wake_get(dev_priv, fw_engine);
@@ -399,6 +401,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 				 1);
 	}
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
+	intel_runtime_pm_put(dev_priv);
 }
 
 /* We give fast paths for the really cool registers */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 13/19] drm: do not steal the display if we have a master
  2013-11-21 16:04   ` Chris Wilson
@ 2013-11-27 20:24     ` Paulo Zanoni
  2013-11-29 13:37       ` Daniel Vetter
  2013-11-30 11:19       ` David Herrmann
  0 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-27 20:24 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, dri-devel

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Sometimes we want to disable all the screens on a system, because that
will allow the graphics card to be put into low-power states. The
problem is that, for example, while all screens are disabled, if we
get a hotplug interrupt, fbcon will decide to set a mode instead of
keeping everything disabled, which will remove us from our low power
states.

Let's assume that if there's a DRM master, it will be able to do
whatever is appropriate when we get the hotplug.

This problem can be reproduced by the runtime PM test program from
intel-gpu-tools: we disable all the screens so the graphics device can
be put into D3, then something triggers a hotplug interrupt, fbcon
sets a mode and breaks our test suite. The problem can be reproduced
more easily by the "i2c" subtest.

Other approaches considered for the problem:
    - Return "false" if "bound == 0" and the caller of
      drm_fb_helper_is_bound is a hotplug handler. This would break
      the case where the machine boots with no outputs connected, then
      the user plugs a monitor.
    - Add a new IOCTL to force fbcon to not set modes. This would keep
      all the current applications behaving the same, but adding a new
      IOCTL is not always the greatest idea.
    - Return false only if "dev->primary->master && bound == 0". This
      was my first implementation, but Chris suggested we should do
      the check irrespective of the "bound" variable.

Thanks to Daniel Vetter for the investigation, ideas and the
implementation of the hotplug alternative.

v2: - Do the check first, irrespective of "bound".
    - Cc dri-devel

Cc: dri-devel@lists.freedesktop.org
Credits-to: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/drm_fb_helper.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0a19401..98a0363 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -359,6 +359,11 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 	struct drm_crtc *crtc;
 	int bound = 0, crtcs_bound = 0;
 
+	/* Sometimes user space wants everything disabled, so don't steal the
+	 * display if there's a master. */
+	if (dev->primary->master)
+		return false;
+
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		if (crtc->fb)
 			crtcs_bound++;
@@ -368,6 +373,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 
 	if (bound < crtcs_bound)
 		return false;
+
 	return true;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8
  2013-11-21 15:47 ` [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8 Paulo Zanoni
@ 2013-11-29 11:11   ` Rodrigo Vivi
  2013-11-29 12:55     ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 11:11 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

I think it should be a return instead a WARN.
Myabe I'm just sleeping yet, but I think the delayed work will execute this even for non HAS_PC8 and warn will always ring on non HSW.
But even if I'm sleeping, since it really touch hsw registers wouldn't be safer a return instead of a warn anyway?


On Thu, Nov 21, 2013 at 01:47:15PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> We already have some checks and shouldn't be reaching these places on
> !HAS_PC8 platforms, but add a WARN,  just in case.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index e85d838..5566de5 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6623,6 +6623,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
>  	struct drm_device *dev = dev_priv->dev;
>  	uint32_t val;
>  
> +	WARN_ON(!HAS_PC8(dev));
> +
>  	if (dev_priv->pc8.enabled)
>  		return;
>  
> @@ -6668,6 +6670,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
>  	if (dev_priv->pc8.disable_count != 1)
>  		return;
>  
> +	WARN_ON(!HAS_PC8(dev));
> +
>  	cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
>  	if (!dev_priv->pc8.enabled)
>  		return;
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [Intel-gfx] [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code
  2013-11-27 19:57   ` Paulo Zanoni
@ 2013-11-29 11:14     ` Rodrigo Vivi
  2013-11-29 13:23       ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 11:14 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni, stable

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Nov 27, 2013 at 05:57:20PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> When I submitted the first patch adding these force wake functions,
> Chris Wilson observed that I was using the wrong functions, so I sent
> a second version of the patch to correct this problem. The problem is
> that v1 was merged instead of v2.
> 
> I was able to notice the problem when running the
> debugfs-forcewake-user subtest of pm_pc8 from intel-gpu-tools.
> 
> V2: - Rebase on the FORCEWAKE_ALL change.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index b0d4132..0eb7053 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6583,7 +6583,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
>  
>  	/* Make sure we're not on PC8 state before disabling PC8, otherwise
>  	 * we'll hang the machine! */
> -	dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
> +	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
>  
>  	if (val & LCPLL_POWER_DOWN_ALLOW) {
>  		val &= ~LCPLL_POWER_DOWN_ALLOW;
> @@ -6617,7 +6617,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
>  			DRM_ERROR("Switching back to LCPLL failed\n");
>  	}
>  
> -	dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
> +	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>  }
>  
>  void hsw_enable_pc8_work(struct work_struct *__work)
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well
  2013-11-27 19:59   ` Paulo Zanoni
@ 2013-11-29 12:35     ` Rodrigo Vivi
  2013-11-29 13:34       ` Rodrigo Vivi
  2013-12-10 21:29     ` Daniel Vetter
  1 sibling, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 12:35 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Nov 27, 2013 at 05:59:22PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> In the current code, at haswell_modeset_global_resources, first we
> decide if we want to enable/disable the power well, then we decide if
> we want to enable/disable PC8. On the case where we're enabling PC8
> this works fine, but on the case where we disable PC8 due to a non-eDP
> monitor being enabled, we first enable the power well and then disable
> PC8. Although wrong, this doesn't seem to be causing any problems now,
> and we don't even see anything in dmesg. But the patches for runtime
> D3 turn this problem into a real bug, so we need to fix it.
> 
> This fixes the "modeset-non-lpsp" subtest from the "pm_pc8" test from
> intel-gpu-tools.
> 
> v2: - Rebase (i915_disable_power_well).
> v3: - More reabase.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 432ec13..1cb02b1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5677,6 +5677,8 @@ static void hsw_set_power_well(struct drm_device *dev,
>  	unsigned long irqflags;
>  	uint32_t tmp;
>  
> +	WARN_ON(dev_priv->pc8.enabled);
> +
>  	tmp = I915_READ(HSW_PWR_WELL_DRIVER);
>  	is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
>  	enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
> @@ -5736,17 +5738,26 @@ static void hsw_set_power_well(struct drm_device *dev,
>  static void __intel_power_well_get(struct drm_device *dev,
>  				   struct i915_power_well *power_well)
>  {
> -	if (!power_well->count++ && power_well->set)
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (!power_well->count++ && power_well->set) {
> +		hsw_disable_package_c8(dev_priv);
>  		power_well->set(dev, power_well, true);
> +	}
>  }
>  
>  static void __intel_power_well_put(struct drm_device *dev,
>  				   struct i915_power_well *power_well)
>  {
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
>  	WARN_ON(!power_well->count);
>  
> -	if (!--power_well->count && power_well->set && i915_disable_power_well)
> +	if (!--power_well->count && power_well->set &&
> +	    i915_disable_power_well) {
>  		power_well->set(dev, power_well, false);
> +		hsw_enable_package_c8(dev_priv);
> +	}
>  }
>  
>  void intel_display_power_get(struct drm_device *dev,
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-11-27 20:01     ` Paulo Zanoni
@ 2013-11-29 12:38       ` Rodrigo Vivi
  2013-11-29 13:34         ` Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 12:38 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Nov 27, 2013 at 06:01:19PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Currently, PC8 is enabled at modeset_global_resources, which is called
> after intel_modeset_update_state. Due to this, there's a small race
> condition on the case where we start enabling PC8, then do a modeset
> while PC8 is still being enabled. The racing condition triggers a WARN
> because intel_modeset_update_state will mark the CRTC as enabled, then
> the thread that's still enabling PC8 might look at the data structure
> and think that PC8 is being enabled while a pipe is enabled. Despite
> the WARN, this is not really a bug since we'll wait for the
> PC8-enabling thread to finish when we call modeset_global_resources.
> 
> So this patch makes sure we get/put PC8 before we update
> drm_crtc->enabled, because if a get() call triggers a PC8 disable,
> we'll call cancel_delayed_work_sync(), which will wait for the thread
> that's enabling PC8, then, after this, we'll disable PC8.
> 
> The side-effect benefit of this patch is that we have a nice place to
> track enabled/disabled CRTCs, so we may want to move some code from
> modeset_global_resources to intel_crtc_set_enabled in the future.
> 
> The problem fixed by this patch can be reproduced by the
> modeset-lpsp-stress-no-wait subtest from the pc8 test of
> intel-gpu-tools.
> 
> v2: - No need for pc8.lock since we already have
>       cancel_delayed_work_sync().
> v3: - Rename to intel_crtc_set_enabled
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++++++++++++++----
>  1 file changed, 23 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0eb7053..5adf540 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -9129,6 +9129,24 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
>  	return false;
>  }
>  
> +/* Sets crtc->base.enabled and gets/puts whatever resources are needed by the
> + * CRTC. */
> +static void intel_crtc_set_enabled(struct intel_crtc *crtc, bool enabled)
> +{
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (enabled == crtc->base.enabled)
> +		return;
> +
> +	if (enabled)
> +		hsw_disable_package_c8(dev_priv);
> +	else
> +		hsw_enable_package_c8(dev_priv);
> +
> +	crtc->base.enabled = enabled;
> +}
> +
>  static void
>  intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
>  {
> @@ -9152,7 +9170,8 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
>  	/* Update computed state. */
>  	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
>  			    base.head) {
> -		intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
> +		intel_crtc_set_enabled(intel_crtc,
> +				       intel_crtc_in_use(&intel_crtc->base));
>  	}
>  
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> @@ -10961,7 +10980,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>  		}
>  
>  		WARN_ON(crtc->active);
> -		crtc->base.enabled = false;
> +		intel_crtc_set_enabled(crtc, false);
>  	}
>  
>  	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
> @@ -10988,7 +11007,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>  			      crtc->base.enabled ? "enabled" : "disabled",
>  			      crtc->active ? "enabled" : "disabled");
>  
> -		crtc->base.enabled = crtc->active;
> +		intel_crtc_set_enabled(crtc, crtc->active);
>  
>  		/* Because we only establish the connector -> encoder ->
>  		 * crtc links if something is active, this means the
> @@ -11085,7 +11104,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>  		crtc->active = dev_priv->display.get_pipe_config(crtc,
>  								 &crtc->config);
>  
> -		crtc->base.enabled = crtc->active;
> +		intel_crtc_set_enabled(crtc, crtc->active);
>  		crtc->primary_enabled = crtc->active;
>  
>  		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-11-27 20:10   ` Paulo Zanoni
@ 2013-11-29 12:54     ` Rodrigo Vivi
  2013-11-29 13:33       ` Rodrigo Vivi
  2013-11-29 14:05     ` Takashi Iwai
  1 sibling, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 12:54 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Nov 27, 2013 at 06:10:30PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> This patch adds the initial infrastructure to allow a Runtime PM
> implementation that sets the device to its D3 state. The patch just
> adds the necessary callbacks and the initial infrastructure.
> 
> We still don't have any platform that actually uses this
> infrastructure, we still don't call get/put in all the places we need
> to, and we don't have any function to save/restore the state of the
> registers. This is not a problem since no platform uses the code added
> by this patch. We have a few people simultaneously working on runtime
> PM, so this initial code could help everybody make their plans.
> 
> V2: - Move some functions to intel_pm.c
>     - Remove useless pm_runtime_allow() call at init
>     - Remove useless pm_runtime_mark_last_busy() call at get
>     - Use pm_runtime_get_sync() instead of 2 calls
>     - Add a WARN to check if we're really awake
> 
> V3: - Rebase.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
>  drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
>  drivers/gpu/drm/i915/intel_drv.h    |  4 +++
>  drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
>  6 files changed, 124 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 89e4cf1..4cdc1ee 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -42,6 +42,8 @@
>  #include <linux/vga_switcheroo.h>
>  #include <linux/slab.h>
>  #include <acpi/video.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
>  
>  #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
>  
> @@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  	if (IS_GEN5(dev))
>  		intel_gpu_ips_init(dev_priv);
>  
> +	intel_init_runtime_pm(dev_priv);
> +
>  	return 0;
>  
>  out_power_well:
> @@ -1702,6 +1706,8 @@ int i915_driver_unload(struct drm_device *dev)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	intel_fini_runtime_pm(dev_priv);
> +
>  	intel_gpu_ips_teardown();
>  
>  	/* The i915.ko module is still not prepared to be loaded when
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 0ec0fb3..d5310a0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_crtc *crtc;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* ignore lid events during suspend */
>  	mutex_lock(&dev_priv->modeset_restore_lock);
>  	dev_priv->modeset_restore = MODESET_SUSPENDED;
> @@ -688,6 +690,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
>  	mutex_lock(&dev_priv->modeset_restore_lock);
>  	dev_priv->modeset_restore = MODESET_DONE;
>  	mutex_unlock(&dev_priv->modeset_restore_lock);
> +
> +	intel_runtime_pm_put(dev_priv);
>  	return error;
>  }
>  
> @@ -902,6 +906,42 @@ static int i915_pm_poweroff(struct device *dev)
>  	return i915_drm_freeze(drm_dev);
>  }
>  
> +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");
> +
> +	dev_priv->pm.suspended = true;
> +
> +	pci_save_state(pdev);
> +	pci_set_power_state(pdev, PCI_D3cold);
> +
> +	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");
> +
> +	pci_set_power_state(pdev, PCI_D0);
> +	pci_restore_state(pdev);
> +
> +	dev_priv->pm.suspended = false;
> +
> +	return 0;
> +}
> +
>  static const struct dev_pm_ops i915_pm_ops = {
>  	.suspend = i915_pm_suspend,
>  	.resume = i915_pm_resume,
> @@ -909,6 +949,8 @@ static const struct dev_pm_ops i915_pm_ops = {
>  	.thaw = i915_pm_thaw,
>  	.poweroff = i915_pm_poweroff,
>  	.restore = i915_pm_resume,
> +	.runtime_suspend = i915_runtime_suspend,
> +	.runtime_resume = i915_runtime_resume,
>  };
>  
>  static const struct vm_operations_struct i915_gem_vm_ops = {
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 00a0217..309ac40 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1291,6 +1291,10 @@ struct i915_package_c8 {
>  	} regsave;
>  };
>  
> +struct i915_runtime_pm {
> +	bool suspended;
> +};
> +
>  enum intel_pipe_crc_source {
>  	INTEL_PIPE_CRC_SOURCE_NONE,
>  	INTEL_PIPE_CRC_SOURCE_PLANE1,
> @@ -1521,6 +1525,8 @@ typedef struct drm_i915_private {
>  
>  	struct i915_package_c8 pc8;
>  
> +	struct i915_runtime_pm pm;
> +
>  	/* Old dri1 support infrastructure, beware the dragons ya fools entering
>  	 * here! */
>  	struct i915_dri1_state dri1;
> @@ -1845,6 +1851,7 @@ struct drm_i915_file_private {
>  #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
>  #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
>  #define HAS_PC8(dev)		(IS_HASWELL(dev)) /* XXX HSW:ULX */
> +#define HAS_RUNTIME_PM(dev)	false
>  
>  #define INTEL_PCH_DEVICE_ID_MASK		0xff00
>  #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 0231281..5596498 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -856,6 +856,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
>  void gen6_rps_boost(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> +void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
>  void ilk_wm_get_hw_state(struct drm_device *dev);
>  
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 1cb02b1..6374884 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -31,6 +31,7 @@
>  #include "../../../platform/x86/intel_ips.h"
>  #include <linux/module.h>
>  #include <drm/i915_powerwell.h>
> +#include <linux/pm_runtime.h>
>  
>  /**
>   * RC6 is a special power stage which allows the GPU to enter an very
> @@ -5953,6 +5954,61 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
>  	hsw_enable_package_c8(dev_priv);
>  }
>  
> +void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	pm_runtime_get_sync(device);
> +	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
> +}
> +
> +void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	pm_runtime_mark_last_busy(device);
> +	pm_runtime_put_autosuspend(device);
> +}
> +
> +void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	dev_priv->pm.suspended = false;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	pm_runtime_set_active(device);
> +	pm_runtime_enable(device);
> +
> +	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
> +	pm_runtime_mark_last_busy(device);
> +	pm_runtime_use_autosuspend(device);
> +}
> +
> +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	/* Make sure we're not suspended first. */
> +	pm_runtime_get_sync(device);
> +	pm_runtime_disable(device);
> +}
> +
>  /* Set up chip specific power management-related functions */
>  void intel_init_pm(struct drm_device *dev)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> index 7619d87..00e5ced 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -433,6 +433,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
>  	}
>  }
>  
> +static void
> +assert_device_not_suspended(struct drm_i915_private *dev_priv)
> +{
> +	WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
> +	     "Device suspended\n");
> +}
> +
>  #define REG_READ_HEADER(x) \
>  	unsigned long irqflags; \
>  	u##x val = 0; \
> @@ -561,6 +568,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
>  	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
>  		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
>  	} \
> +	assert_device_not_suspended(dev_priv); \
>  	__raw_i915_write##x(dev_priv, reg, val); \
>  	if (unlikely(__fifo_ret)) { \
>  		gen6_gt_check_fifodbg(dev_priv); \
> @@ -576,6 +584,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
>  	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
>  		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
>  	} \
> +	assert_device_not_suspended(dev_priv); \
>  	hsw_unclaimed_reg_clear(dev_priv, reg); \
>  	__raw_i915_write##x(dev_priv, reg, val); \
>  	if (unlikely(__fifo_ret)) { \
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8
  2013-11-29 11:11   ` Rodrigo Vivi
@ 2013-11-29 12:55     ` Paulo Zanoni
  2013-11-29 13:31       ` Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-29 12:55 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: Intel Graphics Development, Paulo Zanoni

2013/11/29 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> I think it should be a return instead a WARN.
> Myabe I'm just sleeping yet, but I think the delayed work will execute this even for non HAS_PC8 and warn will always ring on non HSW.
> But even if I'm sleeping, since it really touch hsw registers wouldn't be safer a return instead of a warn anyway?

The refcount should never reach zero on platforms that don't have PC8,
so this should never happen. Also, functions that lead to this
function also have early returns, so we really shouldn't hit this
thing at all.

The early return will hide the problem, while the WARN will tell me my
design is wrong and I need to fix bugs :)

>
>
> On Thu, Nov 21, 2013 at 01:47:15PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> We already have some checks and shouldn't be reaching these places on
>> !HAS_PC8 platforms, but add a WARN,  just in case.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/intel_display.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index e85d838..5566de5 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -6623,6 +6623,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
>>       struct drm_device *dev = dev_priv->dev;
>>       uint32_t val;
>>
>> +     WARN_ON(!HAS_PC8(dev));
>> +
>>       if (dev_priv->pc8.enabled)
>>               return;
>>
>> @@ -6668,6 +6670,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
>>       if (dev_priv->pc8.disable_count != 1)
>>               return;
>>
>> +     WARN_ON(!HAS_PC8(dev));
>> +
>>       cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
>>       if (!dev_priv->pc8.enabled)
>>               return;
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM
  2013-11-27 20:13     ` Paulo Zanoni
@ 2013-11-29 12:56       ` Rodrigo Vivi
  2013-11-29 13:33         ` Rodrigo Vivi
  2013-12-06 22:34         ` Paulo Zanoni
  0 siblings, 2 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 12:56 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Jani Nikula, intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Nov 27, 2013 at 06:13:44PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Now that we are actually setting the device to the D3 state, we should
> issue the notification.
> 
> The opregion spec says we should send the message before the adapter
> is about to be placed in a lower power state, and after the adapter is
> placed in a higher power state.
> 
> Jani originally wrote a similar patch for PC8, but then we discovered
> that we were not really changing the PCI D states when
> enabling/disabling PC8, so we had to postpone his patch.
> 
> v2: - Improve commit message, explaining the expected state.
> 
> Cc: Jani Nikula <jani.nikula@intel.com>
> Credits-to: Jani Nikula <jani.nikula@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index d5310a0..6b92929 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -918,6 +918,7 @@ static int i915_runtime_suspend(struct device *device)
>  
>  	dev_priv->pm.suspended = true;
>  
> +	intel_opregion_notify_adapter(dev, PCI_D3cold);
>  	pci_save_state(pdev);
>  	pci_set_power_state(pdev, PCI_D3cold);
>  
> @@ -936,6 +937,7 @@ static int i915_runtime_resume(struct device *device)
>  
>  	pci_set_power_state(pdev, PCI_D0);
>  	pci_restore_state(pdev);
> +	intel_opregion_notify_adapter(dev, PCI_D0);
>  
>  	dev_priv->pm.suspended = false;
>  
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-27 20:20         ` Paulo Zanoni
@ 2013-11-29 13:03           ` Rodrigo Vivi
  2013-11-29 13:32             ` Rodrigo Vivi
  2013-12-10 21:49             ` Daniel Vetter
  0 siblings, 2 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:03 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Wed, Nov 27, 2013 at 06:20:34PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> If I add code to enable runtime PM on my Haswell machine, start a
> desktop environment, then enable runtime PM, these functions will
> complain that they're trying to read/write registers while the
> graphics card is suspended.
> 
> v2: - Simplify i915_gem_fault changes.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c            | 27 +++++++++++++++++++++------
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 ++++++
>  drivers/gpu/drm/i915/i915_irq.c            |  6 ++++++
>  3 files changed, 33 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 40d9dcf..430b875 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>  	int ret = 0;
>  	bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* We don't use vmf->pgoff since that has the fake offset */
>  	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
>  		PAGE_SHIFT;
> @@ -1427,8 +1429,10 @@ out:
>  		/* If this -EIO is due to a gpu hang, give the reset code a
>  		 * chance to clean up the mess. Otherwise return the proper
>  		 * SIGBUS. */
> -		if (i915_terminally_wedged(&dev_priv->gpu_error))
> -			return VM_FAULT_SIGBUS;
> +		if (i915_terminally_wedged(&dev_priv->gpu_error)) {
> +			ret = VM_FAULT_SIGBUS;
> +			break;
> +		}
>  	case -EAGAIN:
>  		/*
>  		 * EAGAIN means the gpu is hung and we'll wait for the error
> @@ -1443,15 +1447,22 @@ out:
>  		 * EBUSY is ok: this just means that another thread
>  		 * already did the job.
>  		 */
> -		return VM_FAULT_NOPAGE;
> +		ret = VM_FAULT_NOPAGE;
> +		break;
>  	case -ENOMEM:
> -		return VM_FAULT_OOM;
> +		ret = VM_FAULT_OOM;
> +		break;
>  	case -ENOSPC:
> -		return VM_FAULT_SIGBUS;
> +		ret = VM_FAULT_SIGBUS;
> +		break;
>  	default:
>  		WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
> -		return VM_FAULT_SIGBUS;
> +		ret = VM_FAULT_SIGBUS;
> +		break;
>  	}
> +
> +	intel_runtime_pm_put(dev_priv);
> +	return ret;
>  }
>  
>  /**
> @@ -4165,6 +4176,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
>  	drm_i915_private_t *dev_priv = dev->dev_private;
>  	struct i915_vma *vma, *next;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	trace_i915_gem_object_destroy(obj);
>  
>  	if (obj->phys_obj)
> @@ -4209,6 +4222,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
>  
>  	kfree(obj->bit_17);
>  	i915_gem_object_free(obj);
> +
> +	intel_runtime_pm_put(dev_priv);
>  }
>  
>  struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index 3c90dd1..260c147 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -1095,6 +1095,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  		}
>  	}
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	ret = i915_mutex_lock_interruptible(dev);
>  	if (ret)
>  		goto pre_mutex_err;
> @@ -1229,6 +1231,10 @@ err:
>  
>  pre_mutex_err:
>  	kfree(cliprects);
> +
> +	/* intel_gpu_busy should also get a ref, so it will free when the device
> +	 * is really idle. */
> +	intel_runtime_pm_put(dev_priv);
>  	return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 2715600..70c4cef 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -2477,6 +2477,12 @@ static void i915_hangcheck_elapsed(unsigned long data)
>  	if (!i915_enable_hangcheck)
>  		return;
>  
> +	/* Just postpone in case we're completely idle... */
> +	if (dev_priv->pm.suspended) {
> +		i915_queue_hangcheck(dev);
> +		return;
> +	}

I got the idea here, just not sure if it fits on this patch or it is just the commit message.

Anyway,
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

> +
>  	for_each_ring(ring, dev_priv, i) {
>  		u32 seqno, acthd;
>  		bool busy = true;
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 08/19] drm/i915: add some runtime PM get/put calls
  2013-11-27 20:21   ` Paulo Zanoni
@ 2013-11-29 13:05     ` Rodrigo Vivi
  2013-11-29 13:31       ` Rodrigo Vivi
  2013-11-29 13:42       ` Daniel Vetter
  0 siblings, 2 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:05 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

I think this one and last one could be only one patch, but anyway:

Reviewed-by Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Wed, Nov 27, 2013 at 06:21:54PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> These are needed when we cat the debugfs and sysfs files.
> 
> V2: - Rebase
> V3: - Rebase
> V4: - Rebase
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/i915_sysfs.c   | 14 ++++++++++--
>  drivers/gpu/drm/i915/intel_dp.c     | 11 +++++++--
>  drivers/gpu/drm/i915/intel_panel.c  |  3 +++
>  drivers/gpu/drm/i915/intel_uncore.c |  4 ++++
>  5 files changed, 70 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 13accf7..6badc15 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	for_each_ring(ring, dev_priv, i)
>  		i915_ring_seqno_info(m, ring);
>  
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	return 0;
> @@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	if (INTEL_INFO(dev)->gen >= 8) {
>  		int i;
> @@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  		}
>  		i915_ring_seqno_info(m, ring);
>  	}
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	return 0;
> @@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	crstanddelay = I915_READ16(CRSTANDVID);
>  
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
> @@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>  	struct drm_info_node *node = (struct drm_info_node *) m->private;
>  	struct drm_device *dev = node->minor->dev;
>  	drm_i915_private_t *dev_priv = dev->dev_private;
> -	int ret;
> +	int ret = 0;
> +
> +	intel_runtime_pm_get(dev_priv);
>  
>  	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
>  
> @@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>  		/* RPSTAT1 is in the GT power well */
>  		ret = mutex_lock_interruptible(&dev->struct_mutex);
>  		if (ret)
> -			return ret;
> +			goto out;
>  
>  		gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
>  
> @@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>  		seq_puts(m, "no P-state info available\n");
>  	}
>  
> -	return 0;
> +out:
> +	intel_runtime_pm_put(dev_priv);
> +	return ret;
>  }
>  
>  static int i915_delayfreq_table(struct seq_file *m, void *unused)
> @@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	for (i = 0; i < 16; i++) {
>  		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
> @@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
>  			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
>  	}
>  
> +	intel_runtime_pm_put(dev_priv);
> +
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	return 0;
> @@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	for (i = 1; i <= 32; i++) {
>  		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
>  		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
>  	}
>  
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	return 0;
> @@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	rgvmodectl = I915_READ(MEMMODECTL);
>  	rstdbyctl = I915_READ(RSTDBYCTL);
>  	crstandvid = I915_READ16(CRSTANDVID);
>  
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
> @@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	spin_lock_irq(&dev_priv->uncore.lock);
>  	forcewake_count = dev_priv->uncore.forcewake_count;
> @@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
>  	sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
>  	mutex_unlock(&dev_priv->rps.hw_lock);
>  
> +	intel_runtime_pm_put(dev_priv);
> +
>  	seq_printf(m, "Video Turbo Mode: %s\n",
>  		   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
>  	seq_printf(m, "HW control enabled: %s\n",
> @@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>  	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
>  
> @@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>  			   ((ia_freq >> 8) & 0xff) * 100);
>  	}
>  
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev_priv->rps.hw_lock);
>  
>  	return 0;
> @@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
> +	intel_runtime_pm_put(dev_priv);
>  
>  	mutex_unlock(&dev->struct_mutex);
>  
> @@ -1617,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
>  		   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
> @@ -1648,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
>  		seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
>  			   I915_READ(DISP_ARB_CTL));
>  	}
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	return 0;
> @@ -1708,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
>  {
>  	struct drm_info_node *node = (struct drm_info_node *) m->private;
>  	struct drm_device *dev = node->minor->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  
>  	int ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	if (INTEL_INFO(dev)->gen >= 8)
>  		gen8_ppgtt_info(m, dev);
>  	else if (INTEL_INFO(dev)->gen >= 6)
>  		gen6_ppgtt_info(m, dev);
>  
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	return 0;
> @@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>  	u32 psrperf = 0;
>  	bool enabled = false;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
>  	seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
>  
> @@ -1803,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>  			EDP_PSR_PERF_CNT_MASK;
>  	seq_printf(m, "Performance_Counter: %u\n", psrperf);
>  
> +	intel_runtime_pm_put(dev_priv);
>  	return 0;
>  }
>  
> @@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  
>  	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
> +
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev_priv->dev->struct_mutex);
>  
>  	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
> @@ -3038,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val)
>  	if (val > 3)
>  		return -EINVAL;
>  
> +	intel_runtime_pm_get(dev_priv);
>  	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
>  
>  	/* Update the cache sharing policy here as well */
> @@ -3046,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val)
>  	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
>  	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
>  
> +	intel_runtime_pm_put(dev_priv);
>  	return 0;
>  }
>  
> @@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
>  	if (INTEL_INFO(dev)->gen < 6)
>  		return 0;
>  
> +	intel_runtime_pm_get(dev_priv);
>  	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
>  
>  	return 0;
> @@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
>  		return 0;
>  
>  	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
> +	intel_runtime_pm_put(dev_priv);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index 05d8b16..33bcae3 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u64 raw_time; /* 32b value may overflow during fixed point math */
>  	u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
> +	u32 ret;
>  
>  	if (!intel_enable_rc6(dev))
>  		return 0;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* On VLV, residency time is in CZ units rather than 1.28us */
>  	if (IS_VALLEYVIEW(dev)) {
>  		u32 clkctl2;
> @@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>  			CLK_CTL2_CZCOUNT_30NS_SHIFT;
>  		if (!clkctl2) {
>  			WARN(!clkctl2, "bogus CZ count value");
> -			return 0;
> +			ret = 0;
> +			goto out;
>  		}
>  		units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
>  		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
> @@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>  	}
>  
>  	raw_time = I915_READ(reg) * units;
> -	return DIV_ROUND_UP_ULL(raw_time, div);
> +	ret = DIV_ROUND_UP_ULL(raw_time, div);
> +
> +out:
> +	intel_runtime_pm_put(dev_priv);
> +	return ret;
>  }
>  
>  static ssize_t
> @@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
>  	ret = mutex_lock_interruptible(&dev->struct_mutex);
>  	if (ret)
>  		return ret;
> +	intel_runtime_pm_get(dev_priv);
>  	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
> +	intel_runtime_pm_put(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	if (attr == &dev_attr_gt_RP0_freq_mhz) {
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 1e372d5..28fc070 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3082,9 +3082,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct intel_encoder *intel_encoder = &intel_dig_port->base;
>  	struct drm_device *dev = connector->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  	enum drm_connector_status status;
>  	struct edid *edid = NULL;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, drm_get_connector_name(connector));
>  
> @@ -3096,7 +3099,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  		status = g4x_dp_detect(intel_dp);
>  
>  	if (status != connector_status_connected)
> -		return status;
> +		goto out;
>  
>  	intel_dp_probe_oui(intel_dp);
>  
> @@ -3112,7 +3115,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  
>  	if (intel_encoder->type != INTEL_OUTPUT_EDP)
>  		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
> -	return connector_status_connected;
> +	status = connector_status_connected;
> +
> +out:
> +	intel_runtime_pm_put(dev_priv);
> +	return status;
>  }
>  
>  static int intel_dp_get_modes(struct drm_connector *connector)
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index e480cf4..4b7925b 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
>  {
>  	struct intel_connector *connector = bl_get_data(bd);
>  	struct drm_device *dev = connector->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	intel_runtime_pm_get(dev_priv);
>  	mutex_lock(&dev->mode_config.mutex);
>  	ret = intel_panel_get_backlight(connector);
>  	mutex_unlock(&dev->mode_config.mutex);
> +	intel_runtime_pm_put(dev_priv);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> index 00e5ced..2d745a6 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -366,6 +366,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
>  	if (!dev_priv->uncore.funcs.force_wake_get)
>  		return;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* Redirect to VLV specific routine */
>  	if (IS_VALLEYVIEW(dev_priv->dev))
>  		return vlv_force_wake_get(dev_priv, fw_engine);
> @@ -399,6 +401,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
>  				 1);
>  	}
>  	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +
> +	intel_runtime_pm_put(dev_priv);
>  }
>  
>  /* We give fast paths for the really cool registers */
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code
  2013-11-29 11:14     ` [Intel-gfx] " Rodrigo Vivi
@ 2013-11-29 13:23       ` Daniel Vetter
  0 siblings, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-11-29 13:23 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, stable, Paulo Zanoni

On Fri, Nov 29, 2013 at 09:14:41AM -0200, Rodrigo Vivi wrote:
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> 
> On Wed, Nov 27, 2013 at 05:57:20PM -0200, Paulo Zanoni wrote:
> > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > 
> > When I submitted the first patch adding these force wake functions,
> > Chris Wilson observed that I was using the wrong functions, so I sent
> > a second version of the patch to correct this problem. The problem is
> > that v1 was merged instead of v2.
> > 
> > I was able to notice the problem when running the
> > debugfs-forcewake-user subtest of pm_pc8 from intel-gpu-tools.
> > 
> > V2: - Rebase on the FORCEWAKE_ALL change.
> > 
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Picked up for -fixes, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8
  2013-11-29 12:55     ` Paulo Zanoni
@ 2013-11-29 13:31       ` Rodrigo Vivi
  0 siblings, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:31 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni

On Fri, Nov 29, 2013 at 10:55 AM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2013/11/29 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> I think it should be a return instead a WARN.
>> Myabe I'm just sleeping yet, but I think the delayed work will execute this even for non HAS_PC8 and warn will always ring on non HSW.
>> But even if I'm sleeping, since it really touch hsw registers wouldn't be safer a return instead of a warn anyway?
>
> The refcount should never reach zero on platforms that don't have PC8,
> so this should never happen. Also, functions that lead to this
> function also have early returns, so we really shouldn't hit this
> thing at all.
>
> The early return will hide the problem, while the WARN will tell me my
> design is wrong and I need to fix bugs :)

Makes sense.
Feel free to use Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

And sorry about the bad smtp and warns it may caused for everybody.

>
>>
>>
>> On Thu, Nov 21, 2013 at 01:47:15PM -0200, Paulo Zanoni wrote:
>>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>
>>> We already have some checks and shouldn't be reaching these places on
>>> !HAS_PC8 platforms, but add a WARN,  just in case.
>>>
>>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>> ---
>>>  drivers/gpu/drm/i915/intel_display.c | 4 ++++
>>>  1 file changed, 4 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index e85d838..5566de5 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -6623,6 +6623,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
>>>       struct drm_device *dev = dev_priv->dev;
>>>       uint32_t val;
>>>
>>> +     WARN_ON(!HAS_PC8(dev));
>>> +
>>>       if (dev_priv->pc8.enabled)
>>>               return;
>>>
>>> @@ -6668,6 +6670,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
>>>       if (dev_priv->pc8.disable_count != 1)
>>>               return;
>>>
>>> +     WARN_ON(!HAS_PC8(dev));
>>> +
>>>       cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
>>>       if (!dev_priv->pc8.enabled)
>>>               return;
>>> --
>>> 1.8.3.1
>>>
>>> _______________________________________________
>>> Intel-gfx mailing list
>>> Intel-gfx@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 08/19] drm/i915: add some runtime PM get/put calls
  2013-11-29 13:05     ` Rodrigo Vivi
@ 2013-11-29 13:31       ` Rodrigo Vivi
  2013-11-29 13:42       ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:31 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

I think this one and last one could be only one patch, but anyway:

Reviewed-by Rodrigo Vivi <rodrigo.vivi@gmail.com>

(resent with correct smtp)

On Fri, Nov 29, 2013 at 11:05 AM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> I think this one and last one could be only one patch, but anyway:
>
> Reviewed-by Rodrigo Vivi <rodrigo.vivi@gmail.com>
>
> On Wed, Nov 27, 2013 at 06:21:54PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> These are needed when we cat the debugfs and sysfs files.
>>
>> V2: - Rebase
>> V3: - Rebase
>> V4: - Rebase
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++++++++++++++++---
>>  drivers/gpu/drm/i915/i915_sysfs.c   | 14 ++++++++++--
>>  drivers/gpu/drm/i915/intel_dp.c     | 11 +++++++--
>>  drivers/gpu/drm/i915/intel_panel.c  |  3 +++
>>  drivers/gpu/drm/i915/intel_uncore.c |  4 ++++
>>  5 files changed, 70 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> index 13accf7..6badc15 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       for_each_ring(ring, dev_priv, i)
>>               i915_ring_seqno_info(m, ring);
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       return 0;
>> @@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       if (INTEL_INFO(dev)->gen >= 8) {
>>               int i;
>> @@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>>               }
>>               i915_ring_seqno_info(m, ring);
>>       }
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       return 0;
>> @@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       crstanddelay = I915_READ16(CRSTANDVID);
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
>> @@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>>       struct drm_info_node *node = (struct drm_info_node *) m->private;
>>       struct drm_device *dev = node->minor->dev;
>>       drm_i915_private_t *dev_priv = dev->dev_private;
>> -     int ret;
>> +     int ret = 0;
>> +
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       flush_delayed_work(&dev_priv->rps.delayed_resume_work);
>>
>> @@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>>               /* RPSTAT1 is in the GT power well */
>>               ret = mutex_lock_interruptible(&dev->struct_mutex);
>>               if (ret)
>> -                     return ret;
>> +                     goto out;
>>
>>               gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
>>
>> @@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>>               seq_puts(m, "no P-state info available\n");
>>       }
>>
>> -     return 0;
>> +out:
>> +     intel_runtime_pm_put(dev_priv);
>> +     return ret;
>>  }
>>
>>  static int i915_delayfreq_table(struct seq_file *m, void *unused)
>> @@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       for (i = 0; i < 16; i++) {
>>               delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
>> @@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
>>                          (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
>>       }
>>
>> +     intel_runtime_pm_put(dev_priv);
>> +
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       return 0;
>> @@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       for (i = 1; i <= 32; i++) {
>>               inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
>>               seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
>>       }
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       return 0;
>> @@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       rgvmodectl = I915_READ(MEMMODECTL);
>>       rstdbyctl = I915_READ(RSTDBYCTL);
>>       crstandvid = I915_READ16(CRSTANDVID);
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
>> @@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       spin_lock_irq(&dev_priv->uncore.lock);
>>       forcewake_count = dev_priv->uncore.forcewake_count;
>> @@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
>>       sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
>>       mutex_unlock(&dev_priv->rps.hw_lock);
>>
>> +     intel_runtime_pm_put(dev_priv);
>> +
>>       seq_printf(m, "Video Turbo Mode: %s\n",
>>                  yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
>>       seq_printf(m, "HW control enabled: %s\n",
>> @@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>>       ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
>>
>> @@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>>                          ((ia_freq >> 8) & 0xff) * 100);
>>       }
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev_priv->rps.hw_lock);
>>
>>       return 0;
>> @@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
>> +     intel_runtime_pm_put(dev_priv);
>>
>>       mutex_unlock(&dev->struct_mutex);
>>
>> @@ -1617,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
>>                  swizzle_string(dev_priv->mm.bit_6_swizzle_x));
>> @@ -1648,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
>>               seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
>>                          I915_READ(DISP_ARB_CTL));
>>       }
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       return 0;
>> @@ -1708,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
>>  {
>>       struct drm_info_node *node = (struct drm_info_node *) m->private;
>>       struct drm_device *dev = node->minor->dev;
>> +     struct drm_i915_private *dev_priv = dev->dev_private;
>>
>>       int ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       if (INTEL_INFO(dev)->gen >= 8)
>>               gen8_ppgtt_info(m, dev);
>>       else if (INTEL_INFO(dev)->gen >= 6)
>>               gen6_ppgtt_info(m, dev);
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       return 0;
>> @@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>>       u32 psrperf = 0;
>>       bool enabled = false;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
>>       seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
>>
>> @@ -1803,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>>                       EDP_PSR_PERF_CNT_MASK;
>>       seq_printf(m, "Performance_Counter: %u\n", psrperf);
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       return 0;
>>  }
>>
>> @@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>
>>       snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
>> +
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev_priv->dev->struct_mutex);
>>
>>       *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
>> @@ -3038,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val)
>>       if (val > 3)
>>               return -EINVAL;
>>
>> +     intel_runtime_pm_get(dev_priv);
>>       DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
>>
>>       /* Update the cache sharing policy here as well */
>> @@ -3046,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val)
>>       snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
>>       I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
>>
>> +     intel_runtime_pm_put(dev_priv);
>>       return 0;
>>  }
>>
>> @@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
>>       if (INTEL_INFO(dev)->gen < 6)
>>               return 0;
>>
>> +     intel_runtime_pm_get(dev_priv);
>>       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
>>
>>       return 0;
>> @@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
>>               return 0;
>>
>>       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>> +     intel_runtime_pm_put(dev_priv);
>>
>>       return 0;
>>  }
>> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
>> index 05d8b16..33bcae3 100644
>> --- a/drivers/gpu/drm/i915/i915_sysfs.c
>> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
>> @@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       u64 raw_time; /* 32b value may overflow during fixed point math */
>>       u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
>> +     u32 ret;
>>
>>       if (!intel_enable_rc6(dev))
>>               return 0;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       /* On VLV, residency time is in CZ units rather than 1.28us */
>>       if (IS_VALLEYVIEW(dev)) {
>>               u32 clkctl2;
>> @@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>>                       CLK_CTL2_CZCOUNT_30NS_SHIFT;
>>               if (!clkctl2) {
>>                       WARN(!clkctl2, "bogus CZ count value");
>> -                     return 0;
>> +                     ret = 0;
>> +                     goto out;
>>               }
>>               units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
>>               if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
>> @@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>>       }
>>
>>       raw_time = I915_READ(reg) * units;
>> -     return DIV_ROUND_UP_ULL(raw_time, div);
>> +     ret = DIV_ROUND_UP_ULL(raw_time, div);
>> +
>> +out:
>> +     intel_runtime_pm_put(dev_priv);
>> +     return ret;
>>  }
>>
>>  static ssize_t
>> @@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
>>       ret = mutex_lock_interruptible(&dev->struct_mutex);
>>       if (ret)
>>               return ret;
>> +     intel_runtime_pm_get(dev_priv);
>>       rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
>> +     intel_runtime_pm_put(dev_priv);
>>       mutex_unlock(&dev->struct_mutex);
>>
>>       if (attr == &dev_attr_gt_RP0_freq_mhz) {
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 1e372d5..28fc070 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -3082,9 +3082,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>>       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>>       struct intel_encoder *intel_encoder = &intel_dig_port->base;
>>       struct drm_device *dev = connector->dev;
>> +     struct drm_i915_private *dev_priv = dev->dev_private;
>>       enum drm_connector_status status;
>>       struct edid *edid = NULL;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>>                     connector->base.id, drm_get_connector_name(connector));
>>
>> @@ -3096,7 +3099,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>>               status = g4x_dp_detect(intel_dp);
>>
>>       if (status != connector_status_connected)
>> -             return status;
>> +             goto out;
>>
>>       intel_dp_probe_oui(intel_dp);
>>
>> @@ -3112,7 +3115,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>>
>>       if (intel_encoder->type != INTEL_OUTPUT_EDP)
>>               intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
>> -     return connector_status_connected;
>> +     status = connector_status_connected;
>> +
>> +out:
>> +     intel_runtime_pm_put(dev_priv);
>> +     return status;
>>  }
>>
>>  static int intel_dp_get_modes(struct drm_connector *connector)
>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>> index e480cf4..4b7925b 100644
>> --- a/drivers/gpu/drm/i915/intel_panel.c
>> +++ b/drivers/gpu/drm/i915/intel_panel.c
>> @@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
>>  {
>>       struct intel_connector *connector = bl_get_data(bd);
>>       struct drm_device *dev = connector->base.dev;
>> +     struct drm_i915_private *dev_priv = dev->dev_private;
>>       int ret;
>>
>> +     intel_runtime_pm_get(dev_priv);
>>       mutex_lock(&dev->mode_config.mutex);
>>       ret = intel_panel_get_backlight(connector);
>>       mutex_unlock(&dev->mode_config.mutex);
>> +     intel_runtime_pm_put(dev_priv);
>>
>>       return ret;
>>  }
>> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
>> index 00e5ced..2d745a6 100644
>> --- a/drivers/gpu/drm/i915/intel_uncore.c
>> +++ b/drivers/gpu/drm/i915/intel_uncore.c
>> @@ -366,6 +366,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
>>       if (!dev_priv->uncore.funcs.force_wake_get)
>>               return;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       /* Redirect to VLV specific routine */
>>       if (IS_VALLEYVIEW(dev_priv->dev))
>>               return vlv_force_wake_get(dev_priv, fw_engine);
>> @@ -399,6 +401,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
>>                                1);
>>       }
>>       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>> +
>> +     intel_runtime_pm_put(dev_priv);
>>  }
>>
>>  /* We give fast paths for the really cool registers */
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-29 13:03           ` Rodrigo Vivi
@ 2013-11-29 13:32             ` Rodrigo Vivi
  2013-12-10 21:49             ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:32 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

I got the idea here, just not sure if it fits on this patch or it is
just the commit message.

Anyway,
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>


(resent with correct smtp)

On Fri, Nov 29, 2013 at 11:03 AM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> On Wed, Nov 27, 2013 at 06:20:34PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> If I add code to enable runtime PM on my Haswell machine, start a
>> desktop environment, then enable runtime PM, these functions will
>> complain that they're trying to read/write registers while the
>> graphics card is suspended.
>>
>> v2: - Simplify i915_gem_fault changes.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_gem.c            | 27 +++++++++++++++++++++------
>>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  6 ++++++
>>  drivers/gpu/drm/i915/i915_irq.c            |  6 ++++++
>>  3 files changed, 33 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> index 40d9dcf..430b875 100644
>> --- a/drivers/gpu/drm/i915/i915_gem.c
>> +++ b/drivers/gpu/drm/i915/i915_gem.c
>> @@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>>       int ret = 0;
>>       bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       /* We don't use vmf->pgoff since that has the fake offset */
>>       page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
>>               PAGE_SHIFT;
>> @@ -1427,8 +1429,10 @@ out:
>>               /* If this -EIO is due to a gpu hang, give the reset code a
>>                * chance to clean up the mess. Otherwise return the proper
>>                * SIGBUS. */
>> -             if (i915_terminally_wedged(&dev_priv->gpu_error))
>> -                     return VM_FAULT_SIGBUS;
>> +             if (i915_terminally_wedged(&dev_priv->gpu_error)) {
>> +                     ret = VM_FAULT_SIGBUS;
>> +                     break;
>> +             }
>>       case -EAGAIN:
>>               /*
>>                * EAGAIN means the gpu is hung and we'll wait for the error
>> @@ -1443,15 +1447,22 @@ out:
>>                * EBUSY is ok: this just means that another thread
>>                * already did the job.
>>                */
>> -             return VM_FAULT_NOPAGE;
>> +             ret = VM_FAULT_NOPAGE;
>> +             break;
>>       case -ENOMEM:
>> -             return VM_FAULT_OOM;
>> +             ret = VM_FAULT_OOM;
>> +             break;
>>       case -ENOSPC:
>> -             return VM_FAULT_SIGBUS;
>> +             ret = VM_FAULT_SIGBUS;
>> +             break;
>>       default:
>>               WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
>> -             return VM_FAULT_SIGBUS;
>> +             ret = VM_FAULT_SIGBUS;
>> +             break;
>>       }
>> +
>> +     intel_runtime_pm_put(dev_priv);
>> +     return ret;
>>  }
>>
>>  /**
>> @@ -4165,6 +4176,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
>>       drm_i915_private_t *dev_priv = dev->dev_private;
>>       struct i915_vma *vma, *next;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       trace_i915_gem_object_destroy(obj);
>>
>>       if (obj->phys_obj)
>> @@ -4209,6 +4222,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
>>
>>       kfree(obj->bit_17);
>>       i915_gem_object_free(obj);
>> +
>> +     intel_runtime_pm_put(dev_priv);
>>  }
>>
>>  struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
>> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
>> index 3c90dd1..260c147 100644
>> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
>> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
>> @@ -1095,6 +1095,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>>               }
>>       }
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       ret = i915_mutex_lock_interruptible(dev);
>>       if (ret)
>>               goto pre_mutex_err;
>> @@ -1229,6 +1231,10 @@ err:
>>
>>  pre_mutex_err:
>>       kfree(cliprects);
>> +
>> +     /* intel_gpu_busy should also get a ref, so it will free when the device
>> +      * is really idle. */
>> +     intel_runtime_pm_put(dev_priv);
>>       return ret;
>>  }
>>
>> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
>> index 2715600..70c4cef 100644
>> --- a/drivers/gpu/drm/i915/i915_irq.c
>> +++ b/drivers/gpu/drm/i915/i915_irq.c
>> @@ -2477,6 +2477,12 @@ static void i915_hangcheck_elapsed(unsigned long data)
>>       if (!i915_enable_hangcheck)
>>               return;
>>
>> +     /* Just postpone in case we're completely idle... */
>> +     if (dev_priv->pm.suspended) {
>> +             i915_queue_hangcheck(dev);
>> +             return;
>> +     }
>
> I got the idea here, just not sure if it fits on this patch or it is just the commit message.
>
> Anyway,
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>
>> +
>>       for_each_ring(ring, dev_priv, i) {
>>               u32 seqno, acthd;
>>               bool busy = true;
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM
  2013-11-29 12:56       ` Rodrigo Vivi
@ 2013-11-29 13:33         ` Rodrigo Vivi
  2013-12-06 22:34         ` Paulo Zanoni
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:33 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Jani Nikula, intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

(resent with correct smtp)

On Fri, Nov 29, 2013 at 10:56 AM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>
> On Wed, Nov 27, 2013 at 06:13:44PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> Now that we are actually setting the device to the D3 state, we should
>> issue the notification.
>>
>> The opregion spec says we should send the message before the adapter
>> is about to be placed in a lower power state, and after the adapter is
>> placed in a higher power state.
>>
>> Jani originally wrote a similar patch for PC8, but then we discovered
>> that we were not really changing the PCI D states when
>> enabling/disabling PC8, so we had to postpone his patch.
>>
>> v2: - Improve commit message, explaining the expected state.
>>
>> Cc: Jani Nikula <jani.nikula@intel.com>
>> Credits-to: Jani Nikula <jani.nikula@intel.com>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_drv.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index d5310a0..6b92929 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -918,6 +918,7 @@ static int i915_runtime_suspend(struct device *device)
>>
>>       dev_priv->pm.suspended = true;
>>
>> +     intel_opregion_notify_adapter(dev, PCI_D3cold);
>>       pci_save_state(pdev);
>>       pci_set_power_state(pdev, PCI_D3cold);
>>
>> @@ -936,6 +937,7 @@ static int i915_runtime_resume(struct device *device)
>>
>>       pci_set_power_state(pdev, PCI_D0);
>>       pci_restore_state(pdev);
>> +     intel_opregion_notify_adapter(dev, PCI_D0);
>>
>>       dev_priv->pm.suspended = false;
>>
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-11-29 12:54     ` Rodrigo Vivi
@ 2013-11-29 13:33       ` Rodrigo Vivi
  0 siblings, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:33 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

(resent with correct smtp)

On Fri, Nov 29, 2013 at 10:54 AM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>
> On Wed, Nov 27, 2013 at 06:10:30PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> This patch adds the initial infrastructure to allow a Runtime PM
>> implementation that sets the device to its D3 state. The patch just
>> adds the necessary callbacks and the initial infrastructure.
>>
>> We still don't have any platform that actually uses this
>> infrastructure, we still don't call get/put in all the places we need
>> to, and we don't have any function to save/restore the state of the
>> registers. This is not a problem since no platform uses the code added
>> by this patch. We have a few people simultaneously working on runtime
>> PM, so this initial code could help everybody make their plans.
>>
>> V2: - Move some functions to intel_pm.c
>>     - Remove useless pm_runtime_allow() call at init
>>     - Remove useless pm_runtime_mark_last_busy() call at get
>>     - Use pm_runtime_get_sync() instead of 2 calls
>>     - Add a WARN to check if we're really awake
>>
>> V3: - Rebase.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
>>  drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
>>  drivers/gpu/drm/i915/intel_drv.h    |  4 +++
>>  drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
>>  6 files changed, 124 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
>> index 89e4cf1..4cdc1ee 100644
>> --- a/drivers/gpu/drm/i915/i915_dma.c
>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>> @@ -42,6 +42,8 @@
>>  #include <linux/vga_switcheroo.h>
>>  #include <linux/slab.h>
>>  #include <acpi/video.h>
>> +#include <linux/pm.h>
>> +#include <linux/pm_runtime.h>
>>
>>  #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
>>
>> @@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>>       if (IS_GEN5(dev))
>>               intel_gpu_ips_init(dev_priv);
>>
>> +     intel_init_runtime_pm(dev_priv);
>> +
>>       return 0;
>>
>>  out_power_well:
>> @@ -1702,6 +1706,8 @@ int i915_driver_unload(struct drm_device *dev)
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       int ret;
>>
>> +     intel_fini_runtime_pm(dev_priv);
>> +
>>       intel_gpu_ips_teardown();
>>
>>       /* The i915.ko module is still not prepared to be loaded when
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index 0ec0fb3..d5310a0 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       struct drm_crtc *crtc;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       /* ignore lid events during suspend */
>>       mutex_lock(&dev_priv->modeset_restore_lock);
>>       dev_priv->modeset_restore = MODESET_SUSPENDED;
>> @@ -688,6 +690,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
>>       mutex_lock(&dev_priv->modeset_restore_lock);
>>       dev_priv->modeset_restore = MODESET_DONE;
>>       mutex_unlock(&dev_priv->modeset_restore_lock);
>> +
>> +     intel_runtime_pm_put(dev_priv);
>>       return error;
>>  }
>>
>> @@ -902,6 +906,42 @@ static int i915_pm_poweroff(struct device *dev)
>>       return i915_drm_freeze(drm_dev);
>>  }
>>
>> +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");
>> +
>> +     dev_priv->pm.suspended = true;
>> +
>> +     pci_save_state(pdev);
>> +     pci_set_power_state(pdev, PCI_D3cold);
>> +
>> +     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");
>> +
>> +     pci_set_power_state(pdev, PCI_D0);
>> +     pci_restore_state(pdev);
>> +
>> +     dev_priv->pm.suspended = false;
>> +
>> +     return 0;
>> +}
>> +
>>  static const struct dev_pm_ops i915_pm_ops = {
>>       .suspend = i915_pm_suspend,
>>       .resume = i915_pm_resume,
>> @@ -909,6 +949,8 @@ static const struct dev_pm_ops i915_pm_ops = {
>>       .thaw = i915_pm_thaw,
>>       .poweroff = i915_pm_poweroff,
>>       .restore = i915_pm_resume,
>> +     .runtime_suspend = i915_runtime_suspend,
>> +     .runtime_resume = i915_runtime_resume,
>>  };
>>
>>  static const struct vm_operations_struct i915_gem_vm_ops = {
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 00a0217..309ac40 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -1291,6 +1291,10 @@ struct i915_package_c8 {
>>       } regsave;
>>  };
>>
>> +struct i915_runtime_pm {
>> +     bool suspended;
>> +};
>> +
>>  enum intel_pipe_crc_source {
>>       INTEL_PIPE_CRC_SOURCE_NONE,
>>       INTEL_PIPE_CRC_SOURCE_PLANE1,
>> @@ -1521,6 +1525,8 @@ typedef struct drm_i915_private {
>>
>>       struct i915_package_c8 pc8;
>>
>> +     struct i915_runtime_pm pm;
>> +
>>       /* Old dri1 support infrastructure, beware the dragons ya fools entering
>>        * here! */
>>       struct i915_dri1_state dri1;
>> @@ -1845,6 +1851,7 @@ struct drm_i915_file_private {
>>  #define HAS_FPGA_DBG_UNCLAIMED(dev)  (INTEL_INFO(dev)->has_fpga_dbg)
>>  #define HAS_PSR(dev)         (IS_HASWELL(dev) || IS_BROADWELL(dev))
>>  #define HAS_PC8(dev)         (IS_HASWELL(dev)) /* XXX HSW:ULX */
>> +#define HAS_RUNTIME_PM(dev)  false
>>
>>  #define INTEL_PCH_DEVICE_ID_MASK             0xff00
>>  #define INTEL_PCH_IBX_DEVICE_ID_TYPE         0x3b00
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 0231281..5596498 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -856,6 +856,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
>>  void gen6_rps_boost(struct drm_i915_private *dev_priv);
>>  void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
>>  void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
>> +void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
>> +void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
>> +void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
>> +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
>>  void ilk_wm_get_hw_state(struct drm_device *dev);
>>
>>
>> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> index 1cb02b1..6374884 100644
>> --- a/drivers/gpu/drm/i915/intel_pm.c
>> +++ b/drivers/gpu/drm/i915/intel_pm.c
>> @@ -31,6 +31,7 @@
>>  #include "../../../platform/x86/intel_ips.h"
>>  #include <linux/module.h>
>>  #include <drm/i915_powerwell.h>
>> +#include <linux/pm_runtime.h>
>>
>>  /**
>>   * RC6 is a special power stage which allows the GPU to enter an very
>> @@ -5953,6 +5954,61 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
>>       hsw_enable_package_c8(dev_priv);
>>  }
>>
>> +void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>> +{
>> +     struct drm_device *dev = dev_priv->dev;
>> +     struct device *device = &dev->pdev->dev;
>> +
>> +     if (!HAS_RUNTIME_PM(dev))
>> +             return;
>> +
>> +     pm_runtime_get_sync(device);
>> +     WARN(dev_priv->pm.suspended, "Device still suspended.\n");
>> +}
>> +
>> +void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>> +{
>> +     struct drm_device *dev = dev_priv->dev;
>> +     struct device *device = &dev->pdev->dev;
>> +
>> +     if (!HAS_RUNTIME_PM(dev))
>> +             return;
>> +
>> +     pm_runtime_mark_last_busy(device);
>> +     pm_runtime_put_autosuspend(device);
>> +}
>> +
>> +void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>> +{
>> +     struct drm_device *dev = dev_priv->dev;
>> +     struct device *device = &dev->pdev->dev;
>> +
>> +     dev_priv->pm.suspended = false;
>> +
>> +     if (!HAS_RUNTIME_PM(dev))
>> +             return;
>> +
>> +     pm_runtime_set_active(device);
>> +     pm_runtime_enable(device);
>> +
>> +     pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
>> +     pm_runtime_mark_last_busy(device);
>> +     pm_runtime_use_autosuspend(device);
>> +}
>> +
>> +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
>> +{
>> +     struct drm_device *dev = dev_priv->dev;
>> +     struct device *device = &dev->pdev->dev;
>> +
>> +     if (!HAS_RUNTIME_PM(dev))
>> +             return;
>> +
>> +     /* Make sure we're not suspended first. */
>> +     pm_runtime_get_sync(device);
>> +     pm_runtime_disable(device);
>> +}
>> +
>>  /* Set up chip specific power management-related functions */
>>  void intel_init_pm(struct drm_device *dev)
>>  {
>> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
>> index 7619d87..00e5ced 100644
>> --- a/drivers/gpu/drm/i915/intel_uncore.c
>> +++ b/drivers/gpu/drm/i915/intel_uncore.c
>> @@ -433,6 +433,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
>>       }
>>  }
>>
>> +static void
>> +assert_device_not_suspended(struct drm_i915_private *dev_priv)
>> +{
>> +     WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
>> +          "Device suspended\n");
>> +}
>> +
>>  #define REG_READ_HEADER(x) \
>>       unsigned long irqflags; \
>>       u##x val = 0; \
>> @@ -561,6 +568,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
>>       if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
>>               __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
>>       } \
>> +     assert_device_not_suspended(dev_priv); \
>>       __raw_i915_write##x(dev_priv, reg, val); \
>>       if (unlikely(__fifo_ret)) { \
>>               gen6_gt_check_fifodbg(dev_priv); \
>> @@ -576,6 +584,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
>>       if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
>>               __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
>>       } \
>> +     assert_device_not_suspended(dev_priv); \
>>       hsw_unclaimed_reg_clear(dev_priv, reg); \
>>       __raw_i915_write##x(dev_priv, reg, val); \
>>       if (unlikely(__fifo_ret)) { \
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-11-29 12:38       ` Rodrigo Vivi
@ 2013-11-29 13:34         ` Rodrigo Vivi
  0 siblings, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:34 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

(resent with correct smtp)

On Fri, Nov 29, 2013 at 10:38 AM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>
> On Wed, Nov 27, 2013 at 06:01:19PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> Currently, PC8 is enabled at modeset_global_resources, which is called
>> after intel_modeset_update_state. Due to this, there's a small race
>> condition on the case where we start enabling PC8, then do a modeset
>> while PC8 is still being enabled. The racing condition triggers a WARN
>> because intel_modeset_update_state will mark the CRTC as enabled, then
>> the thread that's still enabling PC8 might look at the data structure
>> and think that PC8 is being enabled while a pipe is enabled. Despite
>> the WARN, this is not really a bug since we'll wait for the
>> PC8-enabling thread to finish when we call modeset_global_resources.
>>
>> So this patch makes sure we get/put PC8 before we update
>> drm_crtc->enabled, because if a get() call triggers a PC8 disable,
>> we'll call cancel_delayed_work_sync(), which will wait for the thread
>> that's enabling PC8, then, after this, we'll disable PC8.
>>
>> The side-effect benefit of this patch is that we have a nice place to
>> track enabled/disabled CRTCs, so we may want to move some code from
>> modeset_global_resources to intel_crtc_set_enabled in the future.
>>
>> The problem fixed by this patch can be reproduced by the
>> modeset-lpsp-stress-no-wait subtest from the pc8 test of
>> intel-gpu-tools.
>>
>> v2: - No need for pc8.lock since we already have
>>       cancel_delayed_work_sync().
>> v3: - Rename to intel_crtc_set_enabled
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++++++++++++++----
>>  1 file changed, 23 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 0eb7053..5adf540 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -9129,6 +9129,24 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
>>       return false;
>>  }
>>
>> +/* Sets crtc->base.enabled and gets/puts whatever resources are needed by the
>> + * CRTC. */
>> +static void intel_crtc_set_enabled(struct intel_crtc *crtc, bool enabled)
>> +{
>> +     struct drm_device *dev = crtc->base.dev;
>> +     struct drm_i915_private *dev_priv = dev->dev_private;
>> +
>> +     if (enabled == crtc->base.enabled)
>> +             return;
>> +
>> +     if (enabled)
>> +             hsw_disable_package_c8(dev_priv);
>> +     else
>> +             hsw_enable_package_c8(dev_priv);
>> +
>> +     crtc->base.enabled = enabled;
>> +}
>> +
>>  static void
>>  intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
>>  {
>> @@ -9152,7 +9170,8 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
>>       /* Update computed state. */
>>       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
>>                           base.head) {
>> -             intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
>> +             intel_crtc_set_enabled(intel_crtc,
>> +                                    intel_crtc_in_use(&intel_crtc->base));
>>       }
>>
>>       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
>> @@ -10961,7 +10980,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>>               }
>>
>>               WARN_ON(crtc->active);
>> -             crtc->base.enabled = false;
>> +             intel_crtc_set_enabled(crtc, false);
>>       }
>>
>>       if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
>> @@ -10988,7 +11007,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
>>                             crtc->base.enabled ? "enabled" : "disabled",
>>                             crtc->active ? "enabled" : "disabled");
>>
>> -             crtc->base.enabled = crtc->active;
>> +             intel_crtc_set_enabled(crtc, crtc->active);
>>
>>               /* Because we only establish the connector -> encoder ->
>>                * crtc links if something is active, this means the
>> @@ -11085,7 +11104,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>>               crtc->active = dev_priv->display.get_pipe_config(crtc,
>>                                                                &crtc->config);
>>
>> -             crtc->base.enabled = crtc->active;
>> +             intel_crtc_set_enabled(crtc, crtc->active);
>>               crtc->primary_enabled = crtc->active;
>>
>>               DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well
  2013-11-29 12:35     ` Rodrigo Vivi
@ 2013-11-29 13:34       ` Rodrigo Vivi
  0 siblings, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:34 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

(resent with correct smtp)

On Fri, Nov 29, 2013 at 10:35 AM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>
> On Wed, Nov 27, 2013 at 05:59:22PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> In the current code, at haswell_modeset_global_resources, first we
>> decide if we want to enable/disable the power well, then we decide if
>> we want to enable/disable PC8. On the case where we're enabling PC8
>> this works fine, but on the case where we disable PC8 due to a non-eDP
>> monitor being enabled, we first enable the power well and then disable
>> PC8. Although wrong, this doesn't seem to be causing any problems now,
>> and we don't even see anything in dmesg. But the patches for runtime
>> D3 turn this problem into a real bug, so we need to fix it.
>>
>> This fixes the "modeset-non-lpsp" subtest from the "pm_pc8" test from
>> intel-gpu-tools.
>>
>> v2: - Rebase (i915_disable_power_well).
>> v3: - More reabase.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++--
>>  1 file changed, 13 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> index 432ec13..1cb02b1 100644
>> --- a/drivers/gpu/drm/i915/intel_pm.c
>> +++ b/drivers/gpu/drm/i915/intel_pm.c
>> @@ -5677,6 +5677,8 @@ static void hsw_set_power_well(struct drm_device *dev,
>>       unsigned long irqflags;
>>       uint32_t tmp;
>>
>> +     WARN_ON(dev_priv->pc8.enabled);
>> +
>>       tmp = I915_READ(HSW_PWR_WELL_DRIVER);
>>       is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
>>       enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
>> @@ -5736,17 +5738,26 @@ static void hsw_set_power_well(struct drm_device *dev,
>>  static void __intel_power_well_get(struct drm_device *dev,
>>                                  struct i915_power_well *power_well)
>>  {
>> -     if (!power_well->count++ && power_well->set)
>> +     struct drm_i915_private *dev_priv = dev->dev_private;
>> +
>> +     if (!power_well->count++ && power_well->set) {
>> +             hsw_disable_package_c8(dev_priv);
>>               power_well->set(dev, power_well, true);
>> +     }
>>  }
>>
>>  static void __intel_power_well_put(struct drm_device *dev,
>>                                  struct i915_power_well *power_well)
>>  {
>> +     struct drm_i915_private *dev_priv = dev->dev_private;
>> +
>>       WARN_ON(!power_well->count);
>>
>> -     if (!--power_well->count && power_well->set && i915_disable_power_well)
>> +     if (!--power_well->count && power_well->set &&
>> +         i915_disable_power_well) {
>>               power_well->set(dev, power_well, false);
>> +             hsw_enable_package_c8(dev_priv);
>> +     }
>>  }
>>
>>  void intel_display_power_get(struct drm_device *dev,
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 13/19] drm: do not steal the display if we have a master
  2013-11-27 20:24     ` Paulo Zanoni
@ 2013-11-29 13:37       ` Daniel Vetter
  2013-11-30 11:19       ` David Herrmann
  1 sibling, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-11-29 13:37 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni, dri-devel

On Wed, Nov 27, 2013 at 06:24:08PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Sometimes we want to disable all the screens on a system, because that
> will allow the graphics card to be put into low-power states. The
> problem is that, for example, while all screens are disabled, if we
> get a hotplug interrupt, fbcon will decide to set a mode instead of
> keeping everything disabled, which will remove us from our low power
> states.
> 
> Let's assume that if there's a DRM master, it will be able to do
> whatever is appropriate when we get the hotplug.
> 
> This problem can be reproduced by the runtime PM test program from
> intel-gpu-tools: we disable all the screens so the graphics device can
> be put into D3, then something triggers a hotplug interrupt, fbcon
> sets a mode and breaks our test suite. The problem can be reproduced
> more easily by the "i2c" subtest.
> 
> Other approaches considered for the problem:
>     - Return "false" if "bound == 0" and the caller of
>       drm_fb_helper_is_bound is a hotplug handler. This would break
>       the case where the machine boots with no outputs connected, then
>       the user plugs a monitor.
>     - Add a new IOCTL to force fbcon to not set modes. This would keep
>       all the current applications behaving the same, but adding a new
>       IOCTL is not always the greatest idea.
>     - Return false only if "dev->primary->master && bound == 0". This
>       was my first implementation, but Chris suggested we should do
>       the check irrespective of the "bound" variable.
> 
> Thanks to Daniel Vetter for the investigation, ideas and the
> implementation of the hotplug alternative.
> 
> v2: - Do the check first, irrespective of "bound".
>     - Cc dri-devel
> 
> Cc: dri-devel@lists.freedesktop.org
> Credits-to: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/drm_fb_helper.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 0a19401..98a0363 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -359,6 +359,11 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
>  	struct drm_crtc *crtc;
>  	int bound = 0, crtcs_bound = 0;
>  
> +	/* Sometimes user space wants everything disabled, so don't steal the
> +	 * display if there's a master. */
> +	if (dev->primary->master)
> +		return false;
> +
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>  		if (crtc->fb)
>  			crtcs_bound++;
> @@ -368,6 +373,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
>  
>  	if (bound < crtcs_bound)
>  		return false;
> +
>  	return true;
>  }
>  
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 08/19] drm/i915: add some runtime PM get/put calls
  2013-11-29 13:05     ` Rodrigo Vivi
  2013-11-29 13:31       ` Rodrigo Vivi
@ 2013-11-29 13:42       ` Daniel Vetter
  2013-11-29 13:56         ` Paulo Zanoni
  1 sibling, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2013-11-29 13:42 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

On Fri, Nov 29, 2013 at 11:05:49AM -0200, Rodrigo Vivi wrote:
> I think this one and last one could be only one patch, but anyway:

Yeah, agreed that the split doesn't make too much sense. What I'd really
like to see in these commits (and also all the following ones that
sprinkle runtime pm get/put calls all over the place) is a reference to
the relevant subtest. And with that a natural way to split stuff would be
so that each patch adds the get/put calls for a given feature and hence
testcase.

I don't care too much about the split since it's all disabled by default,
so as-is is imo ok. But the tests should be mentioned. That applies in
general btw: If there's a specific igt testcase for a feature or bugfix,
the kernel commit message should mention the testname.

If people want, we could use a standardized patter like

IGT-Testcase: igt/pm_pc8/gem_mmap_check

or something like that.

Cheers, Daniel
> 
> Reviewed-by Rodrigo Vivi <rodrigo.vivi@gmail.com>
> 
> On Wed, Nov 27, 2013 at 06:21:54PM -0200, Paulo Zanoni wrote:
> > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > 
> > These are needed when we cat the debugfs and sysfs files.
> > 
> > V2: - Rebase
> > V3: - Rebase
> > V4: - Rebase
> > 
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++++++++++++++++---
> >  drivers/gpu/drm/i915/i915_sysfs.c   | 14 ++++++++++--
> >  drivers/gpu/drm/i915/intel_dp.c     | 11 +++++++--
> >  drivers/gpu/drm/i915/intel_panel.c  |  3 +++
> >  drivers/gpu/drm/i915/intel_uncore.c |  4 ++++
> >  5 files changed, 70 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 13accf7..6badc15 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	for_each_ring(ring, dev_priv, i)
> >  		i915_ring_seqno_info(m, ring);
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	return 0;
> > @@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	if (INTEL_INFO(dev)->gen >= 8) {
> >  		int i;
> > @@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
> >  		}
> >  		i915_ring_seqno_info(m, ring);
> >  	}
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	return 0;
> > @@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	crstanddelay = I915_READ16(CRSTANDVID);
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
> > @@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
> >  	struct drm_info_node *node = (struct drm_info_node *) m->private;
> >  	struct drm_device *dev = node->minor->dev;
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> > -	int ret;
> > +	int ret = 0;
> > +
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
> >  
> > @@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
> >  		/* RPSTAT1 is in the GT power well */
> >  		ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  		if (ret)
> > -			return ret;
> > +			goto out;
> >  
> >  		gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
> >  
> > @@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
> >  		seq_puts(m, "no P-state info available\n");
> >  	}
> >  
> > -	return 0;
> > +out:
> > +	intel_runtime_pm_put(dev_priv);
> > +	return ret;
> >  }
> >  
> >  static int i915_delayfreq_table(struct seq_file *m, void *unused)
> > @@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	for (i = 0; i < 16; i++) {
> >  		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
> > @@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
> >  			   (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
> >  	}
> >  
> > +	intel_runtime_pm_put(dev_priv);
> > +
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	return 0;
> > @@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	for (i = 1; i <= 32; i++) {
> >  		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
> >  		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
> >  	}
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	return 0;
> > @@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	rgvmodectl = I915_READ(MEMMODECTL);
> >  	rstdbyctl = I915_READ(RSTDBYCTL);
> >  	crstandvid = I915_READ16(CRSTANDVID);
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
> > @@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	spin_lock_irq(&dev_priv->uncore.lock);
> >  	forcewake_count = dev_priv->uncore.forcewake_count;
> > @@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
> >  	sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
> >  	mutex_unlock(&dev_priv->rps.hw_lock);
> >  
> > +	intel_runtime_pm_put(dev_priv);
> > +
> >  	seq_printf(m, "Video Turbo Mode: %s\n",
> >  		   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
> >  	seq_printf(m, "HW control enabled: %s\n",
> > @@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
> >  	ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
> >  
> > @@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
> >  			   ((ia_freq >> 8) & 0xff) * 100);
> >  	}
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev_priv->rps.hw_lock);
> >  
> >  	return 0;
> > @@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
> > +	intel_runtime_pm_put(dev_priv);
> >  
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> > @@ -1617,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
> >  		   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
> > @@ -1648,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
> >  		seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
> >  			   I915_READ(DISP_ARB_CTL));
> >  	}
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	return 0;
> > @@ -1708,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
> >  {
> >  	struct drm_info_node *node = (struct drm_info_node *) m->private;
> >  	struct drm_device *dev = node->minor->dev;
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> >  
> >  	int ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	if (INTEL_INFO(dev)->gen >= 8)
> >  		gen8_ppgtt_info(m, dev);
> >  	else if (INTEL_INFO(dev)->gen >= 6)
> >  		gen6_ppgtt_info(m, dev);
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	return 0;
> > @@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
> >  	u32 psrperf = 0;
> >  	bool enabled = false;
> >  
> > +	intel_runtime_pm_get(dev_priv);
> > +
> >  	seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
> >  	seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
> >  
> > @@ -1803,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
> >  			EDP_PSR_PERF_CNT_MASK;
> >  	seq_printf(m, "Performance_Counter: %u\n", psrperf);
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	return 0;
> >  }
> >  
> > @@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  
> >  	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
> > +
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev_priv->dev->struct_mutex);
> >  
> >  	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
> > @@ -3038,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val)
> >  	if (val > 3)
> >  		return -EINVAL;
> >  
> > +	intel_runtime_pm_get(dev_priv);
> >  	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
> >  
> >  	/* Update the cache sharing policy here as well */
> > @@ -3046,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val)
> >  	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
> >  	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
> >  
> > +	intel_runtime_pm_put(dev_priv);
> >  	return 0;
> >  }
> >  
> > @@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
> >  	if (INTEL_INFO(dev)->gen < 6)
> >  		return 0;
> >  
> > +	intel_runtime_pm_get(dev_priv);
> >  	gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
> >  
> >  	return 0;
> > @@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
> >  		return 0;
> >  
> >  	gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
> > +	intel_runtime_pm_put(dev_priv);
> >  
> >  	return 0;
> >  }
> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> > index 05d8b16..33bcae3 100644
> > --- a/drivers/gpu/drm/i915/i915_sysfs.c
> > +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> > @@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	u64 raw_time; /* 32b value may overflow during fixed point math */
> >  	u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
> > +	u32 ret;
> >  
> >  	if (!intel_enable_rc6(dev))
> >  		return 0;
> >  
> > +	intel_runtime_pm_get(dev_priv);
> > +
> >  	/* On VLV, residency time is in CZ units rather than 1.28us */
> >  	if (IS_VALLEYVIEW(dev)) {
> >  		u32 clkctl2;
> > @@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
> >  			CLK_CTL2_CZCOUNT_30NS_SHIFT;
> >  		if (!clkctl2) {
> >  			WARN(!clkctl2, "bogus CZ count value");
> > -			return 0;
> > +			ret = 0;
> > +			goto out;
> >  		}
> >  		units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
> >  		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
> > @@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
> >  	}
> >  
> >  	raw_time = I915_READ(reg) * units;
> > -	return DIV_ROUND_UP_ULL(raw_time, div);
> > +	ret = DIV_ROUND_UP_ULL(raw_time, div);
> > +
> > +out:
> > +	intel_runtime_pm_put(dev_priv);
> > +	return ret;
> >  }
> >  
> >  static ssize_t
> > @@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
> >  	ret = mutex_lock_interruptible(&dev->struct_mutex);
> >  	if (ret)
> >  		return ret;
> > +	intel_runtime_pm_get(dev_priv);
> >  	rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
> > +	intel_runtime_pm_put(dev_priv);
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	if (attr == &dev_attr_gt_RP0_freq_mhz) {
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 1e372d5..28fc070 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -3082,9 +3082,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
> >  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> >  	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> >  	struct drm_device *dev = connector->dev;
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	enum drm_connector_status status;
> >  	struct edid *edid = NULL;
> >  
> > +	intel_runtime_pm_get(dev_priv);
> > +
> >  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> >  		      connector->base.id, drm_get_connector_name(connector));
> >  
> > @@ -3096,7 +3099,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
> >  		status = g4x_dp_detect(intel_dp);
> >  
> >  	if (status != connector_status_connected)
> > -		return status;
> > +		goto out;
> >  
> >  	intel_dp_probe_oui(intel_dp);
> >  
> > @@ -3112,7 +3115,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
> >  
> >  	if (intel_encoder->type != INTEL_OUTPUT_EDP)
> >  		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
> > -	return connector_status_connected;
> > +	status = connector_status_connected;
> > +
> > +out:
> > +	intel_runtime_pm_put(dev_priv);
> > +	return status;
> >  }
> >  
> >  static int intel_dp_get_modes(struct drm_connector *connector)
> > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > index e480cf4..4b7925b 100644
> > --- a/drivers/gpu/drm/i915/intel_panel.c
> > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > @@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
> >  {
> >  	struct intel_connector *connector = bl_get_data(bd);
> >  	struct drm_device *dev = connector->base.dev;
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	int ret;
> >  
> > +	intel_runtime_pm_get(dev_priv);
> >  	mutex_lock(&dev->mode_config.mutex);
> >  	ret = intel_panel_get_backlight(connector);
> >  	mutex_unlock(&dev->mode_config.mutex);
> > +	intel_runtime_pm_put(dev_priv);
> >  
> >  	return ret;
> >  }
> > diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> > index 00e5ced..2d745a6 100644
> > --- a/drivers/gpu/drm/i915/intel_uncore.c
> > +++ b/drivers/gpu/drm/i915/intel_uncore.c
> > @@ -366,6 +366,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
> >  	if (!dev_priv->uncore.funcs.force_wake_get)
> >  		return;
> >  
> > +	intel_runtime_pm_get(dev_priv);
> > +
> >  	/* Redirect to VLV specific routine */
> >  	if (IS_VALLEYVIEW(dev_priv->dev))
> >  		return vlv_force_wake_get(dev_priv, fw_engine);
> > @@ -399,6 +401,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
> >  				 1);
> >  	}
> >  	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> > +
> > +	intel_runtime_pm_put(dev_priv);
> >  }
> >  
> >  /* We give fast paths for the really cool registers */
> > -- 
> > 1.8.3.1
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on
  2013-11-21 15:47 ` [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on Paulo Zanoni
@ 2013-11-29 13:50   ` Rodrigo Vivi
  2013-11-29 13:59     ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 13:50 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:23PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> And put it when it's off. Otherwise, when you run pm_pc8 from
> intel-gpu-tools, and the delayed function that disables VDD runs,
> we'll get some messages saying we're touching registers while the HW
> is suspended.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 28fc070..9e9e3d6 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1092,6 +1092,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
>  	if (ironlake_edp_have_panel_vdd(intel_dp))
>  		return;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	DRM_DEBUG_KMS("Turning eDP VDD on\n");
>  
>  	if (!ironlake_edp_have_panel_power(intel_dp))
> @@ -1141,6 +1143,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
>  		DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
>  		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
>  		msleep(intel_dp->panel_power_down_delay);
> +
> +		intel_runtime_pm_put(dev_priv);
>  	}
>  }
>  
> @@ -1248,6 +1252,9 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
>  	intel_dp->want_panel_vdd = false;
>  
>  	ironlake_wait_panel_off(intel_dp);
> +
> +	/* We got a reference when we enabled the VDD. */
> +	intel_runtime_pm_put(dev_priv);

I was going to say it was missing a get until I read the comment above.
But if it gets on VDD on, why not just let it put back on VDD off instead?

>  }
>  
>  void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 08/19] drm/i915: add some runtime PM get/put calls
  2013-11-29 13:42       ` Daniel Vetter
@ 2013-11-29 13:56         ` Paulo Zanoni
  0 siblings, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-29 13:56 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development, Paulo Zanoni

2013/11/29 Daniel Vetter <daniel@ffwll.ch>:
> On Fri, Nov 29, 2013 at 11:05:49AM -0200, Rodrigo Vivi wrote:
>> I think this one and last one could be only one patch, but anyway:
>
> Yeah, agreed that the split doesn't make too much sense. What I'd really
> like to see in these commits (and also all the following ones that
> sprinkle runtime pm get/put calls all over the place) is a reference to
> the relevant subtest. And with that a natural way to split stuff would be
> so that each patch adds the get/put calls for a given feature and hence
> testcase.

That's what I did. I guess I just failed at properly communicating it.

Patch 7 is the very basic thing. If you don't have it, as soon as you
enter D3 you'll hit dozens of WARNs and errors. I guess we can say it
fixes the "rte" subtest of pm_pc8.

Patch 8 is just for the sysfs and debugfs stuff. It fixes the
"debugfs-read", "debugfs-forcewake-user" and "sysfs-read" subtests.

I don't think merging both patches in a single one is good because of
rebasing hell. Our code changes way too much for me to try to keep
giant patches around. If needed, I could try to split patch 8 into
smaller ones.


>
> I don't care too much about the split since it's all disabled by default,
> so as-is is imo ok. But the tests should be mentioned. That applies in
> general btw: If there's a specific igt testcase for a feature or bugfix,
> the kernel commit message should mention the testname.

I agree with this, but the problem is that while you're doing the very
early enabling work of a feature you tend to do so many changes that
you lose track of everything. Also, you change the test suite too. For
patches after the commit that really enables the feature, listing the
test case name is a must-have, and I hope I did this :)

>
> If people want, we could use a standardized patter like
>
> IGT-Testcase: igt/pm_pc8/gem_mmap_check

I'd love to have something like that! Any tag format works for me, as
long as we use it consistently.


Thanks for the reviews!
Paulo


>
> or something like that.



>
> Cheers, Daniel
>>
>> Reviewed-by Rodrigo Vivi <rodrigo.vivi@gmail.com>
>>
>> On Wed, Nov 27, 2013 at 06:21:54PM -0200, Paulo Zanoni wrote:
>> > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> >
>> > These are needed when we cat the debugfs and sysfs files.
>> >
>> > V2: - Rebase
>> > V3: - Rebase
>> > V4: - Rebase
>> >
>> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/i915_debugfs.c | 45 ++++++++++++++++++++++++++++++++++---
>> >  drivers/gpu/drm/i915/i915_sysfs.c   | 14 ++++++++++--
>> >  drivers/gpu/drm/i915/intel_dp.c     | 11 +++++++--
>> >  drivers/gpu/drm/i915/intel_panel.c  |  3 +++
>> >  drivers/gpu/drm/i915/intel_uncore.c |  4 ++++
>> >  5 files changed, 70 insertions(+), 7 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> > index 13accf7..6badc15 100644
>> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> > @@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     for_each_ring(ring, dev_priv, i)
>> >             i915_ring_seqno_info(m, ring);
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     return 0;
>> > @@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     if (INTEL_INFO(dev)->gen >= 8) {
>> >             int i;
>> > @@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>> >             }
>> >             i915_ring_seqno_info(m, ring);
>> >     }
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     return 0;
>> > @@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     crstanddelay = I915_READ16(CRSTANDVID);
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
>> > @@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>> >     struct drm_info_node *node = (struct drm_info_node *) m->private;
>> >     struct drm_device *dev = node->minor->dev;
>> >     drm_i915_private_t *dev_priv = dev->dev_private;
>> > -   int ret;
>> > +   int ret = 0;
>> > +
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     flush_delayed_work(&dev_priv->rps.delayed_resume_work);
>> >
>> > @@ -945,7 +953,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>> >             /* RPSTAT1 is in the GT power well */
>> >             ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >             if (ret)
>> > -                   return ret;
>> > +                   goto out;
>> >
>> >             gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
>> >
>> > @@ -1033,7 +1041,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
>> >             seq_puts(m, "no P-state info available\n");
>> >     }
>> >
>> > -   return 0;
>> > +out:
>> > +   intel_runtime_pm_put(dev_priv);
>> > +   return ret;
>> >  }
>> >
>> >  static int i915_delayfreq_table(struct seq_file *m, void *unused)
>> > @@ -1047,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     for (i = 0; i < 16; i++) {
>> >             delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
>> > @@ -1054,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
>> >                        (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
>> >     }
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> > +
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     return 0;
>> > @@ -1075,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     for (i = 1; i <= 32; i++) {
>> >             inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
>> >             seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
>> >     }
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     return 0;
>> > @@ -1098,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     rgvmodectl = I915_READ(MEMMODECTL);
>> >     rstdbyctl = I915_READ(RSTDBYCTL);
>> >     crstandvid = I915_READ16(CRSTANDVID);
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
>> > @@ -1166,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     spin_lock_irq(&dev_priv->uncore.lock);
>> >     forcewake_count = dev_priv->uncore.forcewake_count;
>> > @@ -1191,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
>> >     sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
>> >     mutex_unlock(&dev_priv->rps.hw_lock);
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> > +
>> >     seq_printf(m, "Video Turbo Mode: %s\n",
>> >                yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
>> >     seq_printf(m, "HW control enabled: %s\n",
>> > @@ -1405,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>> >     ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
>> >
>> > @@ -1421,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>> >                        ((ia_freq >> 8) & 0xff) * 100);
>> >     }
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev_priv->rps.hw_lock);
>> >
>> >     return 0;
>> > @@ -1436,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
>> > +   intel_runtime_pm_put(dev_priv);
>> >
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> > @@ -1617,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
>> >                swizzle_string(dev_priv->mm.bit_6_swizzle_x));
>> > @@ -1648,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
>> >             seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
>> >                        I915_READ(DISP_ARB_CTL));
>> >     }
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     return 0;
>> > @@ -1708,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
>> >  {
>> >     struct drm_info_node *node = (struct drm_info_node *) m->private;
>> >     struct drm_device *dev = node->minor->dev;
>> > +   struct drm_i915_private *dev_priv = dev->dev_private;
>> >
>> >     int ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     if (INTEL_INFO(dev)->gen >= 8)
>> >             gen8_ppgtt_info(m, dev);
>> >     else if (INTEL_INFO(dev)->gen >= 6)
>> >             gen6_ppgtt_info(m, dev);
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     return 0;
>> > @@ -1791,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>> >     u32 psrperf = 0;
>> >     bool enabled = false;
>> >
>> > +   intel_runtime_pm_get(dev_priv);
>> > +
>> >     seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
>> >     seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
>> >
>> > @@ -1803,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>> >                     EDP_PSR_PERF_CNT_MASK;
>> >     seq_printf(m, "Performance_Counter: %u\n", psrperf);
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     return 0;
>> >  }
>> >
>> > @@ -3016,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >
>> >     snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
>> > +
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev_priv->dev->struct_mutex);
>> >
>> >     *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
>> > @@ -3038,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val)
>> >     if (val > 3)
>> >             return -EINVAL;
>> >
>> > +   intel_runtime_pm_get(dev_priv);
>> >     DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
>> >
>> >     /* Update the cache sharing policy here as well */
>> > @@ -3046,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val)
>> >     snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
>> >     I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
>> >
>> > +   intel_runtime_pm_put(dev_priv);
>> >     return 0;
>> >  }
>> >
>> > @@ -3061,6 +3098,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
>> >     if (INTEL_INFO(dev)->gen < 6)
>> >             return 0;
>> >
>> > +   intel_runtime_pm_get(dev_priv);
>> >     gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
>> >
>> >     return 0;
>> > @@ -3075,6 +3113,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
>> >             return 0;
>> >
>> >     gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
>> > +   intel_runtime_pm_put(dev_priv);
>> >
>> >     return 0;
>> >  }
>> > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
>> > index 05d8b16..33bcae3 100644
>> > --- a/drivers/gpu/drm/i915/i915_sysfs.c
>> > +++ b/drivers/gpu/drm/i915/i915_sysfs.c
>> > @@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>> >     struct drm_i915_private *dev_priv = dev->dev_private;
>> >     u64 raw_time; /* 32b value may overflow during fixed point math */
>> >     u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
>> > +   u32 ret;
>> >
>> >     if (!intel_enable_rc6(dev))
>> >             return 0;
>> >
>> > +   intel_runtime_pm_get(dev_priv);
>> > +
>> >     /* On VLV, residency time is in CZ units rather than 1.28us */
>> >     if (IS_VALLEYVIEW(dev)) {
>> >             u32 clkctl2;
>> > @@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>> >                     CLK_CTL2_CZCOUNT_30NS_SHIFT;
>> >             if (!clkctl2) {
>> >                     WARN(!clkctl2, "bogus CZ count value");
>> > -                   return 0;
>> > +                   ret = 0;
>> > +                   goto out;
>> >             }
>> >             units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
>> >             if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
>> > @@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
>> >     }
>> >
>> >     raw_time = I915_READ(reg) * units;
>> > -   return DIV_ROUND_UP_ULL(raw_time, div);
>> > +   ret = DIV_ROUND_UP_ULL(raw_time, div);
>> > +
>> > +out:
>> > +   intel_runtime_pm_put(dev_priv);
>> > +   return ret;
>> >  }
>> >
>> >  static ssize_t
>> > @@ -448,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
>> >     ret = mutex_lock_interruptible(&dev->struct_mutex);
>> >     if (ret)
>> >             return ret;
>> > +   intel_runtime_pm_get(dev_priv);
>> >     rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
>> > +   intel_runtime_pm_put(dev_priv);
>> >     mutex_unlock(&dev->struct_mutex);
>> >
>> >     if (attr == &dev_attr_gt_RP0_freq_mhz) {
>> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> > index 1e372d5..28fc070 100644
>> > --- a/drivers/gpu/drm/i915/intel_dp.c
>> > +++ b/drivers/gpu/drm/i915/intel_dp.c
>> > @@ -3082,9 +3082,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>> >     struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>> >     struct intel_encoder *intel_encoder = &intel_dig_port->base;
>> >     struct drm_device *dev = connector->dev;
>> > +   struct drm_i915_private *dev_priv = dev->dev_private;
>> >     enum drm_connector_status status;
>> >     struct edid *edid = NULL;
>> >
>> > +   intel_runtime_pm_get(dev_priv);
>> > +
>> >     DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>> >                   connector->base.id, drm_get_connector_name(connector));
>> >
>> > @@ -3096,7 +3099,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>> >             status = g4x_dp_detect(intel_dp);
>> >
>> >     if (status != connector_status_connected)
>> > -           return status;
>> > +           goto out;
>> >
>> >     intel_dp_probe_oui(intel_dp);
>> >
>> > @@ -3112,7 +3115,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>> >
>> >     if (intel_encoder->type != INTEL_OUTPUT_EDP)
>> >             intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
>> > -   return connector_status_connected;
>> > +   status = connector_status_connected;
>> > +
>> > +out:
>> > +   intel_runtime_pm_put(dev_priv);
>> > +   return status;
>> >  }
>> >
>> >  static int intel_dp_get_modes(struct drm_connector *connector)
>> > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>> > index e480cf4..4b7925b 100644
>> > --- a/drivers/gpu/drm/i915/intel_panel.c
>> > +++ b/drivers/gpu/drm/i915/intel_panel.c
>> > @@ -845,11 +845,14 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
>> >  {
>> >     struct intel_connector *connector = bl_get_data(bd);
>> >     struct drm_device *dev = connector->base.dev;
>> > +   struct drm_i915_private *dev_priv = dev->dev_private;
>> >     int ret;
>> >
>> > +   intel_runtime_pm_get(dev_priv);
>> >     mutex_lock(&dev->mode_config.mutex);
>> >     ret = intel_panel_get_backlight(connector);
>> >     mutex_unlock(&dev->mode_config.mutex);
>> > +   intel_runtime_pm_put(dev_priv);
>> >
>> >     return ret;
>> >  }
>> > diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
>> > index 00e5ced..2d745a6 100644
>> > --- a/drivers/gpu/drm/i915/intel_uncore.c
>> > +++ b/drivers/gpu/drm/i915/intel_uncore.c
>> > @@ -366,6 +366,8 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
>> >     if (!dev_priv->uncore.funcs.force_wake_get)
>> >             return;
>> >
>> > +   intel_runtime_pm_get(dev_priv);
>> > +
>> >     /* Redirect to VLV specific routine */
>> >     if (IS_VALLEYVIEW(dev_priv->dev))
>> >             return vlv_force_wake_get(dev_priv, fw_engine);
>> > @@ -399,6 +401,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
>> >                              1);
>> >     }
>> >     spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
>> > +
>> > +   intel_runtime_pm_put(dev_priv);
>> >  }
>> >
>> >  /* We give fast paths for the really cool registers */
>> > --
>> > 1.8.3.1
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on
  2013-11-29 13:50   ` Rodrigo Vivi
@ 2013-11-29 13:59     ` Paulo Zanoni
  2013-11-29 14:37       ` Rodrigo Vivi
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-11-29 13:59 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: Intel Graphics Development, Paulo Zanoni

2013/11/29 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> On Thu, Nov 21, 2013 at 01:47:23PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> And put it when it's off. Otherwise, when you run pm_pc8 from
>> intel-gpu-tools, and the delayed function that disables VDD runs,
>> we'll get some messages saying we're touching registers while the HW
>> is suspended.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/intel_dp.c | 7 +++++++
>>  1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 28fc070..9e9e3d6 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -1092,6 +1092,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
>>       if (ironlake_edp_have_panel_vdd(intel_dp))
>>               return;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       DRM_DEBUG_KMS("Turning eDP VDD on\n");
>>
>>       if (!ironlake_edp_have_panel_power(intel_dp))
>> @@ -1141,6 +1143,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
>>               DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
>>               I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
>>               msleep(intel_dp->panel_power_down_delay);
>> +
>> +             intel_runtime_pm_put(dev_priv);
>>       }
>>  }
>>
>> @@ -1248,6 +1252,9 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
>>       intel_dp->want_panel_vdd = false;
>>
>>       ironlake_wait_panel_off(intel_dp);
>> +
>> +     /* We got a reference when we enabled the VDD. */
>> +     intel_runtime_pm_put(dev_priv);
>
> I was going to say it was missing a get until I read the comment above.
> But if it gets on VDD on, why not just let it put back on VDD off instead?

That's the goal of my series. See patches 15 and 16.

>
>>  }
>>
>>  void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-11-27 20:10   ` Paulo Zanoni
  2013-11-29 12:54     ` Rodrigo Vivi
@ 2013-11-29 14:05     ` Takashi Iwai
  2013-12-06 22:31       ` Paulo Zanoni
  1 sibling, 1 reply; 97+ messages in thread
From: Takashi Iwai @ 2013-11-29 14:05 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

At Wed, 27 Nov 2013 18:10:30 -0200,
Paulo Zanoni wrote:
> 
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> This patch adds the initial infrastructure to allow a Runtime PM
> implementation that sets the device to its D3 state. The patch just
> adds the necessary callbacks and the initial infrastructure.
> 
> We still don't have any platform that actually uses this
> infrastructure, we still don't call get/put in all the places we need
> to, and we don't have any function to save/restore the state of the
> registers. This is not a problem since no platform uses the code added
> by this patch. We have a few people simultaneously working on runtime
> PM, so this initial code could help everybody make their plans.
> 
> V2: - Move some functions to intel_pm.c
>     - Remove useless pm_runtime_allow() call at init
>     - Remove useless pm_runtime_mark_last_busy() call at get
>     - Use pm_runtime_get_sync() instead of 2 calls
>     - Add a WARN to check if we're really awake
> 
> V3: - Rebase.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
>  drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
>  drivers/gpu/drm/i915/intel_drv.h    |  4 +++
>  drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
>  6 files changed, 124 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 89e4cf1..4cdc1ee 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -42,6 +42,8 @@
>  #include <linux/vga_switcheroo.h>
>  #include <linux/slab.h>
>  #include <acpi/video.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
>  
>  #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
>  
> @@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  	if (IS_GEN5(dev))
>  		intel_gpu_ips_init(dev_priv);
>  
> +	intel_init_runtime_pm(dev_priv);
> +
>  	return 0;
>  
>  out_power_well:
> @@ -1702,6 +1706,8 @@ int i915_driver_unload(struct drm_device *dev)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	intel_fini_runtime_pm(dev_priv);
> +
>  	intel_gpu_ips_teardown();
>  
>  	/* The i915.ko module is still not prepared to be loaded when
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 0ec0fb3..d5310a0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_crtc *crtc;
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* ignore lid events during suspend */
>  	mutex_lock(&dev_priv->modeset_restore_lock);
>  	dev_priv->modeset_restore = MODESET_SUSPENDED;
> @@ -688,6 +690,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
>  	mutex_lock(&dev_priv->modeset_restore_lock);
>  	dev_priv->modeset_restore = MODESET_DONE;
>  	mutex_unlock(&dev_priv->modeset_restore_lock);
> +
> +	intel_runtime_pm_put(dev_priv);
>  	return error;
>  }
>  
> @@ -902,6 +906,42 @@ static int i915_pm_poweroff(struct device *dev)
>  	return i915_drm_freeze(drm_dev);
>  }
>  
> +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));

It'd be better to add runtime_idle callback for this kind of checks.
It's called always before actually doing runtime PM, and you can
return -EBUSY if the runtime PM isn't available.


> +	DRM_DEBUG_KMS("Suspending device\n");
> +
> +	dev_priv->pm.suspended = true;
> +
> +	pci_save_state(pdev);
> +	pci_set_power_state(pdev, PCI_D3cold);

Why do you need these calls?  PCI runtime PM core should already
handle the power state change by itself.


Takashi

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled
  2013-11-21 15:47 ` [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled Paulo Zanoni
@ 2013-11-29 14:30   ` Rodrigo Vivi
  2013-12-10 21:54   ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 14:30 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Thu, Nov 21, 2013 at 01:47:24PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> The current code was checking if all bits of "val" were enabled and
> DE_PCH_EVENT_IVB was disabled. The new code doesn't care about the
> state of DE_PCH_EVENT_IVB: it just checks if everything else is 1.
> 
> The goal is that future patches may completely disable interrupts, and
> the LCPLL-disabling code shouldn't care about the state of
> DE_PCH_EVENT_IVB.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 846f2de..95e8831 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6499,7 +6499,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
>  
>  	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>  	val = I915_READ(DEIMR);
> -	WARN((val & ~DE_PCH_EVENT_IVB) != val,
> +	WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,
>  	     "Unexpected DEIMR bits enabled: 0x%x\n", val);
>  	val = I915_READ(SDEIMR);
>  	WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on
  2013-11-29 13:59     ` Paulo Zanoni
@ 2013-11-29 14:37       ` Rodrigo Vivi
  2013-12-06 22:23         ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 14:37 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni

On Fri, Nov 29, 2013 at 11:59 AM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2013/11/29 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> On Thu, Nov 21, 2013 at 01:47:23PM -0200, Paulo Zanoni wrote:
>>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>
>>> And put it when it's off. Otherwise, when you run pm_pc8 from
>>> intel-gpu-tools, and the delayed function that disables VDD runs,
>>> we'll get some messages saying we're touching registers while the HW
>>> is suspended.
>>>
>>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>> ---
>>>  drivers/gpu/drm/i915/intel_dp.c | 7 +++++++
>>>  1 file changed, 7 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>>> index 28fc070..9e9e3d6 100644
>>> --- a/drivers/gpu/drm/i915/intel_dp.c
>>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>>> @@ -1092,6 +1092,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
>>>       if (ironlake_edp_have_panel_vdd(intel_dp))
>>>               return;
>>>
>>> +     intel_runtime_pm_get(dev_priv);
>>> +
>>>       DRM_DEBUG_KMS("Turning eDP VDD on\n");
>>>
>>>       if (!ironlake_edp_have_panel_power(intel_dp))
>>> @@ -1141,6 +1143,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
>>>               DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
>>>               I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
>>>               msleep(intel_dp->panel_power_down_delay);
>>> +
>>> +             intel_runtime_pm_put(dev_priv);
>>>       }
>>>  }
>>>
>>> @@ -1248,6 +1252,9 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
>>>       intel_dp->want_panel_vdd = false;
>>>
>>>       ironlake_wait_panel_off(intel_dp);
>>> +
>>> +     /* We got a reference when we enabled the VDD. */
>>> +     intel_runtime_pm_put(dev_priv);
>>
>> I was going to say it was missing a get until I read the comment above.
>> But if it gets on VDD on, why not just let it put back on VDD off instead?
>
> That's the goal of my series. See patches 15 and 16.

I saw both and got your point, but even after them get and put doesn't
look in a symmetric place for me.

wouldn't make sense on this patch remove both of _put here and add one
in vdd_off?
Even after your vdd fixes it would be symmetric.

>
>>
>>>  }
>>>
>>>  void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
>>> --
>>> 1.8.3.1
>>>
>>> _______________________________________________
>>> Intel-gfx mailing list
>>> Intel-gfx@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 15/19] drm/i915: don't enable VDD just to enable the panel
  2013-11-21 15:47 ` [PATCH 15/19] drm/i915: don't enable VDD just to enable the panel Paulo Zanoni
@ 2013-11-29 14:40   ` Rodrigo Vivi
  0 siblings, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 14:40 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

I'm just not sure if it won't regress in any other platform... Just
wondering why it was added in this way.... But..

makes sense so feel free to use:
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>


On Thu, Nov 21, 2013 at 1:47 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> We just don't need this. This saves 250ms from every modeset on my
> machine.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 731a919..e868f5f 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1122,9 +1122,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
>
>         if (type == INTEL_OUTPUT_EDP) {
>                 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -               ironlake_edp_panel_vdd_on(intel_dp);
>                 ironlake_edp_panel_on(intel_dp);
> -               ironlake_edp_panel_vdd_off(intel_dp, true);
>         }
>
>         WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
> --
> 1.8.3.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 16/19] drm/i915: don't touch the VDD when disabling the panel
  2013-11-21 15:47 ` [PATCH 16/19] drm/i915: don't touch the VDD when disabling " Paulo Zanoni
@ 2013-11-29 14:41   ` Rodrigo Vivi
  0 siblings, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-11-29 14:41 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

with or without my bikeshed on patch 10 and with same regress concern
than patch 15,
feel free to use  Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>


On Thu, Nov 21, 2013 at 1:47 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> I don't see a reason to touch VDD when we're disabling the panel:
> since the panel is enabled, we don't need VDD. This saves a few sleep
> calls from the vdd_on and vdd_off functions at every modeset.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c |  1 -
>  drivers/gpu/drm/i915/intel_dp.c  | 10 +---------
>  2 files changed, 1 insertion(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index e868f5f..5fc4b9e 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1165,7 +1165,6 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
>
>         if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
>                 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -               ironlake_edp_panel_vdd_on(intel_dp);
>                 intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>                 ironlake_edp_panel_off(intel_dp);
>         }
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 9e9e3d6..c2a89b2 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1237,24 +1237,17 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
>
>         DRM_DEBUG_KMS("Turn eDP power off\n");
>
> -       WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
> -
>         pp = ironlake_get_pp_control(intel_dp);
>         /* We need to switch off panel power _and_ force vdd, for otherwise some
>          * panels get very unhappy and cease to work. */
> -       pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
> +       pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
>
>         pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
>
>         I915_WRITE(pp_ctrl_reg, pp);
>         POSTING_READ(pp_ctrl_reg);
>
> -       intel_dp->want_panel_vdd = false;
> -
>         ironlake_wait_panel_off(intel_dp);
> -
> -       /* We got a reference when we enabled the VDD. */
> -       intel_runtime_pm_put(dev_priv);
>  }
>
>  void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
> @@ -1779,7 +1772,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
>
>         /* Make sure the panel is off before trying to change the mode. But also
>          * ensure that we have vdd while we switch off the panel. */
> -       ironlake_edp_panel_vdd_on(intel_dp);
>         ironlake_edp_backlight_off(intel_dp);
>         intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>         ironlake_edp_panel_off(intel_dp);
> --
> 1.8.3.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 13/19] drm: do not steal the display if we have a master
  2013-11-27 20:24     ` Paulo Zanoni
  2013-11-29 13:37       ` Daniel Vetter
@ 2013-11-30 11:19       ` David Herrmann
  1 sibling, 0 replies; 97+ messages in thread
From: David Herrmann @ 2013-11-30 11:19 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni, dri-devel

Hi

On Wed, Nov 27, 2013 at 9:24 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Sometimes we want to disable all the screens on a system, because that
> will allow the graphics card to be put into low-power states. The
> problem is that, for example, while all screens are disabled, if we
> get a hotplug interrupt, fbcon will decide to set a mode instead of
> keeping everything disabled, which will remove us from our low power
> states.
>
> Let's assume that if there's a DRM master, it will be able to do
> whatever is appropriate when we get the hotplug.
>
> This problem can be reproduced by the runtime PM test program from
> intel-gpu-tools: we disable all the screens so the graphics device can
> be put into D3, then something triggers a hotplug interrupt, fbcon
> sets a mode and breaks our test suite. The problem can be reproduced
> more easily by the "i2c" subtest.
>
> Other approaches considered for the problem:
>     - Return "false" if "bound == 0" and the caller of
>       drm_fb_helper_is_bound is a hotplug handler. This would break
>       the case where the machine boots with no outputs connected, then
>       the user plugs a monitor.
>     - Add a new IOCTL to force fbcon to not set modes. This would keep
>       all the current applications behaving the same, but adding a new
>       IOCTL is not always the greatest idea.
>     - Return false only if "dev->primary->master && bound == 0". This
>       was my first implementation, but Chris suggested we should do
>       the check irrespective of the "bound" variable.
>
> Thanks to Daniel Vetter for the investigation, ideas and the
> implementation of the hotplug alternative.
>
> v2: - Do the check first, irrespective of "bound".
>     - Cc dri-devel

Thank god all that will get dropped with CONFIG_FB=n. Anyhow:

Reviewed-by: David Herrmann <dh.herrmann@gmail.com>

Thanks
David

> Cc: dri-devel@lists.freedesktop.org
> Credits-to: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/drm_fb_helper.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 0a19401..98a0363 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -359,6 +359,11 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
>         struct drm_crtc *crtc;
>         int bound = 0, crtcs_bound = 0;
>
> +       /* Sometimes user space wants everything disabled, so don't steal the
> +        * display if there's a master. */
> +       if (dev->primary->master)
> +               return false;
> +
>         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
>                 if (crtc->fb)
>                         crtcs_bound++;
> @@ -368,6 +373,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
>
>         if (bound < crtcs_bound)
>                 return false;
> +
>         return true;
>  }
>
> --
> 1.8.3.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-11-21 15:47 ` [PATCH 05/19] drm/i915: add initial Runtime PM functions Paulo Zanoni
  2013-11-27 20:10   ` Paulo Zanoni
@ 2013-12-02 12:23   ` Imre Deak
  1 sibling, 0 replies; 97+ messages in thread
From: Imre Deak @ 2013-12-02 12:23 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni


[-- Attachment #1.1: Type: text/plain, Size: 5149 bytes --]

On Thu, 2013-11-21 at 13:47 -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> This patch adds the initial infrastructure to allow a Runtime PM
> implementation that sets the device to its D3 state. The patch just
> adds the necessary callbacks and the initial infrastructure.
> 
> We still don't have any platform that actually uses this
> infrastructure, we still don't call get/put in all the places we need
> to, and we don't have any function to save/restore the state of the
> registers. This is not a problem since no platform uses the code added
> by this patch. We have a few people simultaneously working on runtime
> PM, so this initial code could help everybody make their plans.
> 
> V2: - Move some functions to intel_pm.c
>     - Remove useless pm_runtime_allow() call at init
>     - Remove useless pm_runtime_mark_last_busy() call at get
>     - Use pm_runtime_get_sync() instead of 2 calls
>     - Add a WARN to check if we're really awake
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
>  drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
>  drivers/gpu/drm/i915/intel_drv.h    |  4 +++
>  drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
>  6 files changed, 124 insertions(+)
> [...]
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 6bd0fc6..ef5e274 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -31,6 +31,7 @@
>  #include "../../../platform/x86/intel_ips.h"
>  #include <linux/module.h>
>  #include <drm/i915_powerwell.h>
> +#include <linux/pm_runtime.h>
>  
>  /**
>   * RC6 is a special power stage which allows the GPU to enter an very
> @@ -5878,6 +5879,61 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
>  	hsw_enable_package_c8(dev_priv);
>  }
>  
> +void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	pm_runtime_get_sync(device);
> +	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
> +}
> +
> +void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	pm_runtime_mark_last_busy(device);
> +	pm_runtime_put_autosuspend(device);
> +}
> +
> +void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	dev_priv->pm.suspended = false;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	pm_runtime_set_active(device);
> +	pm_runtime_enable(device);

This will generate a warning as you get here with an already enabled
state.

--Imre

> +	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
> +	pm_runtime_mark_last_busy(device);
> +	pm_runtime_use_autosuspend(device);
> +}
> +
> +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct device *device = &dev->pdev->dev;
> +
> +	if (!HAS_RUNTIME_PM(dev))
> +		return;
> +
> +	/* Make sure we're not suspended first. */
> +	pm_runtime_get_sync(device);
> +	pm_runtime_disable(device);
> +}
> +
>  /* Set up chip specific power management-related functions */
>  void intel_init_pm(struct drm_device *dev)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> index eac5661..ddd9084 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -346,6 +346,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
>  	}
>  }
>  
> +static void
> +assert_device_not_suspended(struct drm_i915_private *dev_priv)
> +{
> +	WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
> +	     "Device suspended\n");
> +}
> +
>  #define REG_READ_HEADER(x) \
>  	unsigned long irqflags; \
>  	u##x val = 0; \
> @@ -438,6 +445,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
>  	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
>  		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
>  	} \
> +	assert_device_not_suspended(dev_priv); \
>  	__raw_i915_write##x(dev_priv, reg, val); \
>  	if (unlikely(__fifo_ret)) { \
>  		gen6_gt_check_fifodbg(dev_priv); \
> @@ -453,6 +461,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
>  	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
>  		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
>  	} \
> +	assert_device_not_suspended(dev_priv); \
>  	hsw_unclaimed_reg_clear(dev_priv, reg); \
>  	__raw_i915_write##x(dev_priv, reg, val); \
>  	if (unlikely(__fifo_ret)) { \


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 11/19] drm/i915: disable interrupts when enabling PC8
  2013-11-21 15:47 ` [PATCH 11/19] drm/i915: disable interrupts when enabling PC8 Paulo Zanoni
@ 2013-12-02 13:33   ` Rodrigo Vivi
  2013-12-10 21:59   ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Rodrigo Vivi @ 2013-12-02 13:33 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Thu, Nov 21, 2013 at 1:47 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> The plan is to merge PC8 and D3 into a single feature, and when we're
> in D3 we won't get any hotplug interrupt anyway, so leaving them
> enable doesn't make sense, and it also brings us a problem. The
> problem is that we get a hotplug interrupt right when we we wake up
> from D3, when we're still waking up everything. If we fully disable
> interrupts we won't get this hotplug interrupt, so we won't have
> problems.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_irq.c | 26 +++++++++-----------------
>  1 file changed, 9 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 70c4cef..d0f4e61 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -3902,8 +3902,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
>         dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
>         dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
>
> -       ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
> -       ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
> +       ironlake_disable_display_irq(dev_priv, 0xffffffff);
> +       ibx_disable_display_interrupt(dev_priv, 0xffffffff);
>         ilk_disable_gt_irq(dev_priv, 0xffffffff);
>         snb_disable_pm_irq(dev_priv, 0xffffffff);
>
> @@ -3917,34 +3917,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         unsigned long irqflags;
> -       uint32_t val, expected;
> +       uint32_t val;
>
>         spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>
>         val = I915_READ(DEIMR);
> -       expected = ~DE_PCH_EVENT_IVB;
> -       WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
> +       WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
>
> -       val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
> -       expected = ~SDE_HOTPLUG_MASK_CPT;
> -       WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
> -            val, expected);
> +       val = I915_READ(SDEIMR);
> +       WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
>
>         val = I915_READ(GTIMR);
> -       expected = 0xffffffff;
> -       WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
> +       WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
>
>         val = I915_READ(GEN6_PMIMR);
> -       expected = 0xffffffff;
> -       WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
> -            expected);
> +       WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
>
>         dev_priv->pc8.irqs_disabled = false;
>
>         ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
> -       ibx_enable_display_interrupt(dev_priv,
> -                                    ~dev_priv->pc8.regsave.sdeimr &
> -                                    ~SDE_HOTPLUG_MASK_CPT);
> +       ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
>         ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
>         snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
>         I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
> --
> 1.8.3.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 14/19] drm/i915: add runtime PM support on Haswell
  2013-11-21 15:47 ` [PATCH 14/19] drm/i915: add runtime PM support on Haswell Paulo Zanoni
@ 2013-12-02 13:37   ` Rodrigo Vivi
  2013-12-10 22:10     ` Daniel Vetter
  2013-12-10 22:06   ` Daniel Vetter
  1 sibling, 1 reply; 97+ messages in thread
From: Rodrigo Vivi @ 2013-12-02 13:37 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 1:47 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> The code to enable/disable PC8 already takes care of saving and
> restoring all the registers we need to save/restore, so do a put()
> call when we enable PC8 and a get() call when we disable it.
>
> Ideally, in order to make it easier to add runtime PM support to other
> platforms, we should move some things from the PC8 code to the runtime
> PM code, but let's do this later, since we can make Haswell work right
> now.
>
> V2: - Rebase
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      | 2 +-
>  drivers/gpu/drm/i915/intel_display.c | 4 ++++
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3702746..002b99d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1836,7 +1836,7 @@ struct drm_i915_file_private {
>  #define HAS_FPGA_DBG_UNCLAIMED(dev)    (INTEL_INFO(dev)->has_fpga_dbg)
>  #define HAS_PSR(dev)           (IS_HASWELL(dev) || IS_BROADWELL(dev))
>  #define HAS_PC8(dev)           (IS_HASWELL(dev)) /* XXX HSW:ULX */
> -#define HAS_RUNTIME_PM(dev)    false
> +#define HAS_RUNTIME_PM(dev)    (IS_HASWELL(dev))
>
>  #define INTEL_PCH_DEVICE_ID_MASK               0xff00
>  #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 95e8831..820013a 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6641,6 +6641,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
>         lpt_disable_clkout_dp(dev);
>         hsw_pc8_disable_interrupts(dev);
>         hsw_disable_lcpll(dev_priv, true, true);
> +
> +       intel_runtime_pm_put(dev_priv);

Maybe this could be along with other put and get on previous patches
and let this patch just to really enable the runtime pm.
But anyway, feel free to use:
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

>  }
>
>  static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
> @@ -6678,6 +6680,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
>
>         DRM_DEBUG_KMS("Disabling package C8+\n");
>
> +       intel_runtime_pm_get(dev_priv);
> +
>         hsw_restore_lcpll(dev_priv);
>         hsw_pc8_restore_interrupts(dev);
>         lpt_init_pch_refclk(dev);
> --
> 1.8.3.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-11-21 15:47 ` [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC Paulo Zanoni
  2013-11-21 16:12   ` Chris Wilson
@ 2013-12-04  9:01   ` Daniel Vetter
  2013-12-04 13:44     ` Paulo Zanoni
  1 sibling, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2013-12-04  9:01 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:18PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Currently, PC8 is enabled at modeset_global_resources, which is called
> after intel_modeset_update_state. Due to this, there's a small race
> condition on the case where we start enabling PC8, then do a modeset
> while PC8 is still being enabled. The racing condition triggers a WARN
> because intel_modeset_update_state will mark the CRTC as enabled, then
> the thread that's still enabling PC8 might look at the data structure
> and think that PC8 is being enabled while a pipe is enabled. Despite
> the WARN, this is not really a bug since we'll wait for the
> PC8-enabling thread to finish when we call modeset_global_resources.
> 
> So this patch makes sure we get/put PC8 before we update
> drm_crtc->enabled, because if a get() call triggers a PC8 disable,
> we'll call cancel_delayed_work_sync(), which will wait for the thread
> that's enabling PC8, then, after this, we'll disable PC8.
> 
> The side-effect benefit of this patch is that we have a nice place to
> track enabled/disabled CRTCs, so we may want to move some code from
> modeset_global_resources to intel_crtc_set_state in the future.
> 
> The problem fixed by this patch can be reproduced by the
> modeset-lpsp-stress-no-wait subtest from the pc8 test of
> intel-gpu-tools.
> 
> v2: - No need for pc8.lock since we already have
>       cancel_delayed_work_sync().
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Now that Imre's big rework has landed this looks a bit strange. We now
have the display power wells (properly refcounted) and the hsw pc8 stuff
here. Which imo doesn't make much sense since to have a working display
power well we can't go into pc8.

So the right thing to do is to only grab the topmost power well/domain
reference. Those in turn then need to grab the lower-level domains. I.e.
on hsw the crtc get/put should also do a pc8 get/put and then that in turn
should do a D3 get/put (if we keep them split up).

With that change it'd also make tons of sense to move all the hsw pc8
stuff into intel_pm.c together with the other power well stuff. Imo the
approach with use_count in Imre's code is easier to understand.

Now for the actual issue you're trying to fix here: That's just a race in
the check in assert_can_disable_lcpll - you access crtc->base.enabled
without taking the right locks. And if the work runs concurrently to
re-enabling the display power then it'll get confused. The other issue
with this check is that crtc->base.enabled is the wrong thing to check: It
only tracks sw state, e.g. it's still set when we're in dpms off mode. The
right thing to check would be crtc->active, and for that one we have the
correct ordering between get/put calls and updating the field already.

Plan B would be to just ditch this check.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-12-04  9:01   ` Daniel Vetter
@ 2013-12-04 13:44     ` Paulo Zanoni
  2013-12-04 14:07       ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-04 13:44 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development, Paulo Zanoni

2013/12/4 Daniel Vetter <daniel@ffwll.ch>:
> On Thu, Nov 21, 2013 at 01:47:18PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> Currently, PC8 is enabled at modeset_global_resources, which is called
>> after intel_modeset_update_state. Due to this, there's a small race
>> condition on the case where we start enabling PC8, then do a modeset
>> while PC8 is still being enabled. The racing condition triggers a WARN
>> because intel_modeset_update_state will mark the CRTC as enabled, then
>> the thread that's still enabling PC8 might look at the data structure
>> and think that PC8 is being enabled while a pipe is enabled. Despite
>> the WARN, this is not really a bug since we'll wait for the
>> PC8-enabling thread to finish when we call modeset_global_resources.
>>
>> So this patch makes sure we get/put PC8 before we update
>> drm_crtc->enabled, because if a get() call triggers a PC8 disable,
>> we'll call cancel_delayed_work_sync(), which will wait for the thread
>> that's enabling PC8, then, after this, we'll disable PC8.
>>
>> The side-effect benefit of this patch is that we have a nice place to
>> track enabled/disabled CRTCs, so we may want to move some code from
>> modeset_global_resources to intel_crtc_set_state in the future.
>>
>> The problem fixed by this patch can be reproduced by the
>> modeset-lpsp-stress-no-wait subtest from the pc8 test of
>> intel-gpu-tools.
>>
>> v2: - No need for pc8.lock since we already have
>>       cancel_delayed_work_sync().
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Now that Imre's big rework has landed this looks a bit strange. We now
> have the display power wells (properly refcounted) and the hsw pc8 stuff
> here. Which imo doesn't make much sense since to have a working display
> power well we can't go into pc8.

This patch has nothing to do with power wells. We're checking
enabled/disabled CRTCs here, not power wells. The problem this patch
solves also happens on LPSP mode, where the power well is disabled.
I'm confused, please clarify.


>
> So the right thing to do is to only grab the topmost power well/domain
> reference. Those in turn then need to grab the lower-level domains. I.e.
> on hsw the crtc get/put should also do a pc8 get/put and then that in turn
> should do a D3 get/put (if we keep them split up).
>

Same as above.


> With that change it'd also make tons of sense to move all the hsw pc8
> stuff into intel_pm.c together with the other power well stuff. Imo the
> approach with use_count in Imre's code is easier to understand.
>
> Now for the actual issue you're trying to fix here: That's just a race in
> the check in assert_can_disable_lcpll - you access crtc->base.enabled
> without taking the right locks.

Which ones are the "right locks"?


> And if the work runs concurrently to
> re-enabling the display power then it'll get confused.

What exactly do you mean when you say "re-enabling the display power"?
Power wells?


> The other issue
> with this check is that crtc->base.enabled is the wrong thing to check: It
> only tracks sw state, e.g. it's still set when we're in dpms off mode. The
> right thing to check would be crtc->active, and for that one we have the
> correct ordering between get/put calls and updating the field already.

No, we only set crtc->active to true after we call
ironlake_crtc_enable, and that's too late for this specific bug. Also,
we don't enable PC8 nor disable power wells while in DPMS off, there's
a lot of work to do if we want to enable that, and this patch here is
just a bug fix.


>
> Plan B would be to just ditch this check.

The "crtc->base.enabled == enabled" check? That's not possible, it
would result in unbalanced get/put calls.


> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-12-04 13:44     ` Paulo Zanoni
@ 2013-12-04 14:07       ` Daniel Vetter
  2013-12-05 13:43         ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2013-12-04 14:07 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni

On Wed, Dec 4, 2013 at 2:44 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2013/12/4 Daniel Vetter <daniel@ffwll.ch>:
>> On Thu, Nov 21, 2013 at 01:47:18PM -0200, Paulo Zanoni wrote:
>>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>
>>> Currently, PC8 is enabled at modeset_global_resources, which is called
>>> after intel_modeset_update_state. Due to this, there's a small race
>>> condition on the case where we start enabling PC8, then do a modeset
>>> while PC8 is still being enabled. The racing condition triggers a WARN
>>> because intel_modeset_update_state will mark the CRTC as enabled, then
>>> the thread that's still enabling PC8 might look at the data structure
>>> and think that PC8 is being enabled while a pipe is enabled. Despite
>>> the WARN, this is not really a bug since we'll wait for the
>>> PC8-enabling thread to finish when we call modeset_global_resources.
>>>
>>> So this patch makes sure we get/put PC8 before we update
>>> drm_crtc->enabled, because if a get() call triggers a PC8 disable,
>>> we'll call cancel_delayed_work_sync(), which will wait for the thread
>>> that's enabling PC8, then, after this, we'll disable PC8.
>>>
>>> The side-effect benefit of this patch is that we have a nice place to
>>> track enabled/disabled CRTCs, so we may want to move some code from
>>> modeset_global_resources to intel_crtc_set_state in the future.
>>>
>>> The problem fixed by this patch can be reproduced by the
>>> modeset-lpsp-stress-no-wait subtest from the pc8 test of
>>> intel-gpu-tools.
>>>
>>> v2: - No need for pc8.lock since we already have
>>>       cancel_delayed_work_sync().
>>>
>>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> Now that Imre's big rework has landed this looks a bit strange. We now
>> have the display power wells (properly refcounted) and the hsw pc8 stuff
>> here. Which imo doesn't make much sense since to have a working display
>> power well we can't go into pc8.
>
> This patch has nothing to do with power wells. We're checking
> enabled/disabled CRTCs here, not power wells. The problem this patch
> solves also happens on LPSP mode, where the power well is disabled.
> I'm confused, please clarify.

With Imre's power well rework we now have two pieces that manage the
power state of the display hw: modeset_update_power_wells and
modeset_update_power_wells. The later is redundant since you can't
ever enable a crtc power well without disabling pc8.

Note that I'm talking about the generic display power wells Imre
added, which means we also track the power domain usage for crtc A.

My idea is to completely ditch the call to hsw_update_package_c8 and
shovel the respective pc8 get/put calls into the right power domains
in the haswell display power domain implementation in intel_pm.c. That
means that we need to adjust the always-on power well code a bit for
hsw.

In a way power domains should nest, and code should always only care
about the innermost power domain. If it needs to grab explicit
references for power domains outside of that the structure isn't quite
right.

>> So the right thing to do is to only grab the topmost power well/domain
>> reference. Those in turn then need to grab the lower-level domains. I.e.
>> on hsw the crtc get/put should also do a pc8 get/put and then that in turn
>> should do a D3 get/put (if we keep them split up).
>>
>
> Same as above.
>
>
>> With that change it'd also make tons of sense to move all the hsw pc8
>> stuff into intel_pm.c together with the other power well stuff. Imo the
>> approach with use_count in Imre's code is easier to understand.
>>
>> Now for the actual issue you're trying to fix here: That's just a race in
>> the check in assert_can_disable_lcpll - you access crtc->base.enabled
>> without taking the right locks.
>
> Which ones are the "right locks"?

crtc->mutex. It'll deadlock though due to the synchronous work
cancelling. If you go with lockless you'd need some barriers since the
implicit barriers in schedule_work and cancel_work aren't good enough
any more.

>> And if the work runs concurrently to
>> re-enabling the display power then it'll get confused.
>
> What exactly do you mean when you say "re-enabling the display power"?
> Power wells?

power domains in general, whether this is what bspec calls "display
ower well" or pc8 mode or something else. Specifically here the race
seems to happen with the pc8 domain though.

>> The other issue
>> with this check is that crtc->base.enabled is the wrong thing to check: It
>> only tracks sw state, e.g. it's still set when we're in dpms off mode. The
>> right thing to check would be crtc->active, and for that one we have the
>> correct ordering between get/put calls and updating the field already.
>
> No, we only set crtc->active to true after we call
> ironlake_crtc_enable, and that's too late for this specific bug. Also,
> we don't enable PC8 nor disable power wells while in DPMS off, there's
> a lot of work to do if we want to enable that, and this patch here is
> just a bug fix.

I mean the WARN check in assert_can_disable_lcpll, not the checks
you're touching in your patch. For actually deciding whether we can
allow pc8 or not we should imo piggy-pack on top of Imre's rework of
the display power domain handling.

Maybe we should go over the code and replace all mentions of
power_well with power_domain in the generic code to make this clearer.
Imo Imre's work isn't just about what Bspec calls "power wells" but
about managing display power domains in general. Which includes pc8.

>> Plan B would be to just ditch this check.
>
> The "crtc->base.enabled == enabled" check? That's not possible, it
> would result in unbalanced get/put calls.

I mean the check in assert_can_disable_lcpll for crtc->base.enabled,
not the ones you're touching in your patch here. Sorry for the unclear
"this" reference.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-12-04 14:07       ` Daniel Vetter
@ 2013-12-05 13:43         ` Paulo Zanoni
  2013-12-05 14:40           ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-05 13:43 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development, Paulo Zanoni

2013/12/4 Daniel Vetter <daniel@ffwll.ch>:
> On Wed, Dec 4, 2013 at 2:44 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> 2013/12/4 Daniel Vetter <daniel@ffwll.ch>:
>>> On Thu, Nov 21, 2013 at 01:47:18PM -0200, Paulo Zanoni wrote:
>>>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>>
>>>> Currently, PC8 is enabled at modeset_global_resources, which is called
>>>> after intel_modeset_update_state. Due to this, there's a small race
>>>> condition on the case where we start enabling PC8, then do a modeset
>>>> while PC8 is still being enabled. The racing condition triggers a WARN
>>>> because intel_modeset_update_state will mark the CRTC as enabled, then
>>>> the thread that's still enabling PC8 might look at the data structure
>>>> and think that PC8 is being enabled while a pipe is enabled. Despite
>>>> the WARN, this is not really a bug since we'll wait for the
>>>> PC8-enabling thread to finish when we call modeset_global_resources.
>>>>
>>>> So this patch makes sure we get/put PC8 before we update
>>>> drm_crtc->enabled, because if a get() call triggers a PC8 disable,
>>>> we'll call cancel_delayed_work_sync(), which will wait for the thread
>>>> that's enabling PC8, then, after this, we'll disable PC8.
>>>>
>>>> The side-effect benefit of this patch is that we have a nice place to
>>>> track enabled/disabled CRTCs, so we may want to move some code from
>>>> modeset_global_resources to intel_crtc_set_state in the future.
>>>>
>>>> The problem fixed by this patch can be reproduced by the
>>>> modeset-lpsp-stress-no-wait subtest from the pc8 test of
>>>> intel-gpu-tools.
>>>>
>>>> v2: - No need for pc8.lock since we already have
>>>>       cancel_delayed_work_sync().
>>>>
>>>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>
>>> Now that Imre's big rework has landed this looks a bit strange. We now
>>> have the display power wells (properly refcounted) and the hsw pc8 stuff
>>> here. Which imo doesn't make much sense since to have a working display
>>> power well we can't go into pc8.
>>
>> This patch has nothing to do with power wells. We're checking
>> enabled/disabled CRTCs here, not power wells. The problem this patch
>> solves also happens on LPSP mode, where the power well is disabled.
>> I'm confused, please clarify.
>
> With Imre's power well rework we now have two pieces that manage the
> power state of the display hw: modeset_update_power_wells and
> modeset_update_power_wells. The later is redundant since you can't
> ever enable a crtc power well without disabling pc8.
>
> Note that I'm talking about the generic display power wells Imre
> added, which means we also track the power domain usage for crtc A.
>
> My idea is to completely ditch the call to hsw_update_package_c8 and
> shovel the respective pc8 get/put calls into the right power domains
> in the haswell display power domain implementation in intel_pm.c. That
> means that we need to adjust the always-on power well code a bit for
> hsw.
>
> In a way power domains should nest, and code should always only care
> about the innermost power domain. If it needs to grab explicit
> references for power domains outside of that the structure isn't quite
> right.

Thanks for the clarification!

Just documenting what we discussed on IRC yesterday: I agree this is
the way to go, but I think this should all be follow-up patches. We'll
also probably need to add some new power domains: for example which
one do we grab when someone submits a execbuf? POWER_DOMAIN_GT?


>
>>> So the right thing to do is to only grab the topmost power well/domain
>>> reference. Those in turn then need to grab the lower-level domains. I.e.
>>> on hsw the crtc get/put should also do a pc8 get/put and then that in turn
>>> should do a D3 get/put (if we keep them split up).
>>>
>>
>> Same as above.
>>
>>
>>> With that change it'd also make tons of sense to move all the hsw pc8
>>> stuff into intel_pm.c together with the other power well stuff. Imo the
>>> approach with use_count in Imre's code is easier to understand.
>>>
>>> Now for the actual issue you're trying to fix here: That's just a race in
>>> the check in assert_can_disable_lcpll - you access crtc->base.enabled
>>> without taking the right locks.
>>
>> Which ones are the "right locks"?
>
> crtc->mutex. It'll deadlock though due to the synchronous work
> cancelling. If you go with lockless you'd need some barriers since the
> implicit barriers in schedule_work and cancel_work aren't good enough
> any more.

Ok, but assert_can_disable_lcpll is completely unrelated with this
specific patch we're replying. We should fix this with a follow-up
patch. Also, why aren't the implicit barriers good enough anymore?


>
>>> And if the work runs concurrently to
>>> re-enabling the display power then it'll get confused.
>>
>> What exactly do you mean when you say "re-enabling the display power"?
>> Power wells?
>
> power domains in general, whether this is what bspec calls "display
> ower well" or pc8 mode or something else. Specifically here the race
> seems to happen with the pc8 domain though.
>
>>> The other issue
>>> with this check is that crtc->base.enabled is the wrong thing to check: It
>>> only tracks sw state, e.g. it's still set when we're in dpms off mode. The
>>> right thing to check would be crtc->active, and for that one we have the
>>> correct ordering between get/put calls and updating the field already.
>>
>> No, we only set crtc->active to true after we call
>> ironlake_crtc_enable, and that's too late for this specific bug. Also,
>> we don't enable PC8 nor disable power wells while in DPMS off, there's
>> a lot of work to do if we want to enable that, and this patch here is
>> just a bug fix.
>
> I mean the WARN check in assert_can_disable_lcpll, not the checks
> you're touching in your patch. For actually deciding whether we can
> allow pc8 or not we should imo piggy-pack on top of Imre's rework of
> the display power domain handling.
>
> Maybe we should go over the code and replace all mentions of
> power_well with power_domain in the generic code to make this clearer.
> Imo Imre's work isn't just about what Bspec calls "power wells" but
> about managing display power domains in general. Which includes pc8.
>
>>> Plan B would be to just ditch this check.
>>
>> The "crtc->base.enabled == enabled" check? That's not possible, it
>> would result in unbalanced get/put calls.
>
> I mean the check in assert_can_disable_lcpll for crtc->base.enabled,
> not the ones you're touching in your patch here. Sorry for the unclear
> "this" reference.

Since we don't support disabling LCPLL when the CRTC is in DPMS state,
I still think that check is not wrong (not considering
locking/concurrency issues). But if we want to only check what's
strictly necessary, yeah we could change to crtc->active or even
directly poke at the register.


Anyway, given all this discussion, I don't think I should do any
changes on this specific 04/19 patch since it's completely unrelated
with what we're discussing. Please correct me if I'm wrong.

Thanks,
Paulo

> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC
  2013-12-05 13:43         ` Paulo Zanoni
@ 2013-12-05 14:40           ` Daniel Vetter
  2013-12-06 22:29             ` [PATCH] drm/i915: change CRTC assertion on LCPLL disable Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2013-12-05 14:40 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni

On Thu, Dec 5, 2013 at 2:43 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
[snip]

> Just documenting what we discussed on IRC yesterday: I agree this is
> the way to go, but I think this should all be follow-up patches. We'll
> also probably need to add some new power domains: for example which
> one do we grab when someone submits a execbuf? POWER_DOMAIN_GT?

Imo Imre's infrastructure for display power wells doesn't need to be
extended for everything. Adding a POWER_DOMAIN_GT makes not much sense
to me - you're current approach with special get/put functions looks
sane.

To reiterate: My gripe isn't about the color of the get/put functions
at all, but that here we need to wrestle with 2 different power
domains: The pc8 stuff and the display power well stuff (as expressed
through imre's interface work). Which is redundant since if we ask for
the the CRTC_A/B/C power domain to be on that must always also forbid
pc8.

[snip]

> Ok, but assert_can_disable_lcpll is completely unrelated with this
> specific patch we're replying. We should fix this with a follow-up
> patch. Also, why aren't the implicit barriers good enough anymore?

Your commit message says that this patch fixes a race where the pc8
enable work can WARN while we concurrently set crtc->base.enabled.
Afaics that WARN is in assert_can_disable_lcpll (but your commit
message is a bit unclear what exactly is racing against which WARN).

Imo that WARN is bogus and needs to be fixed/removed, not worked
around like you do in this patch here.

[Snip]

> Since we don't support disabling LCPLL when the CRTC is in DPMS state,
> I still think that check is not wrong (not considering
> locking/concurrency issues). But if we want to only check what's
> strictly necessary, yeah we could change to crtc->active or even
> directly poke at the register.
>
>
> Anyway, given all this discussion, I don't think I should do any
> changes on this specific 04/19 patch since it's completely unrelated
> with what we're discussing. Please correct me if I'm wrong.

See above, I think the patch fixes the wrong part of the code and we
instead need to adjust the WARN check. If you want my bikeshed I'd go
with checking crtc->active, but I'm fine with either checking the
register directly or just ditching the check altogether, your call.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 19/19] drm/i915: init the DP panel power seq regs earlier
  2013-11-21 15:47 ` [PATCH 19/19] drm/i915: init the DP panel power seq regs earlier Paulo Zanoni
@ 2013-12-05 15:00   ` Jani Nikula
  2013-12-06 18:39     ` Paulo Zanoni
  0 siblings, 1 reply; 97+ messages in thread
From: Jani Nikula @ 2013-12-05 15:00 UTC (permalink / raw)
  To: Paulo Zanoni, intel-gfx; +Cc: Paulo Zanoni

On Thu, 21 Nov 2013, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> When we call intel_dp_i2c_init we already get some I2C calls, which
> will trigger a VDD enable, which will make use of the panel power
> sequencing registers, so we need to have them ready by this time.

But this patch won't make the registers ready either! The only thing
this one does is initialize the delays in intel_dp. (And unlock the
registers, but that's done in the vdd enable function too.)

And you actually can't trivially initialize the registers either,
because we will only later figure out whether this is a ghost eDP, and
such initialization might botch up LVDS.

See
commit f30d26e468322b50d5e376bec40658683aff8ece
Author: Jani Nikula <jani.nikula@intel.com>
Date:   Wed Jan 16 10:53:40 2013 +0200

    drm/i915/eDP: do not write power sequence registers for ghost eDP

I'm sorry I don't readily have any suggestions.

If you are only interested in fixing the delays for msleep, then please
fix the commit message!

BR,
Jani.



>
> The good side is that we were reading the values, but were not using
> them for anything (because we were just skipping the msleep(0) calls),
> so this "fix" shouldn't fix any real existing bugs. I was only able to
> identify the problem because I added some debug code to check how much
> time time we were saving with my previous patch.
>
> Regression introduced by:
>     commit ed92f0b239ac971edc509169ae3d6955fbe0a188
>     Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
>     Date:   Wed Jun 12 17:27:24 2013 -0300
>         drm/i915: extract intel_edp_init_connector
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 15 ++++++++-------
>  1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 3a1ca80..23927a0 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3565,14 +3565,14 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>  }
>  
>  static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> -				     struct intel_connector *intel_connector)
> +				     struct intel_connector *intel_connector,
> +				     struct edp_power_seq *power_seq)
>  {
>  	struct drm_connector *connector = &intel_connector->base;
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_display_mode *fixed_mode = NULL;
> -	struct edp_power_seq power_seq = { 0 };
>  	bool has_dpcd;
>  	struct drm_display_mode *scan;
>  	struct edid *edid;
> @@ -3580,8 +3580,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	if (!is_edp(intel_dp))
>  		return true;
>  
> -	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> -
>  	/* Cache DPCD and EDID for edp. */
>  	ironlake_edp_panel_vdd_on(intel_dp);
>  	has_dpcd = intel_dp_get_dpcd(intel_dp);
> @@ -3599,8 +3597,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	}
>  
>  	/* We now know it's not a ghost, init power sequence regs. */
> -	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
> -						      &power_seq);
> +	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
>  
>  	edid = drm_get_edid(connector, &intel_dp->adapter);
>  	if (edid) {
> @@ -3649,6 +3646,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  	struct drm_device *dev = intel_encoder->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	enum port port = intel_dig_port->port;
> +	struct edp_power_seq power_seq = { 0 };
>  	const char *name = NULL;
>  	int type, error;
>  
> @@ -3748,13 +3746,16 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  		BUG();
>  	}
>  
> +	if (is_edp(intel_dp))
> +		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> +
>  	error = intel_dp_i2c_init(intel_dp, intel_connector, name);
>  	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
>  	     error, port_name(port));
>  
>  	intel_dp->psr_setup_done = false;
>  
> -	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
> +	if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
>  		i2c_del_adapter(&intel_dp->adapter);
>  		if (is_edp(intel_dp)) {
>  			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -- 
> 1.8.3.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 19/19] drm/i915: init the DP panel power seq regs earlier
  2013-12-05 15:00   ` Jani Nikula
@ 2013-12-06 18:39     ` Paulo Zanoni
  0 siblings, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-06 18:39 UTC (permalink / raw)
  To: Jani Nikula; +Cc: Intel Graphics Development, Paulo Zanoni

2013/12/5 Jani Nikula <jani.nikula@linux.intel.com>:
> On Thu, 21 Nov 2013, Paulo Zanoni <przanoni@gmail.com> wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> When we call intel_dp_i2c_init we already get some I2C calls, which
>> will trigger a VDD enable, which will make use of the panel power
>> sequencing registers, so we need to have them ready by this time.
>
> But this patch won't make the registers ready either! The only thing
> this one does is initialize the delays in intel_dp. (And unlock the
> registers, but that's done in the vdd enable function too.)

Facepalm. You're right. I was mainly looking at the msleep() calls,
which are fixed by this patch. Besides this, we also need the
registers to be correct, but I guess this should be a separate patch.

>
> And you actually can't trivially initialize the registers either,
> because we will only later figure out whether this is a ghost eDP, and
> such initialization might botch up LVDS.

I wonder if we shouldn't at least try to do the right thing on HSW+,
since there's no LVDS there. But then there's the "eDP on port D" case
which we can't forget.


>
> See
> commit f30d26e468322b50d5e376bec40658683aff8ece
> Author: Jani Nikula <jani.nikula@intel.com>
> Date:   Wed Jan 16 10:53:40 2013 +0200
>
>     drm/i915/eDP: do not write power sequence registers for ghost eDP
>
> I'm sorry I don't readily have any suggestions.
>
> If you are only interested in fixing the delays for msleep, then please
> fix the commit message!

Yeah, I'll fix the commit message for now, but I'll also think about
what to do with the registers.

Thanks,
Paulo

>
> BR,
> Jani.
>
>
>
>>
>> The good side is that we were reading the values, but were not using
>> them for anything (because we were just skipping the msleep(0) calls),
>> so this "fix" shouldn't fix any real existing bugs. I was only able to
>> identify the problem because I added some debug code to check how much
>> time time we were saving with my previous patch.
>>
>> Regression introduced by:
>>     commit ed92f0b239ac971edc509169ae3d6955fbe0a188
>>     Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>     Date:   Wed Jun 12 17:27:24 2013 -0300
>>         drm/i915: extract intel_edp_init_connector
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/intel_dp.c | 15 ++++++++-------
>>  1 file changed, 8 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 3a1ca80..23927a0 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -3565,14 +3565,14 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>>  }
>>
>>  static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>> -                                  struct intel_connector *intel_connector)
>> +                                  struct intel_connector *intel_connector,
>> +                                  struct edp_power_seq *power_seq)
>>  {
>>       struct drm_connector *connector = &intel_connector->base;
>>       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>>       struct drm_device *dev = intel_dig_port->base.base.dev;
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       struct drm_display_mode *fixed_mode = NULL;
>> -     struct edp_power_seq power_seq = { 0 };
>>       bool has_dpcd;
>>       struct drm_display_mode *scan;
>>       struct edid *edid;
>> @@ -3580,8 +3580,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>>       if (!is_edp(intel_dp))
>>               return true;
>>
>> -     intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
>> -
>>       /* Cache DPCD and EDID for edp. */
>>       ironlake_edp_panel_vdd_on(intel_dp);
>>       has_dpcd = intel_dp_get_dpcd(intel_dp);
>> @@ -3599,8 +3597,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>>       }
>>
>>       /* We now know it's not a ghost, init power sequence regs. */
>> -     intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
>> -                                                   &power_seq);
>> +     intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
>>
>>       edid = drm_get_edid(connector, &intel_dp->adapter);
>>       if (edid) {
>> @@ -3649,6 +3646,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>>       struct drm_device *dev = intel_encoder->base.dev;
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       enum port port = intel_dig_port->port;
>> +     struct edp_power_seq power_seq = { 0 };
>>       const char *name = NULL;
>>       int type, error;
>>
>> @@ -3748,13 +3746,16 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>>               BUG();
>>       }
>>
>> +     if (is_edp(intel_dp))
>> +             intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
>> +
>>       error = intel_dp_i2c_init(intel_dp, intel_connector, name);
>>       WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
>>            error, port_name(port));
>>
>>       intel_dp->psr_setup_done = false;
>>
>> -     if (!intel_edp_init_connector(intel_dp, intel_connector)) {
>> +     if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
>>               i2c_del_adapter(&intel_dp->adapter);
>>               if (is_edp(intel_dp)) {
>>                       cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Jani Nikula, Intel Open Source Technology Center



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on
  2013-11-29 14:37       ` Rodrigo Vivi
@ 2013-12-06 22:23         ` Paulo Zanoni
  0 siblings, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-06 22:23 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: Intel Graphics Development, Paulo Zanoni

2013/11/29 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> On Fri, Nov 29, 2013 at 11:59 AM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> 2013/11/29 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>>> On Thu, Nov 21, 2013 at 01:47:23PM -0200, Paulo Zanoni wrote:
>>>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>>
>>>> And put it when it's off. Otherwise, when you run pm_pc8 from
>>>> intel-gpu-tools, and the delayed function that disables VDD runs,
>>>> we'll get some messages saying we're touching registers while the HW
>>>> is suspended.
>>>>
>>>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>>> ---
>>>>  drivers/gpu/drm/i915/intel_dp.c | 7 +++++++
>>>>  1 file changed, 7 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>>>> index 28fc070..9e9e3d6 100644
>>>> --- a/drivers/gpu/drm/i915/intel_dp.c
>>>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>>>> @@ -1092,6 +1092,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
>>>>       if (ironlake_edp_have_panel_vdd(intel_dp))
>>>>               return;
>>>>
>>>> +     intel_runtime_pm_get(dev_priv);
>>>> +
>>>>       DRM_DEBUG_KMS("Turning eDP VDD on\n");
>>>>
>>>>       if (!ironlake_edp_have_panel_power(intel_dp))
>>>> @@ -1141,6 +1143,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
>>>>               DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
>>>>               I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
>>>>               msleep(intel_dp->panel_power_down_delay);
>>>> +
>>>> +             intel_runtime_pm_put(dev_priv);
>>>>       }
>>>>  }
>>>>
>>>> @@ -1248,6 +1252,9 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
>>>>       intel_dp->want_panel_vdd = false;
>>>>
>>>>       ironlake_wait_panel_off(intel_dp);
>>>> +
>>>> +     /* We got a reference when we enabled the VDD. */
>>>> +     intel_runtime_pm_put(dev_priv);
>>>
>>> I was going to say it was missing a get until I read the comment above.
>>> But if it gets on VDD on, why not just let it put back on VDD off instead?
>>
>> That's the goal of my series. See patches 15 and 16.
>
> I saw both and got your point, but even after them get and put doesn't
> look in a symmetric place for me.
>

We have 1 place where we "get" and 2 places where we "put", because we
have 1 place where we enable EDP_FORCE_VDD and two places where we
disable EDP_FORCE_VDD. If you only count the get/put ratio it doesn't
look symmetric, but if you compare it against the EDP_FORCE_VDD bit,
it will look symmetric :)


> wouldn't make sense on this patch remove both of _put here and add one
> in vdd_off?

You mean ironlake_edp_panel_vdd_off? That function doesn't touch EDP_FORCE_VDD.

> Even after your vdd fixes it would be symmetric.

Well, at this point maybe the VDD fixes will be merged first, so I
will have to update this patch on top of that, and maybe it will make
more sense to the reviewers :)

>
>>
>>>
>>>>  }
>>>>
>>>>  void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
>>>> --
>>>> 1.8.3.1
>>>>
>>>> _______________________________________________
>>>> Intel-gfx mailing list
>>>> Intel-gfx@lists.freedesktop.org
>>>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
>
>
> --
> Rodrigo Vivi
> Blog: http://blog.vivi.eng.br



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* [PATCH] drm/i915: change CRTC assertion on LCPLL disable
  2013-12-05 14:40           ` Daniel Vetter
@ 2013-12-06 22:29             ` Paulo Zanoni
  2013-12-06 22:37               ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-06 22:29 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Currently, PC8 is enabled at modeset_global_resources, which is called
after intel_modeset_update_state. Due to this, there's a small race
condition on the case where we start enabling PC8, then do a modeset
while PC8 is still being enabled. The racing condition triggers a WARN
because intel_modeset_update_state will mark the CRTC as enabled, then
the thread that's still enabling PC8 might look at the data structure
and think that PC8 is being enabled while a pipe is enabled. Despite
the WARN, this is not really a bug since we'll wait for the
PC8-enabling thread to finish when we call modeset_global_resources.

The spec says the CRTC cannot be enabled when we disable LCPLL, so we
had a check for crtc->base.enabled. If we change to crtc->active we
will still prevent disabling LCPLL while the CRTC is enabled, and we
will also prevent the WARN above.

This is a replacement for the previous patch named
    "drm/i915: get/put PC8 when we get/put a CRTC"

Testcase: igt/pm_pc8/modeset-lpsp-stress-no-wait
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6d9e183..3934b5f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6490,7 +6490,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 	uint32_t val;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
-		WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+		WARN(crtc->active, "CRTC for pipe %c enabled\n",
 		     pipe_name(crtc->pipe));
 
 	WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-11-29 14:05     ` Takashi Iwai
@ 2013-12-06 22:31       ` Paulo Zanoni
  2013-12-06 22:32         ` Paulo Zanoni
  2013-12-08  9:06         ` Takashi Iwai
  0 siblings, 2 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-06 22:31 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Intel Graphics Development, Paulo Zanoni

2013/11/29 Takashi Iwai <tiwai@suse.de>:
> At Wed, 27 Nov 2013 18:10:30 -0200,
> Paulo Zanoni wrote:
>>
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> This patch adds the initial infrastructure to allow a Runtime PM
>> implementation that sets the device to its D3 state. The patch just
>> adds the necessary callbacks and the initial infrastructure.
>>
>> We still don't have any platform that actually uses this
>> infrastructure, we still don't call get/put in all the places we need
>> to, and we don't have any function to save/restore the state of the
>> registers. This is not a problem since no platform uses the code added
>> by this patch. We have a few people simultaneously working on runtime
>> PM, so this initial code could help everybody make their plans.
>>
>> V2: - Move some functions to intel_pm.c
>>     - Remove useless pm_runtime_allow() call at init
>>     - Remove useless pm_runtime_mark_last_busy() call at get
>>     - Use pm_runtime_get_sync() instead of 2 calls
>>     - Add a WARN to check if we're really awake
>>
>> V3: - Rebase.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
>>  drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
>>  drivers/gpu/drm/i915/intel_drv.h    |  4 +++
>>  drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
>>  6 files changed, 124 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
>> index 89e4cf1..4cdc1ee 100644
>> --- a/drivers/gpu/drm/i915/i915_dma.c
>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>> @@ -42,6 +42,8 @@
>>  #include <linux/vga_switcheroo.h>
>>  #include <linux/slab.h>
>>  #include <acpi/video.h>
>> +#include <linux/pm.h>
>> +#include <linux/pm_runtime.h>
>>
>>  #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
>>
>> @@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>>       if (IS_GEN5(dev))
>>               intel_gpu_ips_init(dev_priv);
>>
>> +     intel_init_runtime_pm(dev_priv);
>> +
>>       return 0;
>>
>>  out_power_well:
>> @@ -1702,6 +1706,8 @@ int i915_driver_unload(struct drm_device *dev)
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       int ret;
>>
>> +     intel_fini_runtime_pm(dev_priv);
>> +
>>       intel_gpu_ips_teardown();
>>
>>       /* The i915.ko module is still not prepared to be loaded when
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index 0ec0fb3..d5310a0 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       struct drm_crtc *crtc;
>>
>> +     intel_runtime_pm_get(dev_priv);
>> +
>>       /* ignore lid events during suspend */
>>       mutex_lock(&dev_priv->modeset_restore_lock);
>>       dev_priv->modeset_restore = MODESET_SUSPENDED;
>> @@ -688,6 +690,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
>>       mutex_lock(&dev_priv->modeset_restore_lock);
>>       dev_priv->modeset_restore = MODESET_DONE;
>>       mutex_unlock(&dev_priv->modeset_restore_lock);
>> +
>> +     intel_runtime_pm_put(dev_priv);
>>       return error;
>>  }
>>
>> @@ -902,6 +906,42 @@ static int i915_pm_poweroff(struct device *dev)
>>       return i915_drm_freeze(drm_dev);
>>  }
>>
>> +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));
>
> It'd be better to add runtime_idle callback for this kind of checks.
> It's called always before actually doing runtime PM, and you can
> return -EBUSY if the runtime PM isn't available.

It's a WARN we never expect to hit, so I don't think it's worth
creating a new function just for a check like that.

>
>
>> +     DRM_DEBUG_KMS("Suspending device\n");
>> +
>> +     dev_priv->pm.suspended = true;
>> +
>> +     pci_save_state(pdev);
>> +     pci_set_power_state(pdev, PCI_D3cold);
>
> Why do you need these calls?  PCI runtime PM core should already
> handle the power state change by itself.
>
>
> Takashi



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-12-06 22:31       ` Paulo Zanoni
@ 2013-12-06 22:32         ` Paulo Zanoni
  2013-12-08  9:06         ` Takashi Iwai
  1 sibling, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-06 22:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This patch adds the initial infrastructure to allow a Runtime PM
implementation that sets the device to its D3 state. The patch just
adds the necessary callbacks and the initial infrastructure.

We still don't have any platform that actually uses this
infrastructure, we still don't call get/put in all the places we need
to, and we don't have any function to save/restore the state of the
registers. This is not a problem since no platform uses the code added
by this patch. We have a few people simultaneously working on runtime
PM, so this initial code could help everybody make their plans.

V2: - Move some functions to intel_pm.c
    - Remove useless pm_runtime_allow() call at init
    - Remove useless pm_runtime_mark_last_busy() call at get
    - Use pm_runtime_get_sync() instead of 2 calls
    - Add a WARN to check if we're really awake

V3: - Rebase.

V4: - Don't need to call pci_{save,restore}_state and
      pci_set_power_sate, since they're already called by the PCI
      layer
    - Remove wrong pm_runtime_enable() call at init_runtime_pm

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
 drivers/gpu/drm/i915/i915_drv.c     | 36 ++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
 drivers/gpu/drm/i915/intel_drv.h    |  4 +++
 drivers/gpu/drm/i915/intel_pm.c     | 55 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
 6 files changed, 117 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 5158a0c..9f64dcb 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -42,6 +42,8 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -1655,6 +1657,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (IS_GEN5(dev))
 		intel_gpu_ips_init(dev_priv);
 
+	intel_init_runtime_pm(dev_priv);
+
 	return 0;
 
 out_power_well:
@@ -1694,6 +1698,8 @@ int i915_driver_unload(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	intel_fini_runtime_pm(dev_priv);
+
 	intel_gpu_ips_teardown();
 
 	/* The i915.ko module is still not prepared to be loaded when
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 65b5c83..3289a89 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc;
 
+	intel_runtime_pm_get(dev_priv);
+
 	/* ignore lid events during suspend */
 	mutex_lock(&dev_priv->modeset_restore_lock);
 	dev_priv->modeset_restore = MODESET_SUSPENDED;
@@ -689,6 +691,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
 	mutex_lock(&dev_priv->modeset_restore_lock);
 	dev_priv->modeset_restore = MODESET_DONE;
 	mutex_unlock(&dev_priv->modeset_restore_lock);
+
+	intel_runtime_pm_put(dev_priv);
 	return error;
 }
 
@@ -903,6 +907,36 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 }
 
+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");
+
+	dev_priv->pm.suspended = true;
+
+	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");
+
+	dev_priv->pm.suspended = false;
+
+	return 0;
+}
+
 static const struct dev_pm_ops i915_pm_ops = {
 	.suspend = i915_pm_suspend,
 	.resume = i915_pm_resume,
@@ -910,6 +944,8 @@ static const struct dev_pm_ops i915_pm_ops = {
 	.thaw = i915_pm_thaw,
 	.poweroff = i915_pm_poweroff,
 	.restore = i915_pm_resume,
+	.runtime_suspend = i915_runtime_suspend,
+	.runtime_resume = i915_runtime_resume,
 };
 
 static const struct vm_operations_struct i915_gem_vm_ops = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index efc57fe..1238ac8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1289,6 +1289,10 @@ struct i915_package_c8 {
 	} regsave;
 };
 
+struct i915_runtime_pm {
+	bool suspended;
+};
+
 enum intel_pipe_crc_source {
 	INTEL_PIPE_CRC_SOURCE_NONE,
 	INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -1519,6 +1523,8 @@ typedef struct drm_i915_private {
 
 	struct i915_package_c8 pc8;
 
+	struct i915_runtime_pm pm;
+
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
 	 * here! */
 	struct i915_dri1_state dri1;
@@ -1843,6 +1849,7 @@ struct drm_i915_file_private {
 #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_PC8(dev)		(IS_HASWELL(dev)) /* XXX HSW:ULX */
+#define HAS_RUNTIME_PM(dev)	false
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ea62673..c9b5170 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -859,6 +859,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e707072..c01d08d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -31,6 +31,7 @@
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
 #include <drm/i915_powerwell.h>
+#include <linux/pm_runtime.h>
 
 /**
  * RC6 is a special power stage which allows the GPU to enter an very
@@ -5962,6 +5963,60 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
 	hsw_enable_package_c8(dev_priv);
 }
 
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_get_sync(device);
+	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
+}
+
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_mark_last_busy(device);
+	pm_runtime_put_autosuspend(device);
+}
+
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	dev_priv->pm.suspended = false;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	pm_runtime_set_active(device);
+
+	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
+	pm_runtime_mark_last_busy(device);
+	pm_runtime_use_autosuspend(device);
+}
+
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct device *device = &dev->pdev->dev;
+
+	if (!HAS_RUNTIME_PM(dev))
+		return;
+
+	/* Make sure we're not suspended first. */
+	pm_runtime_get_sync(device);
+	pm_runtime_disable(device);
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index feb2d66..458075e 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -439,6 +439,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
 	}
 }
 
+static void
+assert_device_not_suspended(struct drm_i915_private *dev_priv)
+{
+	WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
+	     "Device suspended\n");
+}
+
 #define REG_READ_HEADER(x) \
 	unsigned long irqflags; \
 	u##x val = 0; \
@@ -570,6 +577,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
+	assert_device_not_suspended(dev_priv); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	if (unlikely(__fifo_ret)) { \
 		gen6_gt_check_fifodbg(dev_priv); \
@@ -585,6 +593,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
 	if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
 		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
 	} \
+	assert_device_not_suspended(dev_priv); \
 	hsw_unclaimed_reg_clear(dev_priv, reg); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	if (unlikely(__fifo_ret)) { \
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM
  2013-11-29 12:56       ` Rodrigo Vivi
  2013-11-29 13:33         ` Rodrigo Vivi
@ 2013-12-06 22:34         ` Paulo Zanoni
  1 sibling, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-06 22:34 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula, Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Now that we are actually setting the device to the D3 state, we should
issue the notification.

The opregion spec says we should send the message before the adapter
is about to be placed in a lower power state, and after the adapter is
placed in a higher power state.

Jani originally wrote a similar patch for PC8, but then we discovered
that we were not really changing the PCI D states when
enabling/disabling PC8, so we had to postpone his patch.

v2: - Improve commit message, explaining the expected state.

v3: - Rebase.

Cc: Jani Nikula <jani.nikula@intel.com>
Credits-to: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> (v2)
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 3289a89..a13b8ed 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -918,6 +918,7 @@ static int i915_runtime_suspend(struct device *device)
 	DRM_DEBUG_KMS("Suspending device\n");
 
 	dev_priv->pm.suspended = true;
+	intel_opregion_notify_adapter(dev, PCI_D3cold);
 
 	return 0;
 }
@@ -932,6 +933,7 @@ static int i915_runtime_resume(struct device *device)
 
 	DRM_DEBUG_KMS("Resuming device\n");
 
+	intel_opregion_notify_adapter(dev, PCI_D0);
 	dev_priv->pm.suspended = false;
 
 	return 0;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 97+ messages in thread

* Re: [PATCH] drm/i915: change CRTC assertion on LCPLL disable
  2013-12-06 22:29             ` [PATCH] drm/i915: change CRTC assertion on LCPLL disable Paulo Zanoni
@ 2013-12-06 22:37               ` Daniel Vetter
  0 siblings, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-12-06 22:37 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Dec 06, 2013 at 08:29:01PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Currently, PC8 is enabled at modeset_global_resources, which is called
> after intel_modeset_update_state. Due to this, there's a small race
> condition on the case where we start enabling PC8, then do a modeset
> while PC8 is still being enabled. The racing condition triggers a WARN
> because intel_modeset_update_state will mark the CRTC as enabled, then
> the thread that's still enabling PC8 might look at the data structure
> and think that PC8 is being enabled while a pipe is enabled. Despite
> the WARN, this is not really a bug since we'll wait for the
> PC8-enabling thread to finish when we call modeset_global_resources.
> 
> The spec says the CRTC cannot be enabled when we disable LCPLL, so we
> had a check for crtc->base.enabled. If we change to crtc->active we
> will still prevent disabling LCPLL while the CRTC is enabled, and we
> will also prevent the WARN above.
> 
> This is a replacement for the previous patch named
>     "drm/i915: get/put PC8 when we get/put a CRTC"
> 
> Testcase: igt/pm_pc8/modeset-lpsp-stress-no-wait
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Queued for -next, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 05/19] drm/i915: add initial Runtime PM functions
  2013-12-06 22:31       ` Paulo Zanoni
  2013-12-06 22:32         ` Paulo Zanoni
@ 2013-12-08  9:06         ` Takashi Iwai
  1 sibling, 0 replies; 97+ messages in thread
From: Takashi Iwai @ 2013-12-08  9:06 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni

At Fri, 6 Dec 2013 20:31:04 -0200,
Paulo Zanoni wrote:
> 
> 2013/11/29 Takashi Iwai <tiwai@suse.de>:
> > At Wed, 27 Nov 2013 18:10:30 -0200,
> > Paulo Zanoni wrote:
> >>
> >> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >>
> >> This patch adds the initial infrastructure to allow a Runtime PM
> >> implementation that sets the device to its D3 state. The patch just
> >> adds the necessary callbacks and the initial infrastructure.
> >>
> >> We still don't have any platform that actually uses this
> >> infrastructure, we still don't call get/put in all the places we need
> >> to, and we don't have any function to save/restore the state of the
> >> registers. This is not a problem since no platform uses the code added
> >> by this patch. We have a few people simultaneously working on runtime
> >> PM, so this initial code could help everybody make their plans.
> >>
> >> V2: - Move some functions to intel_pm.c
> >>     - Remove useless pm_runtime_allow() call at init
> >>     - Remove useless pm_runtime_mark_last_busy() call at get
> >>     - Use pm_runtime_get_sync() instead of 2 calls
> >>     - Add a WARN to check if we're really awake
> >>
> >> V3: - Rebase.
> >>
> >> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/i915_dma.c     |  6 ++++
> >>  drivers/gpu/drm/i915/i915_drv.c     | 42 ++++++++++++++++++++++++++++
> >>  drivers/gpu/drm/i915/i915_drv.h     |  7 +++++
> >>  drivers/gpu/drm/i915/intel_drv.h    |  4 +++
> >>  drivers/gpu/drm/i915/intel_pm.c     | 56 +++++++++++++++++++++++++++++++++++++
> >>  drivers/gpu/drm/i915/intel_uncore.c |  9 ++++++
> >>  6 files changed, 124 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> >> index 89e4cf1..4cdc1ee 100644
> >> --- a/drivers/gpu/drm/i915/i915_dma.c
> >> +++ b/drivers/gpu/drm/i915/i915_dma.c
> >> @@ -42,6 +42,8 @@
> >>  #include <linux/vga_switcheroo.h>
> >>  #include <linux/slab.h>
> >>  #include <acpi/video.h>
> >> +#include <linux/pm.h>
> >> +#include <linux/pm_runtime.h>
> >>
> >>  #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
> >>
> >> @@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> >>       if (IS_GEN5(dev))
> >>               intel_gpu_ips_init(dev_priv);
> >>
> >> +     intel_init_runtime_pm(dev_priv);
> >> +
> >>       return 0;
> >>
> >>  out_power_well:
> >> @@ -1702,6 +1706,8 @@ int i915_driver_unload(struct drm_device *dev)
> >>       struct drm_i915_private *dev_priv = dev->dev_private;
> >>       int ret;
> >>
> >> +     intel_fini_runtime_pm(dev_priv);
> >> +
> >>       intel_gpu_ips_teardown();
> >>
> >>       /* The i915.ko module is still not prepared to be loaded when
> >> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> >> index 0ec0fb3..d5310a0 100644
> >> --- a/drivers/gpu/drm/i915/i915_drv.c
> >> +++ b/drivers/gpu/drm/i915/i915_drv.c
> >> @@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
> >>       struct drm_i915_private *dev_priv = dev->dev_private;
> >>       struct drm_crtc *crtc;
> >>
> >> +     intel_runtime_pm_get(dev_priv);
> >> +
> >>       /* ignore lid events during suspend */
> >>       mutex_lock(&dev_priv->modeset_restore_lock);
> >>       dev_priv->modeset_restore = MODESET_SUSPENDED;
> >> @@ -688,6 +690,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
> >>       mutex_lock(&dev_priv->modeset_restore_lock);
> >>       dev_priv->modeset_restore = MODESET_DONE;
> >>       mutex_unlock(&dev_priv->modeset_restore_lock);
> >> +
> >> +     intel_runtime_pm_put(dev_priv);
> >>       return error;
> >>  }
> >>
> >> @@ -902,6 +906,42 @@ static int i915_pm_poweroff(struct device *dev)
> >>       return i915_drm_freeze(drm_dev);
> >>  }
> >>
> >> +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));
> >
> > It'd be better to add runtime_idle callback for this kind of checks.
> > It's called always before actually doing runtime PM, and you can
> > return -EBUSY if the runtime PM isn't available.
> 
> It's a WARN we never expect to hit, so I don't think it's worth
> creating a new function just for a check like that.

In the current situation with a static condition, maybe so.  But in
general, it'd be safer not to do conditional check in
intel_runtime_pm_get()/put() but filter in runtime idle callback
instead, so that you can concentrate only on consistency of refcounts
in *_get() and *_put().  For example, if the condition changes
dynamically, you cannot apply conditional to *_get() and *_put();
otherwise it'd result in unbalance.  So the above is a recommendation
from my past experiences in others drivers.

And, even if you use WARN() for a static condition check there, it
doesn't have to be spit at each time.  It's no dynamic condition, so
WARN_ON_ONCE() should suffice.


Takashi

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well
  2013-11-27 19:59   ` Paulo Zanoni
  2013-11-29 12:35     ` Rodrigo Vivi
@ 2013-12-10 21:29     ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-12-10 21:29 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Wed, Nov 27, 2013 at 05:59:22PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> In the current code, at haswell_modeset_global_resources, first we
> decide if we want to enable/disable the power well, then we decide if
> we want to enable/disable PC8. On the case where we're enabling PC8
> this works fine, but on the case where we disable PC8 due to a non-eDP
> monitor being enabled, we first enable the power well and then disable
> PC8. Although wrong, this doesn't seem to be causing any problems now,
> and we don't even see anything in dmesg. But the patches for runtime
> D3 turn this problem into a real bug, so we need to fix it.
> 
> This fixes the "modeset-non-lpsp" subtest from the "pm_pc8" test from
> intel-gpu-tools.
> 
> v2: - Rebase (i915_disable_power_well).
> v3: - More reabase.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 432ec13..1cb02b1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5677,6 +5677,8 @@ static void hsw_set_power_well(struct drm_device *dev,
>  	unsigned long irqflags;
>  	uint32_t tmp;
>  
> +	WARN_ON(dev_priv->pc8.enabled);
> +
>  	tmp = I915_READ(HSW_PWR_WELL_DRIVER);
>  	is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
>  	enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
> @@ -5736,17 +5738,26 @@ static void hsw_set_power_well(struct drm_device *dev,
>  static void __intel_power_well_get(struct drm_device *dev,
>  				   struct i915_power_well *power_well)
>  {
> -	if (!power_well->count++ && power_well->set)
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (!power_well->count++ && power_well->set) {
> +		hsw_disable_package_c8(dev_priv);
>  		power_well->set(dev, power_well, true);

Just to reiterate what we've discussed: Once this stuff has settled we
need to push the hsw_*_pc8 out of this common code into the
power_well->set/get functions. Merged the patch for now.
-Daniel

> +	}
>  }
>  
>  static void __intel_power_well_put(struct drm_device *dev,
>  				   struct i915_power_well *power_well)
>  {
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
>  	WARN_ON(!power_well->count);
>  
> -	if (!--power_well->count && power_well->set && i915_disable_power_well)
> +	if (!--power_well->count && power_well->set &&
> +	    i915_disable_power_well) {
>  		power_well->set(dev, power_well, false);
> +		hsw_enable_package_c8(dev_priv);
> +	}
>  }
>  
>  void intel_display_power_get(struct drm_device *dev,
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-11-29 13:03           ` Rodrigo Vivi
  2013-11-29 13:32             ` Rodrigo Vivi
@ 2013-12-10 21:49             ` Daniel Vetter
  2013-12-12 20:07               ` Paulo Zanoni
  1 sibling, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2013-12-10 21:49 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

On Fri, Nov 29, 2013 at 11:03:38AM -0200, Rodrigo Vivi wrote:
> On Wed, Nov 27, 2013 at 06:20:34PM -0200, Paulo Zanoni wrote:
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 2715600..70c4cef 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -2477,6 +2477,12 @@ static void i915_hangcheck_elapsed(unsigned long data)
> >  	if (!i915_enable_hangcheck)
> >  		return;
> >  
> > +	/* Just postpone in case we're completely idle... */
> > +	if (dev_priv->pm.suspended) {
> > +		i915_queue_hangcheck(dev);
> > +		return;
> > +	}
> 
> I got the idea here, just not sure if it fits on this patch or it is just the commit message.

This hunk here is the wrong thing to do: If we're suspended and the
hangcheck fires, we'll just delay it. But if we keep on being suspended
the hangcheck will fire at the normal recheck rate (but never do anything)
which wreaks utter havoc with deep sleep residency. The simples solution
would be to synchronously cancel the timer in the idle work (where we
already put the execbuf runtime ref) I think.

I've dropped this hunk from the patch when merging.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled
  2013-11-21 15:47 ` [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled Paulo Zanoni
  2013-11-29 14:30   ` Rodrigo Vivi
@ 2013-12-10 21:54   ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-12-10 21:54 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:24PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> The current code was checking if all bits of "val" were enabled and
> DE_PCH_EVENT_IVB was disabled. The new code doesn't care about the
> state of DE_PCH_EVENT_IVB: it just checks if everything else is 1.
> 
> The goal is that future patches may completely disable interrupts, and
> the LCPLL-disabling code shouldn't care about the state of
> DE_PCH_EVENT_IVB.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 846f2de..95e8831 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6499,7 +6499,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
>  
>  	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>  	val = I915_READ(DEIMR);
> -	WARN((val & ~DE_PCH_EVENT_IVB) != val,
> +	WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,

I think the old test doesn't really do what your commit message claims it
does, but the new one seems correct. So merged.
-Daniel

>  	     "Unexpected DEIMR bits enabled: 0x%x\n", val);
>  	val = I915_READ(SDEIMR);
>  	WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 11/19] drm/i915: disable interrupts when enabling PC8
  2013-11-21 15:47 ` [PATCH 11/19] drm/i915: disable interrupts when enabling PC8 Paulo Zanoni
  2013-12-02 13:33   ` Rodrigo Vivi
@ 2013-12-10 21:59   ` Daniel Vetter
  2013-12-11 21:33     ` Paulo Zanoni
  1 sibling, 1 reply; 97+ messages in thread
From: Daniel Vetter @ 2013-12-10 21:59 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:25PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> The plan is to merge PC8 and D3 into a single feature, and when we're
> in D3 we won't get any hotplug interrupt anyway, so leaving them
> enable doesn't make sense, and it also brings us a problem. The
> problem is that we get a hotplug interrupt right when we we wake up
> from D3, when we're still waking up everything. If we fully disable
> interrupts we won't get this hotplug interrupt, so we won't have
> problems.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Now that we forgo the partial interrupt enabling of pc8 there's imo no
need any more for the pc8 interrup reg save/restore dance. Instead it'd be
much better to just disable the interrup by disabling the interrupt
handler and then when reenabling things to use our core interrupt enabling
functions.

This way the runtime d3 path uses the same code as resume and driver load.
Furthermore the D3 code will be a bit more generic, which helps with
enabling platforms. But this can (should) be done in a follow-up.
-Daniel
> ---
>  drivers/gpu/drm/i915/i915_irq.c | 26 +++++++++-----------------
>  1 file changed, 9 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 70c4cef..d0f4e61 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -3902,8 +3902,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
>  	dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
>  	dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
>  
> -	ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
> -	ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
> +	ironlake_disable_display_irq(dev_priv, 0xffffffff);
> +	ibx_disable_display_interrupt(dev_priv, 0xffffffff);
>  	ilk_disable_gt_irq(dev_priv, 0xffffffff);
>  	snb_disable_pm_irq(dev_priv, 0xffffffff);
>  
> @@ -3917,34 +3917,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	unsigned long irqflags;
> -	uint32_t val, expected;
> +	uint32_t val;
>  
>  	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>  
>  	val = I915_READ(DEIMR);
> -	expected = ~DE_PCH_EVENT_IVB;
> -	WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
> +	WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
>  
> -	val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
> -	expected = ~SDE_HOTPLUG_MASK_CPT;
> -	WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
> -	     val, expected);
> +	val = I915_READ(SDEIMR);
> +	WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
>  
>  	val = I915_READ(GTIMR);
> -	expected = 0xffffffff;
> -	WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
> +	WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
>  
>  	val = I915_READ(GEN6_PMIMR);
> -	expected = 0xffffffff;
> -	WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
> -	     expected);
> +	WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
>  
>  	dev_priv->pc8.irqs_disabled = false;
>  
>  	ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
> -	ibx_enable_display_interrupt(dev_priv,
> -				     ~dev_priv->pc8.regsave.sdeimr &
> -				     ~SDE_HOTPLUG_MASK_CPT);
> +	ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
>  	ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
>  	snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
>  	I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3
  2013-11-21 15:47 ` [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3 Paulo Zanoni
  2013-11-21 16:02   ` Chris Wilson
@ 2013-12-10 22:03   ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-12-10 22:03 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:26PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> So we'll get a fault when someone tries to access the mmap, then we'll
> wake up from D3.
> 
> This fixes the gem-mmap-gtt subtest from pm_pc8 from intel-gpu-tools.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 2 ++
>  drivers/gpu/drm/i915/i915_drv.h | 1 +
>  drivers/gpu/drm/i915/i915_gem.c | 8 ++++++++
>  3 files changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index b133836..6510483 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -912,6 +912,8 @@ static int i915_runtime_suspend(struct device *device)
>  
>  	DRM_DEBUG_KMS("Suspending device\n");
>  
> +	i915_gem_release_all_mmaps(dev_priv);
> +
>  	dev_priv->pm.suspended = true;
>  
>  	intel_opregion_notify_adapter(dev, PCI_D3cold);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3877a68..3702746 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2003,6 +2003,7 @@ void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
>  int __must_check i915_vma_unbind(struct i915_vma *vma);
>  int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
>  int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
> +void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
>  void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
>  void i915_gem_lastclose(struct drm_device *dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 94c2a38..68fa7c7 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1465,6 +1465,14 @@ out:
>  	return ret;
>  }
>  
> +void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_i915_gem_object *obj;
> +
> +	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)

This should use the global gtt lrus to avoid walking all bound objects -
if there's no ggtt mapping the object also can't be bound. Only downside
is that we need to walk two lists (active+inactive) but that split should
get removed eventually anyway.
-Daniel

> +		i915_gem_release_mmap(obj);
> +}
> +
>  /**
>   * i915_gem_release_mmap - remove physical page mappings
>   * @obj: obj in question
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 14/19] drm/i915: add runtime PM support on Haswell
  2013-11-21 15:47 ` [PATCH 14/19] drm/i915: add runtime PM support on Haswell Paulo Zanoni
  2013-12-02 13:37   ` Rodrigo Vivi
@ 2013-12-10 22:06   ` Daniel Vetter
  1 sibling, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-12-10 22:06 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, Nov 21, 2013 at 01:47:28PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> The code to enable/disable PC8 already takes care of saving and
> restoring all the registers we need to save/restore, so do a put()
> call when we enable PC8 and a get() call when we disable it.
> 
> Ideally, in order to make it easier to add runtime PM support to other
> platforms, we should move some things from the PC8 code to the runtime
> PM code, but let's do this later, since we can make Haswell work right
> now.

Nah, I think this is the right approach. Each power domain should only
grab references to the next outer one. So on hsw we'd have

power well -> pc8 -> runtime D3

On other platfroms maybe

power well A -+-> runtime D3
power well B -|

Hence why I think that we need to shovel the hsw pc8 reference get/put
into the display power wells - we have an always-on power well so this
should fit nicely.

Anyway, current patch merged.
-Daniel

> 
> V2: - Rebase
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      | 2 +-
>  drivers/gpu/drm/i915/intel_display.c | 4 ++++
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3702746..002b99d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1836,7 +1836,7 @@ struct drm_i915_file_private {
>  #define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
>  #define HAS_PSR(dev)		(IS_HASWELL(dev) || IS_BROADWELL(dev))
>  #define HAS_PC8(dev)		(IS_HASWELL(dev)) /* XXX HSW:ULX */
> -#define HAS_RUNTIME_PM(dev)	false
> +#define HAS_RUNTIME_PM(dev)	(IS_HASWELL(dev))
>  
>  #define INTEL_PCH_DEVICE_ID_MASK		0xff00
>  #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 95e8831..820013a 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6641,6 +6641,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
>  	lpt_disable_clkout_dp(dev);
>  	hsw_pc8_disable_interrupts(dev);
>  	hsw_disable_lcpll(dev_priv, true, true);
> +
> +	intel_runtime_pm_put(dev_priv);
>  }
>  
>  static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
> @@ -6678,6 +6680,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
>  
>  	DRM_DEBUG_KMS("Disabling package C8+\n");
>  
> +	intel_runtime_pm_get(dev_priv);
> +
>  	hsw_restore_lcpll(dev_priv);
>  	hsw_pc8_restore_interrupts(dev);
>  	lpt_init_pch_refclk(dev);
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 14/19] drm/i915: add runtime PM support on Haswell
  2013-12-02 13:37   ` Rodrigo Vivi
@ 2013-12-10 22:10     ` Daniel Vetter
  0 siblings, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-12-10 22:10 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

On Mon, Dec 02, 2013 at 11:37:30AM -0200, Rodrigo Vivi wrote:
> On Thu, Nov 21, 2013 at 1:47 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >
> > The code to enable/disable PC8 already takes care of saving and
> > restoring all the registers we need to save/restore, so do a put()
> > call when we enable PC8 and a get() call when we disable it.
> >
> > Ideally, in order to make it easier to add runtime PM support to other
> > platforms, we should move some things from the PC8 code to the runtime
> > PM code, but let's do this later, since we can make Haswell work right
> > now.
> >
> > V2: - Rebase
> >
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h      | 2 +-
> >  drivers/gpu/drm/i915/intel_display.c | 4 ++++
> >  2 files changed, 5 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 3702746..002b99d 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1836,7 +1836,7 @@ struct drm_i915_file_private {
> >  #define HAS_FPGA_DBG_UNCLAIMED(dev)    (INTEL_INFO(dev)->has_fpga_dbg)
> >  #define HAS_PSR(dev)           (IS_HASWELL(dev) || IS_BROADWELL(dev))
> >  #define HAS_PC8(dev)           (IS_HASWELL(dev)) /* XXX HSW:ULX */
> > -#define HAS_RUNTIME_PM(dev)    false
> > +#define HAS_RUNTIME_PM(dev)    (IS_HASWELL(dev))
> >
> >  #define INTEL_PCH_DEVICE_ID_MASK               0xff00
> >  #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 95e8831..820013a 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -6641,6 +6641,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
> >         lpt_disable_clkout_dp(dev);
> >         hsw_pc8_disable_interrupts(dev);
> >         hsw_disable_lcpll(dev_priv, true, true);
> > +
> > +       intel_runtime_pm_put(dev_priv);
> 
> Maybe this could be along with other put and get on previous patches
> and let this patch just to really enable the runtime pm.
> But anyway, feel free to use:
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

Ok, I've merged all the patches with r-bs, minus the one change for the
hangcheck which I've taken out of the relevant patch. And I didn't enable
D3 in this patch since it's not yet complete.

For resending patche I think it's better to start a new thread, I've had a
hard time finding the right patches (so please also check that I've picked
the right ones).

Thanks, Daniel
> 
> >  }
> >
> >  static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
> > @@ -6678,6 +6680,8 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
> >
> >         DRM_DEBUG_KMS("Disabling package C8+\n");
> >
> > +       intel_runtime_pm_get(dev_priv);
> > +
> >         hsw_restore_lcpll(dev_priv);
> >         hsw_pc8_restore_interrupts(dev);
> >         lpt_init_pch_refclk(dev);
> > --
> > 1.8.3.1
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Rodrigo Vivi
> Blog: http://blog.vivi.eng.br
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 11/19] drm/i915: disable interrupts when enabling PC8
  2013-12-10 21:59   ` Daniel Vetter
@ 2013-12-11 21:33     ` Paulo Zanoni
  0 siblings, 0 replies; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-11 21:33 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development, Paulo Zanoni

2013/12/10 Daniel Vetter <daniel@ffwll.ch>:
> On Thu, Nov 21, 2013 at 01:47:25PM -0200, Paulo Zanoni wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> The plan is to merge PC8 and D3 into a single feature, and when we're
>> in D3 we won't get any hotplug interrupt anyway, so leaving them
>> enable doesn't make sense, and it also brings us a problem. The
>> problem is that we get a hotplug interrupt right when we we wake up
>> from D3, when we're still waking up everything. If we fully disable
>> interrupts we won't get this hotplug interrupt, so we won't have
>> problems.
>>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Now that we forgo the partial interrupt enabling of pc8 there's imo no
> need any more for the pc8 interrup reg save/restore dance. Instead it'd be
> much better to just disable the interrup by disabling the interrupt
> handler and then when reenabling things to use our core interrupt enabling
> functions.
>

I tried to do this in August, in one of the early PC8 implementations.
I showed you my implementation, we discussed and then concluded the
current approach was better. Of course, at that time I was trying to
keep the hotplug interrupts alive, so the code will look a little
better now, but I don't see too much benefit.


> This way the runtime d3 path uses the same code as resume and driver load.

Actually I recently had this crazy idea of doing the opposite: make
the suspend/resume code use the runtime PM code. But that's not
something I investigated deeply.


> Furthermore the D3 code will be a bit more generic, which helps with
> enabling platforms. But this can (should) be done in a follow-up.

I'll add it to the list.

> -Daniel
>> ---
>>  drivers/gpu/drm/i915/i915_irq.c | 26 +++++++++-----------------
>>  1 file changed, 9 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
>> index 70c4cef..d0f4e61 100644
>> --- a/drivers/gpu/drm/i915/i915_irq.c
>> +++ b/drivers/gpu/drm/i915/i915_irq.c
>> @@ -3902,8 +3902,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
>>       dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
>>       dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
>>
>> -     ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
>> -     ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
>> +     ironlake_disable_display_irq(dev_priv, 0xffffffff);
>> +     ibx_disable_display_interrupt(dev_priv, 0xffffffff);
>>       ilk_disable_gt_irq(dev_priv, 0xffffffff);
>>       snb_disable_pm_irq(dev_priv, 0xffffffff);
>>
>> @@ -3917,34 +3917,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
>>  {
>>       struct drm_i915_private *dev_priv = dev->dev_private;
>>       unsigned long irqflags;
>> -     uint32_t val, expected;
>> +     uint32_t val;
>>
>>       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>>
>>       val = I915_READ(DEIMR);
>> -     expected = ~DE_PCH_EVENT_IVB;
>> -     WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
>> +     WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
>>
>> -     val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
>> -     expected = ~SDE_HOTPLUG_MASK_CPT;
>> -     WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
>> -          val, expected);
>> +     val = I915_READ(SDEIMR);
>> +     WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
>>
>>       val = I915_READ(GTIMR);
>> -     expected = 0xffffffff;
>> -     WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
>> +     WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
>>
>>       val = I915_READ(GEN6_PMIMR);
>> -     expected = 0xffffffff;
>> -     WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
>> -          expected);
>> +     WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
>>
>>       dev_priv->pc8.irqs_disabled = false;
>>
>>       ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
>> -     ibx_enable_display_interrupt(dev_priv,
>> -                                  ~dev_priv->pc8.regsave.sdeimr &
>> -                                  ~SDE_HOTPLUG_MASK_CPT);
>> +     ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
>>       ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
>>       snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
>>       I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-12-10 21:49             ` Daniel Vetter
@ 2013-12-12 20:07               ` Paulo Zanoni
  2013-12-12 20:54                 ` Daniel Vetter
  0 siblings, 1 reply; 97+ messages in thread
From: Paulo Zanoni @ 2013-12-12 20:07 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development, Paulo Zanoni

2013/12/10 Daniel Vetter <daniel@ffwll.ch>:
> On Fri, Nov 29, 2013 at 11:03:38AM -0200, Rodrigo Vivi wrote:
>> On Wed, Nov 27, 2013 at 06:20:34PM -0200, Paulo Zanoni wrote:
>> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
>> > index 2715600..70c4cef 100644
>> > --- a/drivers/gpu/drm/i915/i915_irq.c
>> > +++ b/drivers/gpu/drm/i915/i915_irq.c
>> > @@ -2477,6 +2477,12 @@ static void i915_hangcheck_elapsed(unsigned long data)
>> >     if (!i915_enable_hangcheck)
>> >             return;
>> >
>> > +   /* Just postpone in case we're completely idle... */
>> > +   if (dev_priv->pm.suspended) {
>> > +           i915_queue_hangcheck(dev);
>> > +           return;
>> > +   }
>>
>> I got the idea here, just not sure if it fits on this patch or it is just the commit message.
>
> This hunk here is the wrong thing to do: If we're suspended and the
> hangcheck fires, we'll just delay it. But if we keep on being suspended
> the hangcheck will fire at the normal recheck rate (but never do anything)
> which wreaks utter havoc with deep sleep residency. The simples solution
> would be to synchronously cancel the timer in the idle work (where we
> already put the execbuf runtime ref) I think.
>

The problem is that if I do this, then we won't end up running the
hangcheck (which we always run today), so we won't check for hangs,
which is probably not good. I could add "i915_force_hangcheck" what
would be called at intel_mark_idle if you would like, but I'm not too
sure what are the downsides of doing this.

I also tried getting/putting a refcount on the hangcheck function, but
I get complaints that it's sleeping from an invalid context.

Which approach is the best?



> I've dropped this hunk from the patch when merging.
> -Daniel
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 97+ messages in thread

* Re: [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places
  2013-12-12 20:07               ` Paulo Zanoni
@ 2013-12-12 20:54                 ` Daniel Vetter
  0 siblings, 0 replies; 97+ messages in thread
From: Daniel Vetter @ 2013-12-12 20:54 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Paulo Zanoni

On Thu, Dec 12, 2013 at 9:07 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> This hunk here is the wrong thing to do: If we're suspended and the
>> hangcheck fires, we'll just delay it. But if we keep on being suspended
>> the hangcheck will fire at the normal recheck rate (but never do anything)
>> which wreaks utter havoc with deep sleep residency. The simples solution
>> would be to synchronously cancel the timer in the idle work (where we
>> already put the execbuf runtime ref) I think.
>>
>
> The problem is that if I do this, then we won't end up running the
> hangcheck (which we always run today), so we won't check for hangs,
> which is probably not good. I could add "i915_force_hangcheck" what
> would be called at intel_mark_idle if you would like, but I'm not too
> sure what are the downsides of doing this.

If the gpu is truly idle then there's no need to run the hangcheck any
more ... So I don't understand why we can't cancel it before we drop
the gpu-is-busy runtime pm reference.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 97+ messages in thread

end of thread, other threads:[~2013-12-12 20:54 UTC | newest]

Thread overview: 97+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-21 15:47 [PATCH 00/19] Haswell runtime PM support + D3 Paulo Zanoni
2013-11-21 15:47 ` [PATCH 01/19] drm/i915: WARN if !HAS_PC8 when enabling/disabling PC8 Paulo Zanoni
2013-11-29 11:11   ` Rodrigo Vivi
2013-11-29 12:55     ` Paulo Zanoni
2013-11-29 13:31       ` Rodrigo Vivi
2013-11-21 15:47 ` [PATCH 02/19] drm/i915: use the correct force_wake function at the PC8 code Paulo Zanoni
2013-11-27 19:57   ` Paulo Zanoni
2013-11-29 11:14     ` [Intel-gfx] " Rodrigo Vivi
2013-11-29 13:23       ` Daniel Vetter
2013-11-21 15:47 ` [PATCH 03/19] drm/i915: get a PC8 reference when enabling the power well Paulo Zanoni
2013-11-27 19:59   ` Paulo Zanoni
2013-11-29 12:35     ` Rodrigo Vivi
2013-11-29 13:34       ` Rodrigo Vivi
2013-12-10 21:29     ` Daniel Vetter
2013-11-21 15:47 ` [PATCH 04/19] drm/i915: get/put PC8 when we get/put a CRTC Paulo Zanoni
2013-11-21 16:12   ` Chris Wilson
2013-11-27 20:01     ` Paulo Zanoni
2013-11-29 12:38       ` Rodrigo Vivi
2013-11-29 13:34         ` Rodrigo Vivi
2013-12-04  9:01   ` Daniel Vetter
2013-12-04 13:44     ` Paulo Zanoni
2013-12-04 14:07       ` Daniel Vetter
2013-12-05 13:43         ` Paulo Zanoni
2013-12-05 14:40           ` Daniel Vetter
2013-12-06 22:29             ` [PATCH] drm/i915: change CRTC assertion on LCPLL disable Paulo Zanoni
2013-12-06 22:37               ` Daniel Vetter
2013-11-21 15:47 ` [PATCH 05/19] drm/i915: add initial Runtime PM functions Paulo Zanoni
2013-11-27 20:10   ` Paulo Zanoni
2013-11-29 12:54     ` Rodrigo Vivi
2013-11-29 13:33       ` Rodrigo Vivi
2013-11-29 14:05     ` Takashi Iwai
2013-12-06 22:31       ` Paulo Zanoni
2013-12-06 22:32         ` Paulo Zanoni
2013-12-08  9:06         ` Takashi Iwai
2013-12-02 12:23   ` Imre Deak
2013-11-21 15:47 ` [PATCH 06/19] drm/i915: do adapter power state notification at runtime PM Paulo Zanoni
2013-11-21 16:14   ` Chris Wilson
2013-11-27 20:13     ` Paulo Zanoni
2013-11-29 12:56       ` Rodrigo Vivi
2013-11-29 13:33         ` Rodrigo Vivi
2013-12-06 22:34         ` Paulo Zanoni
2013-11-21 15:47 ` [PATCH 07/19] drm/i915: add runtime put/get calls at the basic places Paulo Zanoni
2013-11-21 16:07   ` Chris Wilson
2013-11-25 20:55     ` Paulo Zanoni
2013-11-25 21:21       ` Chris Wilson
2013-11-27 20:20         ` Paulo Zanoni
2013-11-29 13:03           ` Rodrigo Vivi
2013-11-29 13:32             ` Rodrigo Vivi
2013-12-10 21:49             ` Daniel Vetter
2013-12-12 20:07               ` Paulo Zanoni
2013-12-12 20:54                 ` Daniel Vetter
2013-11-21 15:47 ` [PATCH 08/19] drm/i915: add some runtime PM get/put calls Paulo Zanoni
2013-11-27 20:21   ` Paulo Zanoni
2013-11-29 13:05     ` Rodrigo Vivi
2013-11-29 13:31       ` Rodrigo Vivi
2013-11-29 13:42       ` Daniel Vetter
2013-11-29 13:56         ` Paulo Zanoni
2013-11-21 15:47 ` [PATCH 09/19] drm/i915: get a runtime PM reference when the panel VDD is on Paulo Zanoni
2013-11-29 13:50   ` Rodrigo Vivi
2013-11-29 13:59     ` Paulo Zanoni
2013-11-29 14:37       ` Rodrigo Vivi
2013-12-06 22:23         ` Paulo Zanoni
2013-11-21 15:47 ` [PATCH 10/19] drm/i915: do not assert DE_PCH_EVENT_IVB enabled Paulo Zanoni
2013-11-29 14:30   ` Rodrigo Vivi
2013-12-10 21:54   ` Daniel Vetter
2013-11-21 15:47 ` [PATCH 11/19] drm/i915: disable interrupts when enabling PC8 Paulo Zanoni
2013-12-02 13:33   ` Rodrigo Vivi
2013-12-10 21:59   ` Daniel Vetter
2013-12-11 21:33     ` Paulo Zanoni
2013-11-21 15:47 ` [PATCH 12/19] drm/i915: release the GTT mmaps when going into D3 Paulo Zanoni
2013-11-21 16:02   ` Chris Wilson
2013-11-21 16:27     ` Paulo Zanoni
2013-12-10 22:03   ` Daniel Vetter
2013-11-21 15:47 ` [PATCH 13/19] drm: do not steal the display if we have a master Paulo Zanoni
2013-11-21 16:04   ` Chris Wilson
2013-11-27 20:24     ` Paulo Zanoni
2013-11-29 13:37       ` Daniel Vetter
2013-11-30 11:19       ` David Herrmann
2013-11-21 15:47 ` [PATCH 14/19] drm/i915: add runtime PM support on Haswell Paulo Zanoni
2013-12-02 13:37   ` Rodrigo Vivi
2013-12-10 22:10     ` Daniel Vetter
2013-12-10 22:06   ` Daniel Vetter
2013-11-21 15:47 ` [PATCH 15/19] drm/i915: don't enable VDD just to enable the panel Paulo Zanoni
2013-11-29 14:40   ` Rodrigo Vivi
2013-11-21 15:47 ` [PATCH 16/19] drm/i915: don't touch the VDD when disabling " Paulo Zanoni
2013-11-29 14:41   ` Rodrigo Vivi
2013-11-21 15:47 ` [PATCH 17/19] drm/i915: fix VDD override off wait Paulo Zanoni
2013-11-21 15:47 ` [PATCH 18/19] drm/i915: save some time when waiting the eDP timings Paulo Zanoni
2013-11-21 16:00   ` Chris Wilson
2013-11-25 22:17     ` Ben Widawsky
2013-11-25 23:25       ` Chris Wilson
2013-11-26  2:38         ` Ben Widawsky
2013-11-26  9:14           ` Chris Wilson
2013-11-26 15:53             ` Paulo Zanoni
2013-11-21 15:47 ` [PATCH 19/19] drm/i915: init the DP panel power seq regs earlier Paulo Zanoni
2013-12-05 15:00   ` Jani Nikula
2013-12-06 18:39     ` Paulo Zanoni

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.