All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/6] enabling runtime on BYT
@ 2014-01-22 12:04 naresh.kumar.kachhi
  2014-01-22 12:04 ` [RFC 1/6] drm/i915: cover ioctls with runtime_get/put naresh.kumar.kachhi
                   ` (5 more replies)
  0 siblings, 6 replies; 23+ messages in thread
From: naresh.kumar.kachhi @ 2014-01-22 12:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: Naresh Kumar Kachhi

From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

This is the first set of patches to enable runtime pm for BYT.
These patches are created keeping in mind that PC8 feature will
be replaced with runtime pm. So all the patches are on assumption
that HAS_RUNTIME_PM is true while HAS_PC8 is false.
This set is mainly to cover the accesses with runtime_[get/put].
while the second set (WIP) will be to introduce BYT specific
runtime_[suspend/resume].

Naresh Kumar Kachhi (6):
  drm/i915: cover ioctls with runtime_get/put
  drm/i915: cover ring access with rpm get/put
  drm/i915: introduce runtime get/put based on display activity
  drm/i915/vlv: call runtime get/put based on disp activity
  drm/i915: device specific runtime suspend/resume
  FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init

 drivers/gpu/drm/i915/i915_dma.c            |   9 +-
 drivers/gpu/drm/i915/i915_drv.c            |  44 ++++++----
 drivers/gpu/drm/i915/i915_drv.h            |  18 +++-
 drivers/gpu/drm/i915/i915_gem.c            |  27 ++++--
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   4 +-
 drivers/gpu/drm/i915/i915_ioc32.c          |  11 ++-
 drivers/gpu/drm/i915/intel_display.c       |   3 +
 drivers/gpu/drm/i915/intel_drv.h           |   4 +
 drivers/gpu/drm/i915/intel_pm.c            | 135 +++++++++++++++++++++++++++++
 9 files changed, 222 insertions(+), 33 deletions(-)

-- 
1.8.1.2

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

* [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-22 12:04 [RFC 0/6] enabling runtime on BYT naresh.kumar.kachhi
@ 2014-01-22 12:04 ` naresh.kumar.kachhi
  2014-01-22 12:51   ` Daniel Vetter
  2014-01-22 13:35   ` Paulo Zanoni
  2014-01-22 12:04 ` [RFC 2/6] drm/i915: cover ring access with rpm get/put naresh.kumar.kachhi
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 23+ messages in thread
From: naresh.kumar.kachhi @ 2014-01-22 12:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: Naresh Kumar Kachhi

From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

With runtime PM enabled, we need to make sure that all HW access
are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
HW hangs. Ex. A hang is seen if display register is accessed on
BYT while display power island is power gated.

This patch is covering all the IOCTLs with get/put.
TODO: limit runtime_get/put to IOCTLs that accesses HW

Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c   | 21 ++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_ioc32.c | 11 +++++++++--
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 82c4605..80965be 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -845,6 +845,25 @@ i915_pci_remove(struct pci_dev *pdev)
 	drm_put_dev(dev);
 }
 
+static long i915_unlocked_ioctl(struct file *filp,
+	      unsigned int cmd, unsigned long arg)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_device *dev = file_priv->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	/* Don't do anything if device is not ready */
+	if (drm_device_is_unplugged(dev))
+		return -ENODEV;
+
+	intel_runtime_pm_get(dev_priv);
+	ret = drm_ioctl(filp, cmd, arg);
+	intel_runtime_pm_put(dev_priv);
+
+	return ret;
+}
+
 static int i915_pm_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -970,7 +989,7 @@ static const struct file_operations i915_driver_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_open,
 	.release = drm_release,
-	.unlocked_ioctl = drm_ioctl,
+	.unlocked_ioctl = i915_unlocked_ioctl,
 	.mmap = drm_gem_mmap,
 	.poll = drm_poll,
 	.read = drm_read,
diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c
index 3c59584..bfc773e 100644
--- a/drivers/gpu/drm/i915/i915_ioc32.c
+++ b/drivers/gpu/drm/i915/i915_ioc32.c
@@ -201,12 +201,17 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = {
  */
 long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_device *dev = file_priv->minor->dev;
 	unsigned int nr = DRM_IOCTL_NR(cmd);
 	drm_ioctl_compat_t *fn = NULL;
 	int ret;
 
-	if (nr < DRM_COMMAND_BASE)
-		return drm_compat_ioctl(filp, cmd, arg);
+	intel_runtime_pm_get(dev->dev_private);
+	if (nr < DRM_COMMAND_BASE) {
+		ret = drm_compat_ioctl(filp, cmd, arg);
+		goto out;
+	}
 
 	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
 		fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
@@ -216,6 +221,8 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	else
 		ret = drm_ioctl(filp, cmd, arg);
 
+out:
+	intel_runtime_pm_put(dev->dev_private);
 	return ret;
 }
 #endif
-- 
1.8.1.2

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

* [RFC 2/6] drm/i915: cover ring access with rpm get/put
  2014-01-22 12:04 [RFC 0/6] enabling runtime on BYT naresh.kumar.kachhi
  2014-01-22 12:04 ` [RFC 1/6] drm/i915: cover ioctls with runtime_get/put naresh.kumar.kachhi
@ 2014-01-22 12:04 ` naresh.kumar.kachhi
  2014-01-22 13:39   ` Paulo Zanoni
  2014-01-22 12:04 ` [RFC 3/6] drm/i915: introduce runtime get/put based on display activity naresh.kumar.kachhi
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: naresh.kumar.kachhi @ 2014-01-22 12:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: Naresh Kumar Kachhi

From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

GPU idleness is tracked by checking the request queue. Whenever
request queue is empty we assume that GPU is idle. When a new
set of commands sheduled on ring we call i915_add_request to
make sure these commands are tracked properly. However there are
few places which are not being treacked currently.
This patch introduces a new function add_request_wo_flush to track
such requests. add_request_wo_flush is same as add_request, only
difference is that it will not cause a flush. This is to avoid
any extra overhead while adding new request.

To make sure Gfx is in D0 while there are still commands pending
on ring following is done.
- All the ioctls are already covered with get/put this makes sure
  at the time of scheduling commands on GPU, Gfx is in D0
- Once command scheduling is done, we call add_request to track
  ring activity.
- We call get_noresume if this is first request (ioctl is already
  covered with get_sync).
- put is called only when request_list becomes empty. i.e GPU is
  idle and there are no pending commands on the rings

Note: Make sure we don't do multiple add_request in same
ioctl/callback only one in the end is enough

Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c            |  5 ++++
 drivers/gpu/drm/i915/i915_drv.h            | 10 +++++--
 drivers/gpu/drm/i915/i915_gem.c            | 27 ++++++++++++-----
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  4 +--
 drivers/gpu/drm/i915/intel_display.c       |  1 +
 drivers/gpu/drm/i915/intel_drv.h           |  3 ++
 drivers/gpu/drm/i915/intel_pm.c            | 47 ++++++++++++++++++++++++++++++
 7 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ee9502b..b5af745 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -454,6 +454,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
 				   struct drm_clip_rect *cliprects,
 				   void *cmdbuf)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int nbox = cmd->num_cliprects;
 	int i = 0, count, ret;
 
@@ -480,6 +481,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
 	}
 
 	i915_emit_breadcrumb(dev);
+	i915_add_request_wo_flush(LP_RING(dev_priv));
 	return 0;
 }
 
@@ -542,6 +544,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
 	}
 
 	i915_emit_breadcrumb(dev);
+	i915_add_request_wo_flush(LP_RING(dev_priv));
 	return 0;
 }
 
@@ -595,6 +598,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
 		ADVANCE_LP_RING();
 	}
 
+	i915_add_request_wo_flush(LP_RING(dev_priv));
 	master_priv->sarea_priv->pf_current_page = dev_priv->dri1.current_page;
 	return 0;
 }
@@ -768,6 +772,7 @@ static int i915_emit_irq(struct drm_device * dev)
 		OUT_RING(dev_priv->dri1.counter);
 		OUT_RING(MI_USER_INTERRUPT);
 		ADVANCE_LP_RING();
+		i915_add_request_wo_flush(LP_RING(dev_priv));
 	}
 
 	return dev_priv->dri1.counter;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 56c720b..d1399f9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1324,6 +1324,7 @@ struct i915_package_c8 {
 
 struct i915_runtime_pm {
 	bool suspended;
+	bool gpu_idle;
 };
 
 enum intel_pipe_crc_source {
@@ -2063,7 +2064,7 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
 
 int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
 int i915_gem_object_sync(struct drm_i915_gem_object *obj,
-			 struct intel_ring_buffer *to);
+			 struct intel_ring_buffer *to, bool add_request);
 void i915_vma_move_to_active(struct i915_vma *vma,
 			     struct intel_ring_buffer *ring);
 int i915_gem_dumb_create(struct drm_file *file_priv,
@@ -2139,9 +2140,12 @@ int __must_check i915_gem_suspend(struct drm_device *dev);
 int __i915_add_request(struct intel_ring_buffer *ring,
 		       struct drm_file *file,
 		       struct drm_i915_gem_object *batch_obj,
-		       u32 *seqno);
+		       u32 *seqno,
+		       bool flush_caches);
 #define i915_add_request(ring, seqno) \
-	__i915_add_request(ring, NULL, NULL, seqno)
+	__i915_add_request(ring, NULL, NULL, seqno, true)
+#define i915_add_request_wo_flush(ring) \
+	__i915_add_request(ring, NULL, NULL, NULL, false)
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
 				 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 024e454..3e8202e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2136,7 +2136,8 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
 int __i915_add_request(struct intel_ring_buffer *ring,
 		       struct drm_file *file,
 		       struct drm_i915_gem_object *obj,
-		       u32 *out_seqno)
+		       u32 *out_seqno,
+		       bool flush_caches)
 {
 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	struct drm_i915_gem_request *request;
@@ -2152,9 +2153,11 @@ int __i915_add_request(struct intel_ring_buffer *ring,
 	 * is that the flush _must_ happen before the next request, no matter
 	 * what.
 	 */
-	ret = intel_ring_flush_all_caches(ring);
-	if (ret)
-		return ret;
+	if (flush_caches) {
+		ret = intel_ring_flush_all_caches(ring);
+		if (ret)
+			return ret;
+	}
 
 	request = ring->preallocated_lazy_request;
 	if (WARN_ON(request == NULL))
@@ -2219,6 +2222,7 @@ int __i915_add_request(struct intel_ring_buffer *ring,
 					   &dev_priv->mm.retire_work,
 					   round_jiffies_up_relative(HZ));
 			intel_mark_busy(dev_priv->dev);
+			intel_runtime_pm_gpu_busy(dev_priv);
 		}
 	}
 
@@ -2544,10 +2548,12 @@ i915_gem_retire_requests(struct drm_device *dev)
 		idle &= list_empty(&ring->request_list);
 	}
 
-	if (idle)
+	if (idle) {
 		mod_delayed_work(dev_priv->wq,
 				   &dev_priv->mm.idle_work,
 				   msecs_to_jiffies(100));
+		intel_runtime_pm_gpu_idle(dev_priv);
+	}
 
 	return idle;
 }
@@ -2691,6 +2697,8 @@ out:
  *
  * @obj: object which may be in use on another ring.
  * @to: ring we wish to use the object on. May be NULL.
+ * @add_request: do we need to add a request to track operations
+ *    submitted on ring with sync_to function
  *
  * This code is meant to abstract object synchronization with the GPU.
  * Calling with NULL implies synchronizing the object with the CPU
@@ -2700,7 +2708,7 @@ out:
  */
 int
 i915_gem_object_sync(struct drm_i915_gem_object *obj,
-		     struct intel_ring_buffer *to)
+		     struct intel_ring_buffer *to, bool add_request)
 {
 	struct intel_ring_buffer *from = obj->ring;
 	u32 seqno;
@@ -2724,12 +2732,15 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
 
 	trace_i915_gem_ring_sync_to(from, to, seqno);
 	ret = to->sync_to(to, from, seqno);
-	if (!ret)
+	if (!ret) {
 		/* We use last_read_seqno because sync_to()
 		 * might have just caused seqno wrap under
 		 * the radar.
 		 */
 		from->sync_seqno[idx] = obj->last_read_seqno;
+		if (add_request)
+			i915_add_request_wo_flush(to);
+	}
 
 	return ret;
 }
@@ -3707,7 +3718,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	int ret;
 
 	if (pipelined != obj->ring) {
-		ret = i915_gem_object_sync(obj, pipelined);
+		ret = i915_gem_object_sync(obj, pipelined, true);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 0c6bcff..bda7a06 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -832,7 +832,7 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
 
 	list_for_each_entry(vma, vmas, exec_list) {
 		struct drm_i915_gem_object *obj = vma->obj;
-		ret = i915_gem_object_sync(obj, ring);
+		ret = i915_gem_object_sync(obj, ring, false);
 		if (ret)
 			return ret;
 
@@ -969,7 +969,7 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev,
 	ring->gpu_caches_dirty = true;
 
 	/* Add a breadcrumb for the completion of the batch buffer */
-	(void)__i915_add_request(ring, file, obj, NULL);
+	(void)__i915_add_request(ring, file, obj, NULL, true);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ec96002..25eae03 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8624,6 +8624,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
 
 	intel_mark_page_flip_active(intel_crtc);
 	__intel_ring_advance(ring);
+	i915_add_request_wo_flush(ring);
 	return 0;
 
 err_unpin:
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7b3c209..9061aa7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -881,9 +881,12 @@ 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_get_noresume(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 intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_gpu_idle(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 b9b4fe4..991ff62 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5470,6 +5470,37 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
 	hsw_enable_package_c8(dev_priv);
 }
 
+void intel_runtime_pm_gpu_idle(struct drm_i915_private *dev_priv)
+{
+	if (!HAS_RUNTIME_PM(dev_priv->dev))
+		return;
+
+	/* don't need a seperate mutex here as callers are
+	 * already under struct_mutex
+	 */
+	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+	if (!dev_priv->pm.gpu_idle) {
+		dev_priv->pm.gpu_idle = true;
+		/* match with get in gpu_busy */
+		intel_runtime_pm_put(dev_priv);
+	}
+}
+
+void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv)
+{
+	if (!HAS_RUNTIME_PM(dev_priv->dev))
+		return;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+	if (dev_priv->pm.gpu_idle) {
+		dev_priv->pm.gpu_idle = false;
+		/* make sure that we keep the GPU on until request list
+		 * is empty
+		 */
+		intel_runtime_pm_get_noresume(dev_priv);
+	}
+}
+
 void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -5482,6 +5513,21 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
 	WARN(dev_priv->pm.suspended, "Device still suspended.\n");
 }
 
+void intel_runtime_pm_get_noresume(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;
+
+	/* driver calls no resume when it is sure that device is
+	 * already active and just want to increment the ref count
+	 */
+	WARN(dev_priv->pm.suspended, "Device suspended. call get_sync?\n");
+	pm_runtime_get_noresume(device);
+}
+
 void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -5500,6 +5546,7 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
 	struct device *device = &dev->pdev->dev;
 
 	dev_priv->pm.suspended = false;
+	dev_priv->pm.gpu_idle = true;
 
 	if (!HAS_RUNTIME_PM(dev))
 		return;
-- 
1.8.1.2

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

* [RFC 3/6] drm/i915: introduce runtime get/put based on display activity
  2014-01-22 12:04 [RFC 0/6] enabling runtime on BYT naresh.kumar.kachhi
  2014-01-22 12:04 ` [RFC 1/6] drm/i915: cover ioctls with runtime_get/put naresh.kumar.kachhi
  2014-01-22 12:04 ` [RFC 2/6] drm/i915: cover ring access with rpm get/put naresh.kumar.kachhi
@ 2014-01-22 12:04 ` naresh.kumar.kachhi
  2014-01-22 13:40   ` Paulo Zanoni
  2014-01-22 12:04 ` [RFC 4/6] drm/i915/vlv: call runtime get/put based on disp activity naresh.kumar.kachhi
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: naresh.kumar.kachhi @ 2014-01-22 12:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: Naresh Kumar Kachhi

From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

Once the display is disabled, we need to call runtime_put to
make sure Runtime framework triggers runtime_suspend based on
idleness. Similarly when display gets enabled, runtime_get should
be called. We have similiar function for pc8 feature, but some
platform(BYT) might not have pc8 feature, so creating a generic
function for runtime_pm

Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |  2 ++
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 drivers/gpu/drm/i915/intel_pm.c  | 50 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d1399f9..6a6f046 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1325,6 +1325,8 @@ struct i915_package_c8 {
 struct i915_runtime_pm {
 	bool suspended;
 	bool gpu_idle;
+	bool disp_idle;
+	struct mutex lock;
 };
 
 enum intel_pipe_crc_source {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9061aa7..94a6127 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -887,6 +887,7 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
 void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_gpu_idle(struct drm_i915_private *dev_priv);
+void intel_runtime_update_disp_state(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 991ff62..9d6d0e1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5501,6 +5501,54 @@ void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv)
 	}
 }
 
+static void intel_runtime_pm_disp_idle(struct drm_i915_private *dev_priv)
+{
+	if (!HAS_RUNTIME_PM(dev_priv->dev))
+		return;
+
+	mutex_lock(&dev_priv->pm.lock);
+	if (!dev_priv->pm.disp_idle) {
+		dev_priv->pm.disp_idle = true;
+		intel_runtime_pm_put(dev_priv);
+	}
+	mutex_unlock(&dev_priv->pm.lock);
+}
+
+static void intel_runtime_pm_disp_busy(struct drm_i915_private *dev_priv)
+{
+	if (!HAS_RUNTIME_PM(dev_priv->dev))
+		return;
+
+	mutex_lock(&dev_priv->pm.lock);
+	if (dev_priv->pm.disp_idle) {
+		dev_priv->pm.disp_idle = false;
+		/* This call is coming from an IOCTL so we have already done a
+		 * get_sync. get_noresume should suffice here
+		 */
+		intel_runtime_pm_get_noresume(dev_priv);
+	}
+	mutex_unlock(&dev_priv->pm.lock);
+}
+
+void intel_runtime_update_disp_state(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_crtc *crtc;
+	bool enabled = false;
+
+	if (!HAS_RUNTIME_PM(dev_priv->dev))
+		return;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
+		enabled |= crtc->base.enabled;
+
+	if (enabled)
+		intel_runtime_pm_disp_busy(dev_priv);
+	else
+		intel_runtime_pm_disp_idle(dev_priv);
+
+}
+
 void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -5547,6 +5595,8 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
 
 	dev_priv->pm.suspended = false;
 	dev_priv->pm.gpu_idle = true;
+	dev_priv->pm.disp_idle = true;
+	mutex_init(&dev_priv->pm.lock);
 
 	if (!HAS_RUNTIME_PM(dev))
 		return;
-- 
1.8.1.2

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

* [RFC 4/6] drm/i915/vlv: call runtime get/put based on disp activity
  2014-01-22 12:04 [RFC 0/6] enabling runtime on BYT naresh.kumar.kachhi
                   ` (2 preceding siblings ...)
  2014-01-22 12:04 ` [RFC 3/6] drm/i915: introduce runtime get/put based on display activity naresh.kumar.kachhi
@ 2014-01-22 12:04 ` naresh.kumar.kachhi
  2014-01-22 12:04 ` [RFC 5/6] drm/i915: device specific runtime suspend/resume naresh.kumar.kachhi
  2014-01-22 12:04 ` [RFC 6/6] FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init naresh.kumar.kachhi
  5 siblings, 0 replies; 23+ messages in thread
From: naresh.kumar.kachhi @ 2014-01-22 12:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: Naresh Kumar Kachhi

From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

do a runtime_get/put based on the display activity for valleyview
platrform

Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 25eae03..52aa5f3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4132,6 +4132,8 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
 
 	if (req_cdclk != cur_cdclk)
 		valleyview_set_cdclk(dev, req_cdclk);
+
+	intel_runtime_update_disp_state(dev_priv);
 }
 
 static void valleyview_crtc_enable(struct drm_crtc *crtc)
-- 
1.8.1.2

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

* [RFC 5/6] drm/i915: device specific runtime suspend/resume
  2014-01-22 12:04 [RFC 0/6] enabling runtime on BYT naresh.kumar.kachhi
                   ` (3 preceding siblings ...)
  2014-01-22 12:04 ` [RFC 4/6] drm/i915/vlv: call runtime get/put based on disp activity naresh.kumar.kachhi
@ 2014-01-22 12:04 ` naresh.kumar.kachhi
  2014-01-22 12:58   ` Daniel Vetter
  2014-01-22 12:04 ` [RFC 6/6] FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init naresh.kumar.kachhi
  5 siblings, 1 reply; 23+ messages in thread
From: naresh.kumar.kachhi @ 2014-01-22 12:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: Naresh Kumar Kachhi

From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

we might need special handling for different platforms.
for ex. baytrail. To handle this this patch creates function
pointers for runtime suspend/resume which are assigned
during driver load time

Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 23 ++++++++---------------
 drivers/gpu/drm/i915/i915_drv.h |  6 ++++++
 drivers/gpu/drm/i915/intel_pm.c | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 80965be..dc1cfab 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -935,19 +935,10 @@ static int i915_runtime_suspend(struct device *device)
 
 	DRM_DEBUG_KMS("Suspending device\n");
 
-	i915_gem_release_all_mmaps(dev_priv);
-
-	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
-	dev_priv->pm.suspended = true;
-
-	/*
-	 * current versions of firmware which depend on this opregion
-	 * notification have repurposed the D1 definition to mean
-	 * "runtime suspended" vs. what you would normally expect (D3)
-	 * to distinguish it from notifications that might be sent
-	 * via the suspend path.
-	 */
-	intel_opregion_notify_adapter(dev, PCI_D1);
+	if (dev_priv->pm.funcs.runtime_suspend)
+		dev_priv->pm.funcs.runtime_suspend(dev_priv);
+	else
+		DRM_ERROR("Device does not have runtime functions");
 
 	return 0;
 }
@@ -962,8 +953,10 @@ 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;
+	if (dev_priv->pm.funcs.runtime_resume)
+		dev_priv->pm.funcs.runtime_resume(dev_priv);
+	else
+		DRM_ERROR("Device does not have runtime functions");
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6a6f046..54aa31d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1322,11 +1322,17 @@ struct i915_package_c8 {
 	} regsave;
 };
 
+struct i915_runtime_pm_funcs {
+	int (*runtime_suspend)(struct drm_i915_private *dev_priv);
+	int (*runtime_resume)(struct drm_i915_private *dev_priv);
+};
+
 struct i915_runtime_pm {
 	bool suspended;
 	bool gpu_idle;
 	bool disp_idle;
 	struct mutex lock;
+	struct i915_runtime_pm_funcs funcs;
 };
 
 enum intel_pipe_crc_source {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 9d6d0e1..6713995 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5588,6 +5588,41 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
 	pm_runtime_put_autosuspend(device);
 }
 
+static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	WARN_ON(!HAS_RUNTIME_PM(dev));
+
+	i915_gem_release_all_mmaps(dev_priv);
+
+	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
+	dev_priv->pm.suspended = true;
+
+	/*
+	 * current versions of firmware which depend on this opregion
+	 * notification have repurposed the D1 definition to mean
+	 * "runtime suspended" vs. what you would normally expect (D3)
+	 * to distinguish it from notifications that might be sent
+	 * via the suspend path.
+	 */
+	intel_opregion_notify_adapter(dev, PCI_D1);
+
+
+	return 0;
+}
+
+static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	WARN_ON(!HAS_RUNTIME_PM(dev));
+
+	intel_opregion_notify_adapter(dev_priv->dev, PCI_D0);
+	dev_priv->pm.suspended = false;
+
+	return 0;
+}
+
 void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -5606,6 +5641,9 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
 	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
 	pm_runtime_mark_last_busy(device);
 	pm_runtime_use_autosuspend(device);
+
+	dev_priv->pm.funcs.runtime_suspend = hsw_runtime_suspend;
+	dev_priv->pm.funcs.runtime_resume = hsw_runtime_resume;
 }
 
 void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
-- 
1.8.1.2

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

* [RFC 6/6] FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init
  2014-01-22 12:04 [RFC 0/6] enabling runtime on BYT naresh.kumar.kachhi
                   ` (4 preceding siblings ...)
  2014-01-22 12:04 ` [RFC 5/6] drm/i915: device specific runtime suspend/resume naresh.kumar.kachhi
@ 2014-01-22 12:04 ` naresh.kumar.kachhi
  2014-01-22 13:44   ` Paulo Zanoni
  5 siblings, 1 reply; 23+ messages in thread
From: naresh.kumar.kachhi @ 2014-01-22 12:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: Naresh Kumar Kachhi

From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

with current code intel_runtime_pm_gpu_idle is getting called
even before runtime_pm is initialized. Moving runtime_pm_init
before i915_gem_init

Following is the call stack, note: by this time
runtime_pm was not initialized

intel_runtime_pm_gpu_idle+0x37/0x90
i915_gem_retire_requests+0x8d/0xa0
i915_gem_init_seqno+0x48/0x90
i915_gem_set_seqno+0x2a/0x70
i915_gem_init_hw+0x19c/0x300
?
i915_gem_context_init+0x123/0x220
i915_gem_init+0x57/0x1a0
i915_driver_load+0xbf4/0xd50

Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index b5af745..85162da 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1511,6 +1511,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	mutex_init(&dev_priv->dpio_lock);
 	mutex_init(&dev_priv->modeset_restore_lock);
 
+	intel_init_runtime_pm(dev_priv);
+
 	intel_pm_setup(dev);
 
 	intel_display_crc_init(dev);
@@ -1674,8 +1676,6 @@ 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:
-- 
1.8.1.2

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

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-22 12:04 ` [RFC 1/6] drm/i915: cover ioctls with runtime_get/put naresh.kumar.kachhi
@ 2014-01-22 12:51   ` Daniel Vetter
  2014-01-22 13:23     ` Imre Deak
  2014-01-22 13:35   ` Paulo Zanoni
  1 sibling, 1 reply; 23+ messages in thread
From: Daniel Vetter @ 2014-01-22 12:51 UTC (permalink / raw)
  To: naresh.kumar.kachhi; +Cc: intel-gfx

On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com wrote:
> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> 
> With runtime PM enabled, we need to make sure that all HW access
> are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
> HW hangs. Ex. A hang is seen if display register is accessed on
> BYT while display power island is power gated.
> 
> This patch is covering all the IOCTLs with get/put.
> TODO: limit runtime_get/put to IOCTLs that accesses HW
> 
> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

Nack on the concept. We need to have get/put calls for the individual
functional blocks of the hw, which then in turn (if it's not the top-level
power domain) need to grab references to the next up power domain.
Splattering unconditional get/puts over all driver entry points is bad
style and imo also too fragile.

Also, with Paulos final runtime pm/pc8 unification patches and Imre's
display power well patches for byt we should have full coverage already.
Have you looked at the work of these too?
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.c   | 21 ++++++++++++++++++++-
>  drivers/gpu/drm/i915/i915_ioc32.c | 11 +++++++++--
>  2 files changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 82c4605..80965be 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -845,6 +845,25 @@ i915_pci_remove(struct pci_dev *pdev)
>  	drm_put_dev(dev);
>  }
>  
> +static long i915_unlocked_ioctl(struct file *filp,
> +	      unsigned int cmd, unsigned long arg)
> +{
> +	struct drm_file *file_priv = filp->private_data;
> +	struct drm_device *dev = file_priv->minor->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	int ret;
> +
> +	/* Don't do anything if device is not ready */
> +	if (drm_device_is_unplugged(dev))
> +		return -ENODEV;
> +
> +	intel_runtime_pm_get(dev_priv);
> +	ret = drm_ioctl(filp, cmd, arg);
> +	intel_runtime_pm_put(dev_priv);
> +
> +	return ret;
> +}
> +
>  static int i915_pm_suspend(struct device *dev)
>  {
>  	struct pci_dev *pdev = to_pci_dev(dev);
> @@ -970,7 +989,7 @@ static const struct file_operations i915_driver_fops = {
>  	.owner = THIS_MODULE,
>  	.open = drm_open,
>  	.release = drm_release,
> -	.unlocked_ioctl = drm_ioctl,
> +	.unlocked_ioctl = i915_unlocked_ioctl,
>  	.mmap = drm_gem_mmap,
>  	.poll = drm_poll,
>  	.read = drm_read,
> diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c
> index 3c59584..bfc773e 100644
> --- a/drivers/gpu/drm/i915/i915_ioc32.c
> +++ b/drivers/gpu/drm/i915/i915_ioc32.c
> @@ -201,12 +201,17 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = {
>   */
>  long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  {
> +	struct drm_file *file_priv = filp->private_data;
> +	struct drm_device *dev = file_priv->minor->dev;
>  	unsigned int nr = DRM_IOCTL_NR(cmd);
>  	drm_ioctl_compat_t *fn = NULL;
>  	int ret;
>  
> -	if (nr < DRM_COMMAND_BASE)
> -		return drm_compat_ioctl(filp, cmd, arg);
> +	intel_runtime_pm_get(dev->dev_private);
> +	if (nr < DRM_COMMAND_BASE) {
> +		ret = drm_compat_ioctl(filp, cmd, arg);
> +		goto out;
> +	}
>  
>  	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
>  		fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
> @@ -216,6 +221,8 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  	else
>  		ret = drm_ioctl(filp, cmd, arg);
>  
> +out:
> +	intel_runtime_pm_put(dev->dev_private);
>  	return ret;
>  }
>  #endif
> -- 
> 1.8.1.2
> 
> _______________________________________________
> 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] 23+ messages in thread

* Re: [RFC 5/6] drm/i915: device specific runtime suspend/resume
  2014-01-22 12:04 ` [RFC 5/6] drm/i915: device specific runtime suspend/resume naresh.kumar.kachhi
@ 2014-01-22 12:58   ` Daniel Vetter
  2014-01-24 15:23     ` Naresh Kumar Kachhi
  0 siblings, 1 reply; 23+ messages in thread
From: Daniel Vetter @ 2014-01-22 12:58 UTC (permalink / raw)
  To: naresh.kumar.kachhi; +Cc: intel-gfx

On Wed, Jan 22, 2014 at 05:34:21PM +0530, naresh.kumar.kachhi@intel.com wrote:
> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> 
> we might need special handling for different platforms.
> for ex. baytrail. To handle this this patch creates function
> pointers for runtime suspend/resume which are assigned
> during driver load time
> 
> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

Again NAK on principles: vtables always have a cost, so before we add a
new one we need to demonstrate the need. Which means 2-3 different
implementations for the vfunc must exist. Sometimes some of these are
still embargo'ed in the -internal tree (like with the ppgtt refactor a
year ago) and that's ok.

The other reason I don't like this is that thus far the driver
load/teardown and suspend/resume sequences are generic. There are tricky
(sometimes really tricky) dependcies, but that's the design thus far. So
if we want to switch the design to per-platform functions we need good
reasons for that switch in general. Which means likely the same issues
will crop up in the normal suspend/resume and driver load/teardown paths.
Which leaves me wondering why we don't have this here.

Finally we've been bitten countless times through superflous differences
and duplicated codepaths between normal operation, suspend/resume, driver
load/teardown and now runtime pm. So again deviating from a shared code
pattern need excellent justification. Yes I know that atm pc8 has its own
stuff, and I expect this to hurt us eventually ;-)

Looking at this patch I don't see any of this.
-Daniel
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 23 ++++++++---------------
>  drivers/gpu/drm/i915/i915_drv.h |  6 ++++++
>  drivers/gpu/drm/i915/intel_pm.c | 38 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 52 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 80965be..dc1cfab 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -935,19 +935,10 @@ static int i915_runtime_suspend(struct device *device)
>  
>  	DRM_DEBUG_KMS("Suspending device\n");
>  
> -	i915_gem_release_all_mmaps(dev_priv);
> -
> -	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
> -	dev_priv->pm.suspended = true;
> -
> -	/*
> -	 * current versions of firmware which depend on this opregion
> -	 * notification have repurposed the D1 definition to mean
> -	 * "runtime suspended" vs. what you would normally expect (D3)
> -	 * to distinguish it from notifications that might be sent
> -	 * via the suspend path.
> -	 */
> -	intel_opregion_notify_adapter(dev, PCI_D1);
> +	if (dev_priv->pm.funcs.runtime_suspend)
> +		dev_priv->pm.funcs.runtime_suspend(dev_priv);
> +	else
> +		DRM_ERROR("Device does not have runtime functions");
>  
>  	return 0;
>  }
> @@ -962,8 +953,10 @@ 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;
> +	if (dev_priv->pm.funcs.runtime_resume)
> +		dev_priv->pm.funcs.runtime_resume(dev_priv);
> +	else
> +		DRM_ERROR("Device does not have runtime functions");
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 6a6f046..54aa31d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1322,11 +1322,17 @@ struct i915_package_c8 {
>  	} regsave;
>  };
>  
> +struct i915_runtime_pm_funcs {
> +	int (*runtime_suspend)(struct drm_i915_private *dev_priv);
> +	int (*runtime_resume)(struct drm_i915_private *dev_priv);
> +};
> +
>  struct i915_runtime_pm {
>  	bool suspended;
>  	bool gpu_idle;
>  	bool disp_idle;
>  	struct mutex lock;
> +	struct i915_runtime_pm_funcs funcs;
>  };
>  
>  enum intel_pipe_crc_source {
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 9d6d0e1..6713995 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5588,6 +5588,41 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>  	pm_runtime_put_autosuspend(device);
>  }
>  
> +static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +
> +	WARN_ON(!HAS_RUNTIME_PM(dev));
> +
> +	i915_gem_release_all_mmaps(dev_priv);
> +
> +	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
> +	dev_priv->pm.suspended = true;
> +
> +	/*
> +	 * current versions of firmware which depend on this opregion
> +	 * notification have repurposed the D1 definition to mean
> +	 * "runtime suspended" vs. what you would normally expect (D3)
> +	 * to distinguish it from notifications that might be sent
> +	 * via the suspend path.
> +	 */
> +	intel_opregion_notify_adapter(dev, PCI_D1);
> +
> +
> +	return 0;
> +}
> +
> +static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	WARN_ON(!HAS_RUNTIME_PM(dev));
> +
> +	intel_opregion_notify_adapter(dev_priv->dev, PCI_D0);
> +	dev_priv->pm.suspended = false;
> +
> +	return 0;
> +}
> +
>  void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> @@ -5606,6 +5641,9 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>  	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
>  	pm_runtime_mark_last_busy(device);
>  	pm_runtime_use_autosuspend(device);
> +
> +	dev_priv->pm.funcs.runtime_suspend = hsw_runtime_suspend;
> +	dev_priv->pm.funcs.runtime_resume = hsw_runtime_resume;
>  }
>  
>  void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
> -- 
> 1.8.1.2
> 
> _______________________________________________
> 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] 23+ messages in thread

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-22 12:51   ` Daniel Vetter
@ 2014-01-22 13:23     ` Imre Deak
  2014-01-24 15:05       ` Naresh Kumar Kachhi
  0 siblings, 1 reply; 23+ messages in thread
From: Imre Deak @ 2014-01-22 13:23 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, naresh.kumar.kachhi


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

On Wed, 2014-01-22 at 13:51 +0100, Daniel Vetter wrote:
> On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com wrote:
> > From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> > 
> > With runtime PM enabled, we need to make sure that all HW access
> > are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
> > HW hangs. Ex. A hang is seen if display register is accessed on
> > BYT while display power island is power gated.
> > 
> > This patch is covering all the IOCTLs with get/put.
> > TODO: limit runtime_get/put to IOCTLs that accesses HW
> > 
> > Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> 
> Nack on the concept. We need to have get/put calls for the individual
> functional blocks of the hw, which then in turn (if it's not the top-level
> power domain) need to grab references to the next up power domain.
> Splattering unconditional get/puts over all driver entry points is bad
> style and imo also too fragile.
> 
> Also, with Paulos final runtime pm/pc8 unification patches and Imre's
> display power well patches for byt we should have full coverage already.
> Have you looked at the work of these too?

I'm still in debt with the BYT specific power domain patches, I want to
post them (this week) after I sorted out spurious pipe stat IRQs we'd
receive atm with the power well off. Until then there is only the WIP
version at: https://github.com/ideak/linux/commits/powerwells

But in practice, as you point out the plan was to only call
modeset_update_power_wells() during modeset time and that will end up
doing the proper RPM get/put as necessary. Similarly on some other code
paths like connector detect and HW state read-out code, we'd ask only
for the needed power domains which would end up doing the RPM get/put.

--Imre


[-- 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] 23+ messages in thread

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-22 12:04 ` [RFC 1/6] drm/i915: cover ioctls with runtime_get/put naresh.kumar.kachhi
  2014-01-22 12:51   ` Daniel Vetter
@ 2014-01-22 13:35   ` Paulo Zanoni
  1 sibling, 0 replies; 23+ messages in thread
From: Paulo Zanoni @ 2014-01-22 13:35 UTC (permalink / raw)
  To: naresh.kumar.kachhi; +Cc: Intel Graphics Development

2014/1/22  <naresh.kumar.kachhi@intel.com>:
> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>
> With runtime PM enabled, we need to make sure that all HW access
> are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
> HW hangs. Ex. A hang is seen if display register is accessed on
> BYT while display power island is power gated.
>
> This patch is covering all the IOCTLs with get/put.
> TODO: limit runtime_get/put to IOCTLs that accesses HW
>
> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>

We believe the current upstream code is enough to get runtime PM
references whenever they are needed. Can you please point the cases
where we fail to do this?

Also, if you find a spot we don't cover, please also patch
intel-gpu-tools, adding new test cases to pm_pc8.c.

Thanks,
Paulo

> ---
>  drivers/gpu/drm/i915/i915_drv.c   | 21 ++++++++++++++++++++-
>  drivers/gpu/drm/i915/i915_ioc32.c | 11 +++++++++--
>  2 files changed, 29 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 82c4605..80965be 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -845,6 +845,25 @@ i915_pci_remove(struct pci_dev *pdev)
>         drm_put_dev(dev);
>  }
>
> +static long i915_unlocked_ioctl(struct file *filp,
> +             unsigned int cmd, unsigned long arg)
> +{
> +       struct drm_file *file_priv = filp->private_data;
> +       struct drm_device *dev = file_priv->minor->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       int ret;
> +
> +       /* Don't do anything if device is not ready */
> +       if (drm_device_is_unplugged(dev))
> +               return -ENODEV;
> +
> +       intel_runtime_pm_get(dev_priv);
> +       ret = drm_ioctl(filp, cmd, arg);
> +       intel_runtime_pm_put(dev_priv);
> +
> +       return ret;
> +}
> +
>  static int i915_pm_suspend(struct device *dev)
>  {
>         struct pci_dev *pdev = to_pci_dev(dev);
> @@ -970,7 +989,7 @@ static const struct file_operations i915_driver_fops = {
>         .owner = THIS_MODULE,
>         .open = drm_open,
>         .release = drm_release,
> -       .unlocked_ioctl = drm_ioctl,
> +       .unlocked_ioctl = i915_unlocked_ioctl,
>         .mmap = drm_gem_mmap,
>         .poll = drm_poll,
>         .read = drm_read,
> diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c
> index 3c59584..bfc773e 100644
> --- a/drivers/gpu/drm/i915/i915_ioc32.c
> +++ b/drivers/gpu/drm/i915/i915_ioc32.c
> @@ -201,12 +201,17 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = {
>   */
>  long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>  {
> +       struct drm_file *file_priv = filp->private_data;
> +       struct drm_device *dev = file_priv->minor->dev;
>         unsigned int nr = DRM_IOCTL_NR(cmd);
>         drm_ioctl_compat_t *fn = NULL;
>         int ret;
>
> -       if (nr < DRM_COMMAND_BASE)
> -               return drm_compat_ioctl(filp, cmd, arg);
> +       intel_runtime_pm_get(dev->dev_private);
> +       if (nr < DRM_COMMAND_BASE) {
> +               ret = drm_compat_ioctl(filp, cmd, arg);
> +               goto out;
> +       }
>
>         if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
>                 fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
> @@ -216,6 +221,8 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
>         else
>                 ret = drm_ioctl(filp, cmd, arg);
>
> +out:
> +       intel_runtime_pm_put(dev->dev_private);
>         return ret;
>  }
>  #endif
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [RFC 2/6] drm/i915: cover ring access with rpm get/put
  2014-01-22 12:04 ` [RFC 2/6] drm/i915: cover ring access with rpm get/put naresh.kumar.kachhi
@ 2014-01-22 13:39   ` Paulo Zanoni
  0 siblings, 0 replies; 23+ messages in thread
From: Paulo Zanoni @ 2014-01-22 13:39 UTC (permalink / raw)
  To: naresh.kumar.kachhi; +Cc: Intel Graphics Development

2014/1/22  <naresh.kumar.kachhi@intel.com>:
> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>
> GPU idleness is tracked by checking the request queue. Whenever
> request queue is empty we assume that GPU is idle. When a new
> set of commands sheduled on ring we call i915_add_request to
> make sure these commands are tracked properly. However there are
> few places which are not being treacked currently.
> This patch introduces a new function add_request_wo_flush to track
> such requests. add_request_wo_flush is same as add_request, only
> difference is that it will not cause a flush. This is to avoid
> any extra overhead while adding new request.
>
> To make sure Gfx is in D0 while there are still commands pending
> on ring following is done.
> - All the ioctls are already covered with get/put this makes sure
>   at the time of scheduling commands on GPU, Gfx is in D0
> - Once command scheduling is done, we call add_request to track
>   ring activity.
> - We call get_noresume if this is first request (ioctl is already
>   covered with get_sync).
> - put is called only when request_list becomes empty. i.e GPU is
>   idle and there are no pending commands on the rings
>
> Note: Make sure we don't do multiple add_request in same
> ioctl/callback only one in the end is enough
>

The PC8 code already has an infrastructure to track GPU idleness, and
I already submitted a patch to move that code to
dev_priv->pm.gpu_idle. Please see this patch:
http://patchwork.freedesktop.org/patch/16952/ . I suggest you should
try to reuse this infrastructure, and if you find any problems, please
add testcases to pm_pc8.c reproducing these problems.


> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c            |  5 ++++
>  drivers/gpu/drm/i915/i915_drv.h            | 10 +++++--
>  drivers/gpu/drm/i915/i915_gem.c            | 27 ++++++++++++-----
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |  4 +--
>  drivers/gpu/drm/i915/intel_display.c       |  1 +
>  drivers/gpu/drm/i915/intel_drv.h           |  3 ++
>  drivers/gpu/drm/i915/intel_pm.c            | 47 ++++++++++++++++++++++++++++++
>  7 files changed, 84 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index ee9502b..b5af745 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -454,6 +454,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
>                                    struct drm_clip_rect *cliprects,
>                                    void *cmdbuf)
>  {
> +       struct drm_i915_private *dev_priv = dev->dev_private;
>         int nbox = cmd->num_cliprects;
>         int i = 0, count, ret;
>
> @@ -480,6 +481,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
>         }
>
>         i915_emit_breadcrumb(dev);
> +       i915_add_request_wo_flush(LP_RING(dev_priv));
>         return 0;
>  }
>
> @@ -542,6 +544,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
>         }
>
>         i915_emit_breadcrumb(dev);
> +       i915_add_request_wo_flush(LP_RING(dev_priv));
>         return 0;
>  }
>
> @@ -595,6 +598,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
>                 ADVANCE_LP_RING();
>         }
>
> +       i915_add_request_wo_flush(LP_RING(dev_priv));
>         master_priv->sarea_priv->pf_current_page = dev_priv->dri1.current_page;
>         return 0;
>  }
> @@ -768,6 +772,7 @@ static int i915_emit_irq(struct drm_device * dev)
>                 OUT_RING(dev_priv->dri1.counter);
>                 OUT_RING(MI_USER_INTERRUPT);
>                 ADVANCE_LP_RING();
> +               i915_add_request_wo_flush(LP_RING(dev_priv));
>         }
>
>         return dev_priv->dri1.counter;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 56c720b..d1399f9 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1324,6 +1324,7 @@ struct i915_package_c8 {
>
>  struct i915_runtime_pm {
>         bool suspended;
> +       bool gpu_idle;
>  };
>
>  enum intel_pipe_crc_source {
> @@ -2063,7 +2064,7 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
>
>  int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
>  int i915_gem_object_sync(struct drm_i915_gem_object *obj,
> -                        struct intel_ring_buffer *to);
> +                        struct intel_ring_buffer *to, bool add_request);
>  void i915_vma_move_to_active(struct i915_vma *vma,
>                              struct intel_ring_buffer *ring);
>  int i915_gem_dumb_create(struct drm_file *file_priv,
> @@ -2139,9 +2140,12 @@ int __must_check i915_gem_suspend(struct drm_device *dev);
>  int __i915_add_request(struct intel_ring_buffer *ring,
>                        struct drm_file *file,
>                        struct drm_i915_gem_object *batch_obj,
> -                      u32 *seqno);
> +                      u32 *seqno,
> +                      bool flush_caches);
>  #define i915_add_request(ring, seqno) \
> -       __i915_add_request(ring, NULL, NULL, seqno)
> +       __i915_add_request(ring, NULL, NULL, seqno, true)
> +#define i915_add_request_wo_flush(ring) \
> +       __i915_add_request(ring, NULL, NULL, NULL, false)
>  int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
>                                  uint32_t seqno);
>  int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 024e454..3e8202e 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2136,7 +2136,8 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
>  int __i915_add_request(struct intel_ring_buffer *ring,
>                        struct drm_file *file,
>                        struct drm_i915_gem_object *obj,
> -                      u32 *out_seqno)
> +                      u32 *out_seqno,
> +                      bool flush_caches)
>  {
>         drm_i915_private_t *dev_priv = ring->dev->dev_private;
>         struct drm_i915_gem_request *request;
> @@ -2152,9 +2153,11 @@ int __i915_add_request(struct intel_ring_buffer *ring,
>          * is that the flush _must_ happen before the next request, no matter
>          * what.
>          */
> -       ret = intel_ring_flush_all_caches(ring);
> -       if (ret)
> -               return ret;
> +       if (flush_caches) {
> +               ret = intel_ring_flush_all_caches(ring);
> +               if (ret)
> +                       return ret;
> +       }
>
>         request = ring->preallocated_lazy_request;
>         if (WARN_ON(request == NULL))
> @@ -2219,6 +2222,7 @@ int __i915_add_request(struct intel_ring_buffer *ring,
>                                            &dev_priv->mm.retire_work,
>                                            round_jiffies_up_relative(HZ));
>                         intel_mark_busy(dev_priv->dev);
> +                       intel_runtime_pm_gpu_busy(dev_priv);
>                 }
>         }
>
> @@ -2544,10 +2548,12 @@ i915_gem_retire_requests(struct drm_device *dev)
>                 idle &= list_empty(&ring->request_list);
>         }
>
> -       if (idle)
> +       if (idle) {
>                 mod_delayed_work(dev_priv->wq,
>                                    &dev_priv->mm.idle_work,
>                                    msecs_to_jiffies(100));
> +               intel_runtime_pm_gpu_idle(dev_priv);
> +       }
>
>         return idle;
>  }
> @@ -2691,6 +2697,8 @@ out:
>   *
>   * @obj: object which may be in use on another ring.
>   * @to: ring we wish to use the object on. May be NULL.
> + * @add_request: do we need to add a request to track operations
> + *    submitted on ring with sync_to function
>   *
>   * This code is meant to abstract object synchronization with the GPU.
>   * Calling with NULL implies synchronizing the object with the CPU
> @@ -2700,7 +2708,7 @@ out:
>   */
>  int
>  i915_gem_object_sync(struct drm_i915_gem_object *obj,
> -                    struct intel_ring_buffer *to)
> +                    struct intel_ring_buffer *to, bool add_request)
>  {
>         struct intel_ring_buffer *from = obj->ring;
>         u32 seqno;
> @@ -2724,12 +2732,15 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
>
>         trace_i915_gem_ring_sync_to(from, to, seqno);
>         ret = to->sync_to(to, from, seqno);
> -       if (!ret)
> +       if (!ret) {
>                 /* We use last_read_seqno because sync_to()
>                  * might have just caused seqno wrap under
>                  * the radar.
>                  */
>                 from->sync_seqno[idx] = obj->last_read_seqno;
> +               if (add_request)
> +                       i915_add_request_wo_flush(to);
> +       }
>
>         return ret;
>  }
> @@ -3707,7 +3718,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
>         int ret;
>
>         if (pipelined != obj->ring) {
> -               ret = i915_gem_object_sync(obj, pipelined);
> +               ret = i915_gem_object_sync(obj, pipelined, true);
>                 if (ret)
>                         return ret;
>         }
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index 0c6bcff..bda7a06 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -832,7 +832,7 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
>
>         list_for_each_entry(vma, vmas, exec_list) {
>                 struct drm_i915_gem_object *obj = vma->obj;
> -               ret = i915_gem_object_sync(obj, ring);
> +               ret = i915_gem_object_sync(obj, ring, false);
>                 if (ret)
>                         return ret;
>
> @@ -969,7 +969,7 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev,
>         ring->gpu_caches_dirty = true;
>
>         /* Add a breadcrumb for the completion of the batch buffer */
> -       (void)__i915_add_request(ring, file, obj, NULL);
> +       (void)__i915_add_request(ring, file, obj, NULL, true);
>  }
>
>  static int
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ec96002..25eae03 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -8624,6 +8624,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
>
>         intel_mark_page_flip_active(intel_crtc);
>         __intel_ring_advance(ring);
> +       i915_add_request_wo_flush(ring);
>         return 0;
>
>  err_unpin:
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 7b3c209..9061aa7 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -881,9 +881,12 @@ 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_get_noresume(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 intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv);
> +void intel_runtime_pm_gpu_idle(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 b9b4fe4..991ff62 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5470,6 +5470,37 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
>         hsw_enable_package_c8(dev_priv);
>  }
>
> +void intel_runtime_pm_gpu_idle(struct drm_i915_private *dev_priv)
> +{
> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
> +               return;
> +
> +       /* don't need a seperate mutex here as callers are
> +        * already under struct_mutex
> +        */
> +       WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
> +       if (!dev_priv->pm.gpu_idle) {
> +               dev_priv->pm.gpu_idle = true;
> +               /* match with get in gpu_busy */
> +               intel_runtime_pm_put(dev_priv);
> +       }
> +}
> +
> +void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv)
> +{
> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
> +               return;
> +
> +       WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
> +       if (dev_priv->pm.gpu_idle) {
> +               dev_priv->pm.gpu_idle = false;
> +               /* make sure that we keep the GPU on until request list
> +                * is empty
> +                */
> +               intel_runtime_pm_get_noresume(dev_priv);
> +       }
> +}
> +
>  void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>  {
>         struct drm_device *dev = dev_priv->dev;
> @@ -5482,6 +5513,21 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>         WARN(dev_priv->pm.suspended, "Device still suspended.\n");
>  }
>
> +void intel_runtime_pm_get_noresume(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;
> +
> +       /* driver calls no resume when it is sure that device is
> +        * already active and just want to increment the ref count
> +        */
> +       WARN(dev_priv->pm.suspended, "Device suspended. call get_sync?\n");
> +       pm_runtime_get_noresume(device);
> +}
> +
>  void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>  {
>         struct drm_device *dev = dev_priv->dev;
> @@ -5500,6 +5546,7 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>         struct device *device = &dev->pdev->dev;
>
>         dev_priv->pm.suspended = false;
> +       dev_priv->pm.gpu_idle = true;
>
>         if (!HAS_RUNTIME_PM(dev))
>                 return;
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [RFC 3/6] drm/i915: introduce runtime get/put based on display activity
  2014-01-22 12:04 ` [RFC 3/6] drm/i915: introduce runtime get/put based on display activity naresh.kumar.kachhi
@ 2014-01-22 13:40   ` Paulo Zanoni
  2014-02-24  5:21     ` Naresh Kumar Kachhi
  0 siblings, 1 reply; 23+ messages in thread
From: Paulo Zanoni @ 2014-01-22 13:40 UTC (permalink / raw)
  To: naresh.kumar.kachhi; +Cc: Intel Graphics Development

Hi

2014/1/22  <naresh.kumar.kachhi@intel.com>:
> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>
> Once the display is disabled, we need to call runtime_put to
> make sure Runtime framework triggers runtime_suspend based on
> idleness. Similarly when display gets enabled, runtime_get should
> be called. We have similiar function for pc8 feature, but some
> platform(BYT) might not have pc8 feature, so creating a generic
> function for runtime_pm

Does this patch series help you somehow?
http://lists.freedesktop.org/archives/intel-gfx/2013-December/037721.html

>
> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h  |  2 ++
>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>  drivers/gpu/drm/i915/intel_pm.c  | 50 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 53 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index d1399f9..6a6f046 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1325,6 +1325,8 @@ struct i915_package_c8 {
>  struct i915_runtime_pm {
>         bool suspended;
>         bool gpu_idle;
> +       bool disp_idle;
> +       struct mutex lock;
>  };
>
>  enum intel_pipe_crc_source {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 9061aa7..94a6127 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -887,6 +887,7 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
>  void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_gpu_idle(struct drm_i915_private *dev_priv);
> +void intel_runtime_update_disp_state(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 991ff62..9d6d0e1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5501,6 +5501,54 @@ void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv)
>         }
>  }
>
> +static void intel_runtime_pm_disp_idle(struct drm_i915_private *dev_priv)
> +{
> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
> +               return;
> +
> +       mutex_lock(&dev_priv->pm.lock);
> +       if (!dev_priv->pm.disp_idle) {
> +               dev_priv->pm.disp_idle = true;
> +               intel_runtime_pm_put(dev_priv);
> +       }
> +       mutex_unlock(&dev_priv->pm.lock);
> +}
> +
> +static void intel_runtime_pm_disp_busy(struct drm_i915_private *dev_priv)
> +{
> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
> +               return;
> +
> +       mutex_lock(&dev_priv->pm.lock);
> +       if (dev_priv->pm.disp_idle) {
> +               dev_priv->pm.disp_idle = false;
> +               /* This call is coming from an IOCTL so we have already done a
> +                * get_sync. get_noresume should suffice here
> +                */
> +               intel_runtime_pm_get_noresume(dev_priv);
> +       }
> +       mutex_unlock(&dev_priv->pm.lock);
> +}
> +
> +void intel_runtime_update_disp_state(struct drm_i915_private *dev_priv)
> +{
> +       struct drm_device *dev = dev_priv->dev;
> +       struct intel_crtc *crtc;
> +       bool enabled = false;
> +
> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
> +               return;
> +
> +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
> +               enabled |= crtc->base.enabled;
> +
> +       if (enabled)
> +               intel_runtime_pm_disp_busy(dev_priv);
> +       else
> +               intel_runtime_pm_disp_idle(dev_priv);
> +
> +}
> +
>  void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>  {
>         struct drm_device *dev = dev_priv->dev;
> @@ -5547,6 +5595,8 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>
>         dev_priv->pm.suspended = false;
>         dev_priv->pm.gpu_idle = true;
> +       dev_priv->pm.disp_idle = true;
> +       mutex_init(&dev_priv->pm.lock);
>
>         if (!HAS_RUNTIME_PM(dev))
>                 return;
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [RFC 6/6] FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init
  2014-01-22 12:04 ` [RFC 6/6] FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init naresh.kumar.kachhi
@ 2014-01-22 13:44   ` Paulo Zanoni
  2014-01-24 15:11     ` Naresh Kumar Kachhi
  0 siblings, 1 reply; 23+ messages in thread
From: Paulo Zanoni @ 2014-01-22 13:44 UTC (permalink / raw)
  To: naresh.kumar.kachhi; +Cc: Intel Graphics Development

2014/1/22  <naresh.kumar.kachhi@intel.com>:
> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>
> with current code intel_runtime_pm_gpu_idle is getting called
> even before runtime_pm is initialized. Moving runtime_pm_init
> before i915_gem_init
>
> Following is the call stack, note: by this time
> runtime_pm was not initialized
>
> intel_runtime_pm_gpu_idle+0x37/0x90
> i915_gem_retire_requests+0x8d/0xa0
> i915_gem_init_seqno+0x48/0x90
> i915_gem_set_seqno+0x2a/0x70
> i915_gem_init_hw+0x19c/0x300
> ?
> i915_gem_context_init+0x123/0x220
> i915_gem_init+0x57/0x1a0
> i915_driver_load+0xbf4/0xd50

And why exactly is this a problem? Delaying intel_init_runtime_pm is a
nice thing because we don't want our driver trying to runtime suspend
while it's still being loaded.

>
> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index b5af745..85162da 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1511,6 +1511,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>         mutex_init(&dev_priv->dpio_lock);
>         mutex_init(&dev_priv->modeset_restore_lock);
>
> +       intel_init_runtime_pm(dev_priv);
> +
>         intel_pm_setup(dev);
>
>         intel_display_crc_init(dev);
> @@ -1674,8 +1676,6 @@ 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:
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-22 13:23     ` Imre Deak
@ 2014-01-24 15:05       ` Naresh Kumar Kachhi
  2014-01-24 15:56         ` Paulo Zanoni
  2014-01-24 17:23         ` Imre Deak
  0 siblings, 2 replies; 23+ messages in thread
From: Naresh Kumar Kachhi @ 2014-01-24 15:05 UTC (permalink / raw)
  To: imre.deak, Daniel Vetter; +Cc: intel-gfx, Satyanantha, Rama Gopal M


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

On 01/22/2014 06:53 PM, Imre Deak wrote:
> On Wed, 2014-01-22 at 13:51 +0100, Daniel Vetter wrote:
>> On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com wrote:
>>> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>>>
>>> With runtime PM enabled, we need to make sure that all HW access
>>> are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
>>> HW hangs. Ex. A hang is seen if display register is accessed on
>>> BYT while display power island is power gated.
>>>
>>> This patch is covering all the IOCTLs with get/put.
>>> TODO: limit runtime_get/put to IOCTLs that accesses HW
>>>
>>> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>> Nack on the concept. We need to have get/put calls for the individual
>> functional blocks of the hw, which then in turn (if it's not the top-level
>> power domain) need to grab references to the next up power domain.
>> Splattering unconditional get/puts over all driver entry points is bad
>> style and imo also too fragile.
>>
>> Also, with Paulos final runtime pm/pc8 unification patches and Imre's
>> display power well patches for byt we should have full coverage already.
>> Have you looked at the work of these too?
> I'm still in debt with the BYT specific power domain patches, I want to
> post them (this week) after I sorted out spurious pipe stat IRQs we'd
> receive atm with the power well off. Until then there is only the WIP
> version at: https://github.com/ideak/linux/commits/powerwells
>
> But in practice, as you point out the plan was to only call
> modeset_update_power_wells() during modeset time and that will end up
> doing the proper RPM get/put as necessary. Similarly on some other code
> paths like connector detect and HW state read-out code, we'd ask only
> for the needed power domains which would end up doing the RPM get/put.
>
> --Imre
>
Hi Imre,
I tried to go through your and Paulo's patches (http://patchwork.freedesktop.org/patch/16952/).
As per my understanding we are doing disp power well gate/ungate independent of we are in
runtime_suspend/resume state we might face problem here as on BYT interrupts are routed through
display power well, so we might have a situation where display power island is power gated,
but render workload is still active. As we won't be receiving any interrupt __wait_seq_no will
stall and we might end up in a TDR. We will not see the issue until display power gating is
enabled. I will try to include a test to cover this test

This can be avoided by adding display_get/put in runtime_resume/suspend.
I am not sure if this scenario will be applicable for HSW.

Need for covering ioclts:
However there is one more problem for LP platforms. Once display/render/media power
islands are power gated, system will enter into deeper sleep state causing Gunit to power
gate. We will loose the state once Gunit resumes, so Gunit restore and ring initialization is
required in runtime_resume. Even after adding these to runtime_suspend/resume, we will have
to make sure all the ring activities, Gunit register accesses are covered with runtime_get/put.
There are few places with current implementation where we might hit this problem.
Example:
i915_batchbuffer(ioctl)->i915_batchbuffer (gpu commands scheduled)
i915_irq_emit(ioctl) -> i915_emit_irq (gpu commands scheduled)
i915_cmdbuffer (ioctl) -> i915_dispatch_cmdbuffer-> i915_emit_cmds(gpu commands scheduled)
There are few more.
These ioclts not being covered with runtime_get/put will might cause invalid executions
if we are resuming for deeper power state (gunit was powergated).

solutions:
 From design perspective, we can cover all accesses at low level, but this means a lot of get/put
and also will have to make sure that we cover future accesses as well. As an other solution we
can cover these ioctls individually or can have a wrapper function (as purposed in this patch)
to cover the accesses (TODO: make them conditional to do get/put on few ioclts only).
I will try to upload refined patch with conditional get/put.

Thanks,
Naresh












[-- Attachment #1.2: Type: text/html, Size: 5080 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] 23+ messages in thread

* Re: [RFC 6/6] FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init
  2014-01-22 13:44   ` Paulo Zanoni
@ 2014-01-24 15:11     ` Naresh Kumar Kachhi
  0 siblings, 0 replies; 23+ messages in thread
From: Naresh Kumar Kachhi @ 2014-01-24 15:11 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development, Satyanantha, Rama Gopal M


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

On 01/22/2014 07:14 PM, Paulo Zanoni wrote:
> 2014/1/22<naresh.kumar.kachhi@intel.com>:
>> From: Naresh Kumar Kachhi<naresh.kumar.kachhi@intel.com>
>>
>> with current code intel_runtime_pm_gpu_idle is getting called
>> even before runtime_pm is initialized. Moving runtime_pm_init
>> before i915_gem_init
>>
>> Following is the call stack, note: by this time
>> runtime_pm was not initialized
>>
>> intel_runtime_pm_gpu_idle+0x37/0x90
>> i915_gem_retire_requests+0x8d/0xa0
>> i915_gem_init_seqno+0x48/0x90
>> i915_gem_set_seqno+0x2a/0x70
>> i915_gem_init_hw+0x19c/0x300
>> ?
>> i915_gem_context_init+0x123/0x220
>> i915_gem_init+0x57/0x1a0
>> i915_driver_load+0xbf4/0xd50
> And why exactly is this a problem? Delaying intel_init_runtime_pm is a
> nice thing because we don't want our driver trying to runtime suspend
> while it's still being loaded.

pm.gpu_idle will be false (dev_priv is zeroed) until the init_runtime_pm is called.
In the call stack mentioned above we might see a call to intel_runtime_pm_gpu_idle.
If runtime pm is not initialized by now, pm.gpu_idle will be false and we will do a
runtime_put, without a matching runtime_get.
However in you patch
http://lists.freedesktop.org/archives/intel-gfx/2013-December/037729.html, i saw
you have moved the initializing gpu_idle in intel_pm_setup, which will fix this problem.
We will not need this patch with your new patches.
only concern in this patch is that we are scattering the pm initialization across two
function (runtime_pm_init and pm_setup).


>> Signed-off-by: Naresh Kumar Kachhi<naresh.kumar.kachhi@intel.com>
>> ---
>>   drivers/gpu/drm/i915/i915_dma.c | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
>> index b5af745..85162da 100644
>> --- a/drivers/gpu/drm/i915/i915_dma.c
>> +++ b/drivers/gpu/drm/i915/i915_dma.c
>> @@ -1511,6 +1511,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>>          mutex_init(&dev_priv->dpio_lock);
>>          mutex_init(&dev_priv->modeset_restore_lock);
>>
>> +       intel_init_runtime_pm(dev_priv);
>> +
>>          intel_pm_setup(dev);
>>
>>          intel_display_crc_init(dev);
>> @@ -1674,8 +1676,6 @@ 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:
>> --
>> 1.8.1.2
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>


[-- Attachment #1.2: Type: text/html, Size: 3894 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] 23+ messages in thread

* Re: [RFC 5/6] drm/i915: device specific runtime suspend/resume
  2014-01-22 12:58   ` Daniel Vetter
@ 2014-01-24 15:23     ` Naresh Kumar Kachhi
  0 siblings, 0 replies; 23+ messages in thread
From: Naresh Kumar Kachhi @ 2014-01-24 15:23 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, Satyanantha, Rama Gopal M

On 01/22/2014 06:28 PM, Daniel Vetter wrote:
> On Wed, Jan 22, 2014 at 05:34:21PM +0530, naresh.kumar.kachhi@intel.com wrote:
>> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>>
>> we might need special handling for different platforms.
>> for ex. baytrail. To handle this this patch creates function
>> pointers for runtime suspend/resume which are assigned
>> during driver load time
>>
>> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> Again NAK on principles: vtables always have a cost, so before we add a
> new one we need to demonstrate the need. Which means 2-3 different
> implementations for the vfunc must exist. Sometimes some of these are
> still embargo'ed in the -internal tree (like with the ppgtt refactor a
> year ago) and that's ok.
>
> The other reason I don't like this is that thus far the driver
> load/teardown and suspend/resume sequences are generic. There are tricky
> (sometimes really tricky) dependcies, but that's the design thus far. So
> if we want to switch the design to per-platform functions we need good
> reasons for that switch in general. Which means likely the same issues
> will crop up in the normal suspend/resume and driver load/teardown paths.
> Which leaves me wondering why we don't have this here.
>
> Finally we've been bitten countless times through superflous differences
> and duplicated codepaths between normal operation, suspend/resume, driver
> load/teardown and now runtime pm. So again deviating from a shared code
> pattern need excellent justification. Yes I know that atm pc8 has its own
> stuff, and I expect this to hurt us eventually ;-)
>
> Looking at this patch I don't see any of this.
> -Daniel

Hi Daniel,
I agree with you here, we should try to have a generic solutions. But we have
different scenario in case of LP platform and mainstream. In case of LP we
might go to deeper sleep state (causing Gunit power gate), and might need
some extra work during runtime_suspend/resume. Also as on BYT interrupts are
routed through display power island, making display power gating dependent on
runtime_suspend/resume. which might not be the case for other platforms.
Yes, this patch is not conclusive to prove the need of a separate function
I am working on BYT runtime runtime_suspend/resume. Once done, we can evaluate if we
need a separate functions or not.


>> ---
>>   drivers/gpu/drm/i915/i915_drv.c | 23 ++++++++---------------
>>   drivers/gpu/drm/i915/i915_drv.h |  6 ++++++
>>   drivers/gpu/drm/i915/intel_pm.c | 38 ++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 52 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index 80965be..dc1cfab 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -935,19 +935,10 @@ static int i915_runtime_suspend(struct device *device)
>>   
>>   	DRM_DEBUG_KMS("Suspending device\n");
>>   
>> -	i915_gem_release_all_mmaps(dev_priv);
>> -
>> -	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
>> -	dev_priv->pm.suspended = true;
>> -
>> -	/*
>> -	 * current versions of firmware which depend on this opregion
>> -	 * notification have repurposed the D1 definition to mean
>> -	 * "runtime suspended" vs. what you would normally expect (D3)
>> -	 * to distinguish it from notifications that might be sent
>> -	 * via the suspend path.
>> -	 */
>> -	intel_opregion_notify_adapter(dev, PCI_D1);
>> +	if (dev_priv->pm.funcs.runtime_suspend)
>> +		dev_priv->pm.funcs.runtime_suspend(dev_priv);
>> +	else
>> +		DRM_ERROR("Device does not have runtime functions");
>>   
>>   	return 0;
>>   }
>> @@ -962,8 +953,10 @@ 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;
>> +	if (dev_priv->pm.funcs.runtime_resume)
>> +		dev_priv->pm.funcs.runtime_resume(dev_priv);
>> +	else
>> +		DRM_ERROR("Device does not have runtime functions");
>>   
>>   	return 0;
>>   }
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 6a6f046..54aa31d 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -1322,11 +1322,17 @@ struct i915_package_c8 {
>>   	} regsave;
>>   };
>>   
>> +struct i915_runtime_pm_funcs {
>> +	int (*runtime_suspend)(struct drm_i915_private *dev_priv);
>> +	int (*runtime_resume)(struct drm_i915_private *dev_priv);
>> +};
>> +
>>   struct i915_runtime_pm {
>>   	bool suspended;
>>   	bool gpu_idle;
>>   	bool disp_idle;
>>   	struct mutex lock;
>> +	struct i915_runtime_pm_funcs funcs;
>>   };
>>   
>>   enum intel_pipe_crc_source {
>> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> index 9d6d0e1..6713995 100644
>> --- a/drivers/gpu/drm/i915/intel_pm.c
>> +++ b/drivers/gpu/drm/i915/intel_pm.c
>> @@ -5588,6 +5588,41 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
>>   	pm_runtime_put_autosuspend(device);
>>   }
>>   
>> +static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
>> +{
>> +	struct drm_device *dev = dev_priv->dev;
>> +
>> +	WARN_ON(!HAS_RUNTIME_PM(dev));
>> +
>> +	i915_gem_release_all_mmaps(dev_priv);
>> +
>> +	del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
>> +	dev_priv->pm.suspended = true;
>> +
>> +	/*
>> +	 * current versions of firmware which depend on this opregion
>> +	 * notification have repurposed the D1 definition to mean
>> +	 * "runtime suspended" vs. what you would normally expect (D3)
>> +	 * to distinguish it from notifications that might be sent
>> +	 * via the suspend path.
>> +	 */
>> +	intel_opregion_notify_adapter(dev, PCI_D1);
>> +
>> +
>> +	return 0;
>> +}
>> +
>> +static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
>> +{
>> +	struct drm_device *dev = dev_priv->dev;
>> +	WARN_ON(!HAS_RUNTIME_PM(dev));
>> +
>> +	intel_opregion_notify_adapter(dev_priv->dev, PCI_D0);
>> +	dev_priv->pm.suspended = false;
>> +
>> +	return 0;
>> +}
>> +
>>   void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>>   {
>>   	struct drm_device *dev = dev_priv->dev;
>> @@ -5606,6 +5641,9 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>>   	pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
>>   	pm_runtime_mark_last_busy(device);
>>   	pm_runtime_use_autosuspend(device);
>> +
>> +	dev_priv->pm.funcs.runtime_suspend = hsw_runtime_suspend;
>> +	dev_priv->pm.funcs.runtime_resume = hsw_runtime_resume;
>>   }
>>   
>>   void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
>> -- 
>> 1.8.1.2
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-24 15:05       ` Naresh Kumar Kachhi
@ 2014-01-24 15:56         ` Paulo Zanoni
  2014-02-24  5:17           ` Naresh Kumar Kachhi
  2014-01-24 17:23         ` Imre Deak
  1 sibling, 1 reply; 23+ messages in thread
From: Paulo Zanoni @ 2014-01-24 15:56 UTC (permalink / raw)
  To: Naresh Kumar Kachhi; +Cc: Satyanantha, Rama Gopal M, Intel Graphics Development

2014/1/24 Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>:
> On 01/22/2014 06:53 PM, Imre Deak wrote:
>
> On Wed, 2014-01-22 at 13:51 +0100, Daniel Vetter wrote:
>
> On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com
> wrote:
>
> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>
> With runtime PM enabled, we need to make sure that all HW access
> are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
> HW hangs. Ex. A hang is seen if display register is accessed on
> BYT while display power island is power gated.
>
> This patch is covering all the IOCTLs with get/put.
> TODO: limit runtime_get/put to IOCTLs that accesses HW
>
> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>
> Nack on the concept. We need to have get/put calls for the individual
> functional blocks of the hw, which then in turn (if it's not the top-level
> power domain) need to grab references to the next up power domain.
> Splattering unconditional get/puts over all driver entry points is bad
> style and imo also too fragile.
>
> Also, with Paulos final runtime pm/pc8 unification patches and Imre's
> display power well patches for byt we should have full coverage already.
> Have you looked at the work of these too?
>
> I'm still in debt with the BYT specific power domain patches, I want to
> post them (this week) after I sorted out spurious pipe stat IRQs we'd
> receive atm with the power well off. Until then there is only the WIP
> version at: https://github.com/ideak/linux/commits/powerwells
>
> But in practice, as you point out the plan was to only call
> modeset_update_power_wells() during modeset time and that will end up
> doing the proper RPM get/put as necessary. Similarly on some other code
> paths like connector detect and HW state read-out code, we'd ask only
> for the needed power domains which would end up doing the RPM get/put.
>
> --Imre
>
> Hi Imre,
> I tried to go through your and Paulo's patches
> (http://patchwork.freedesktop.org/patch/16952/).
> As per my understanding we are doing disp power well gate/ungate independent
> of we are in
> runtime_suspend/resume state we might face problem here as on BYT interrupts
> are routed through
> display power well, so we might have a situation where display power island
> is power gated,
> but render workload is still active. As we won't be receiving any interrupt
> __wait_seq_no will
> stall and we might end up in a TDR. We will not see the issue until display
> power gating is
> enabled. I will try to include a test to cover this test
>
> This can be avoided by adding display_get/put in runtime_resume/suspend.
> I am not sure if this scenario will be applicable for HSW.
>
> Need for covering ioclts:
> However there is one more problem for LP platforms. Once
> display/render/media power
> islands are power gated, system will enter into deeper sleep state causing
> Gunit to power
> gate. We will loose the state once Gunit resumes, so Gunit restore and ring
> initialization is
> required in runtime_resume. Even after adding these to
> runtime_suspend/resume, we will have
> to make sure all the ring activities, Gunit register accesses are covered
> with runtime_get/put.
> There are few places with current implementation where we might hit this
> problem.
> Example:
> i915_batchbuffer(ioctl)->i915_batchbuffer (gpu commands scheduled)
> i915_irq_emit(ioctl) -> i915_emit_irq (gpu commands scheduled)
> i915_cmdbuffer (ioctl) -> i915_dispatch_cmdbuffer-> i915_emit_cmds(gpu
> commands scheduled)
> There are few more.
> These ioclts not being covered with runtime_get/put will might cause invalid
> executions
> if we are resuming for deeper power state (gunit was powergated).

If possible, please write pm_pc8.c subtests that reproduce all these
problems you found :)


>
> solutions:
> From design perspective, we can cover all accesses at low level, but this
> means a lot of get/put
> and also will have to make sure that we cover future accesses as well. As an
> other solution we
> can cover these ioctls individually or can have a wrapper function (as
> purposed in this patch)
> to cover the accesses (TODO: make them conditional to do get/put on few
> ioclts only).
> I will try to upload refined patch with conditional get/put.
>
> Thanks,
> Naresh
>
>
>
>
>
>
>
>
>
>
>
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>



-- 
Paulo Zanoni

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

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-24 15:05       ` Naresh Kumar Kachhi
  2014-01-24 15:56         ` Paulo Zanoni
@ 2014-01-24 17:23         ` Imre Deak
  2014-02-21 20:07           ` Jesse Barnes
  1 sibling, 1 reply; 23+ messages in thread
From: Imre Deak @ 2014-01-24 17:23 UTC (permalink / raw)
  To: Naresh Kumar Kachhi; +Cc: intel-gfx, Satyanantha, Rama Gopal M


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

On Fri, 2014-01-24 at 20:35 +0530, Naresh Kumar Kachhi wrote:
> On 01/22/2014 06:53 PM, Imre Deak wrote:
> 
> > On Wed, 2014-01-22 at 13:51 +0100, Daniel Vetter wrote:
> > > On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com wrote:
> > > > From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> > > > 
> > > > With runtime PM enabled, we need to make sure that all HW access
> > > > are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
> > > > HW hangs. Ex. A hang is seen if display register is accessed on
> > > > BYT while display power island is power gated.
> > > > 
> > > > This patch is covering all the IOCTLs with get/put.
> > > > TODO: limit runtime_get/put to IOCTLs that accesses HW
> > > > 
> > > > Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> > > Nack on the concept. We need to have get/put calls for the individual
> > > functional blocks of the hw, which then in turn (if it's not the top-level
> > > power domain) need to grab references to the next up power domain.
> > > Splattering unconditional get/puts over all driver entry points is bad
> > > style and imo also too fragile.
> > > 
> > > Also, with Paulos final runtime pm/pc8 unification patches and Imre's
> > > display power well patches for byt we should have full coverage already.
> > > Have you looked at the work of these too?
> > I'm still in debt with the BYT specific power domain patches, I want to
> > post them (this week) after I sorted out spurious pipe stat IRQs we'd
> > receive atm with the power well off. Until then there is only the WIP
> > version at: https://github.com/ideak/linux/commits/powerwells
> > 
> > But in practice, as you point out the plan was to only call
> > modeset_update_power_wells() during modeset time and that will end up
> > doing the proper RPM get/put as necessary. Similarly on some other code
> > paths like connector detect and HW state read-out code, we'd ask only
> > for the needed power domains which would end up doing the RPM get/put.
> > 
> > --Imre
> > 
> Hi Imre,
> I tried to go through your and Paulo's patches (http://patchwork.freedesktop.org/patch/16952/).
> As per my understanding we are doing disp power well gate/ungate independent of we are in 
> runtime_suspend/resume state we might face problem here as on BYT interrupts are routed through
> display power well, so we might have a situation where display power island is power gated,
> but render workload is still active. As we won't be receiving any interrupt __wait_seq_no will
> stall and we might end up in a TDR. We will not see the issue until display power gating is 
> enabled. I will try to include a test to cover this test

Hm, which exact interrupt routing are you referring to? At least on my
BYT I manage to power off only the display power well and keep the
render well on, while still being able to run for example
igt/tests/gem_render_copy, gem_render_linear_blits. I can see that
through /proc/interrupts that GT interrupts are properly generated. The
display side interrupt routing is of course off, for example the
PIPESTAT registers will read all 0xffffffff, but DEIIR, DEIMR, DEISR are
all seem to work ok.

--Imre

> This can be avoided by adding display_get/put in runtime_resume/suspend.
> I am not sure if this scenario will be applicable for HSW.
> 
> Need for covering ioclts:
> However there is one more problem for LP platforms. Once display/render/media power
> islands are power gated, system will enter into deeper sleep state causing Gunit to power
> gate. We will loose the state once Gunit resumes, so Gunit restore and ring initialization is
> required in runtime_resume. Even after adding these to runtime_suspend/resume, we will have
> to make sure all the ring activities, Gunit register accesses are covered with runtime_get/put.
> There are few places with current implementation where we might hit this problem.
> Example: 
> i915_batchbuffer(ioctl)->i915_batchbuffer (gpu commands scheduled)
> i915_irq_emit(ioctl) -> i915_emit_irq (gpu commands scheduled)
> i915_cmdbuffer (ioctl) -> i915_dispatch_cmdbuffer-> i915_emit_cmds(gpu commands scheduled)
> There are few more.
> These ioclts not being covered with runtime_get/put will might cause invalid executions
> if we are resuming for deeper power state (gunit was powergated).
> 
> solutions:
> From design perspective, we can cover all accesses at low level, but this means a lot of get/put
> and also will have to make sure that we cover future accesses as well. As an other solution we
> can cover these ioctls individually or can have a wrapper function (as purposed in this patch)
> to cover the accesses (TODO: make them conditional to do get/put on few ioclts only).
> I will try to upload refined patch with conditional get/put.
> 
> Thanks,
> Naresh
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 


[-- 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] 23+ messages in thread

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-24 17:23         ` Imre Deak
@ 2014-02-21 20:07           ` Jesse Barnes
  2014-02-24  5:30             ` Naresh Kumar Kachhi
  0 siblings, 1 reply; 23+ messages in thread
From: Jesse Barnes @ 2014-02-21 20:07 UTC (permalink / raw)
  To: imre.deak; +Cc: intel-gfx, Naresh Kumar Kachhi, Satyanantha, Rama Gopal M

On Fri, 24 Jan 2014 19:23:54 +0200
Imre Deak <imre.deak@intel.com> wrote:

> On Fri, 2014-01-24 at 20:35 +0530, Naresh Kumar Kachhi wrote:
> > On 01/22/2014 06:53 PM, Imre Deak wrote:
> > 
> > > On Wed, 2014-01-22 at 13:51 +0100, Daniel Vetter wrote:
> > > > On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com wrote:
> > > > > From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> > > > > 
> > > > > With runtime PM enabled, we need to make sure that all HW access
> > > > > are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
> > > > > HW hangs. Ex. A hang is seen if display register is accessed on
> > > > > BYT while display power island is power gated.
> > > > > 
> > > > > This patch is covering all the IOCTLs with get/put.
> > > > > TODO: limit runtime_get/put to IOCTLs that accesses HW
> > > > > 
> > > > > Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
> > > > Nack on the concept. We need to have get/put calls for the individual
> > > > functional blocks of the hw, which then in turn (if it's not the top-level
> > > > power domain) need to grab references to the next up power domain.
> > > > Splattering unconditional get/puts over all driver entry points is bad
> > > > style and imo also too fragile.
> > > > 
> > > > Also, with Paulos final runtime pm/pc8 unification patches and Imre's
> > > > display power well patches for byt we should have full coverage already.
> > > > Have you looked at the work of these too?
> > > I'm still in debt with the BYT specific power domain patches, I want to
> > > post them (this week) after I sorted out spurious pipe stat IRQs we'd
> > > receive atm with the power well off. Until then there is only the WIP
> > > version at: https://github.com/ideak/linux/commits/powerwells
> > > 
> > > But in practice, as you point out the plan was to only call
> > > modeset_update_power_wells() during modeset time and that will end up
> > > doing the proper RPM get/put as necessary. Similarly on some other code
> > > paths like connector detect and HW state read-out code, we'd ask only
> > > for the needed power domains which would end up doing the RPM get/put.
> > > 
> > > --Imre
> > > 
> > Hi Imre,
> > I tried to go through your and Paulo's patches (http://patchwork.freedesktop.org/patch/16952/).
> > As per my understanding we are doing disp power well gate/ungate independent of we are in 
> > runtime_suspend/resume state we might face problem here as on BYT interrupts are routed through
> > display power well, so we might have a situation where display power island is power gated,
> > but render workload is still active. As we won't be receiving any interrupt __wait_seq_no will
> > stall and we might end up in a TDR. We will not see the issue until display power gating is 
> > enabled. I will try to include a test to cover this test
> 
> Hm, which exact interrupt routing are you referring to? At least on my
> BYT I manage to power off only the display power well and keep the
> render well on, while still being able to run for example
> igt/tests/gem_render_copy, gem_render_linear_blits. I can see that
> through /proc/interrupts that GT interrupts are properly generated. The
> display side interrupt routing is of course off, for example the
> PIPESTAT registers will read all 0xffffffff, but DEIIR, DEIMR, DEISR are
> all seem to work ok.

I think Naresh is referring to full D3 state shutdown, where the Gunit
goes away too.  But in that case the GT will be shut down as well, so I
don't think the display vs GT thing by itself is a problem.

-- 
Jesse Barnes, Intel Open Source Technology Center

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

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-01-24 15:56         ` Paulo Zanoni
@ 2014-02-24  5:17           ` Naresh Kumar Kachhi
  0 siblings, 0 replies; 23+ messages in thread
From: Naresh Kumar Kachhi @ 2014-02-24  5:17 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Satyanantha, Rama Gopal M, Intel Graphics Development

On 01/24/2014 09:26 PM, Paulo Zanoni wrote:
> 2014/1/24 Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>:
>> On 01/22/2014 06:53 PM, Imre Deak wrote:
>>
>> On Wed, 2014-01-22 at 13:51 +0100, Daniel Vetter wrote:
>>
>> On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com
>> wrote:
>>
>> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>>
>> With runtime PM enabled, we need to make sure that all HW access
>> are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
>> HW hangs. Ex. A hang is seen if display register is accessed on
>> BYT while display power island is power gated.
>>
>> This patch is covering all the IOCTLs with get/put.
>> TODO: limit runtime_get/put to IOCTLs that accesses HW
>>
>> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>>
>> Nack on the concept. We need to have get/put calls for the individual
>> functional blocks of the hw, which then in turn (if it's not the top-level
>> power domain) need to grab references to the next up power domain.
>> Splattering unconditional get/puts over all driver entry points is bad
>> style and imo also too fragile.
>>
>> Also, with Paulos final runtime pm/pc8 unification patches and Imre's
>> display power well patches for byt we should have full coverage already.
>> Have you looked at the work of these too?
>>
>> I'm still in debt with the BYT specific power domain patches, I want to
>> post them (this week) after I sorted out spurious pipe stat IRQs we'd
>> receive atm with the power well off. Until then there is only the WIP
>> version at: https://github.com/ideak/linux/commits/powerwells
>>
>> But in practice, as you point out the plan was to only call
>> modeset_update_power_wells() during modeset time and that will end up
>> doing the proper RPM get/put as necessary. Similarly on some other code
>> paths like connector detect and HW state read-out code, we'd ask only
>> for the needed power domains which would end up doing the RPM get/put.
>>
>> --Imre
>>
>> Hi Imre,
>> I tried to go through your and Paulo's patches
>> (http://patchwork.freedesktop.org/patch/16952/).
>> As per my understanding we are doing disp power well gate/ungate independent
>> of we are in
>> runtime_suspend/resume state we might face problem here as on BYT interrupts
>> are routed through
>> display power well, so we might have a situation where display power island
>> is power gated,
>> but render workload is still active. As we won't be receiving any interrupt
>> __wait_seq_no will
>> stall and we might end up in a TDR. We will not see the issue until display
>> power gating is
>> enabled. I will try to include a test to cover this test
>>
>> This can be avoided by adding display_get/put in runtime_resume/suspend.
>> I am not sure if this scenario will be applicable for HSW.
>>
>> Need for covering ioclts:
>> However there is one more problem for LP platforms. Once
>> display/render/media power
>> islands are power gated, system will enter into deeper sleep state causing
>> Gunit to power
>> gate. We will loose the state once Gunit resumes, so Gunit restore and ring
>> initialization is
>> required in runtime_resume. Even after adding these to
>> runtime_suspend/resume, we will have
>> to make sure all the ring activities, Gunit register accesses are covered
>> with runtime_get/put.
>> There are few places with current implementation where we might hit this
>> problem.
>> Example:
>> i915_batchbuffer(ioctl)->i915_batchbuffer (gpu commands scheduled)
>> i915_irq_emit(ioctl) -> i915_emit_irq (gpu commands scheduled)
>> i915_cmdbuffer (ioctl) -> i915_dispatch_cmdbuffer-> i915_emit_cmds(gpu
>> commands scheduled)
>> There are few more.
>> These ioclts not being covered with runtime_get/put will might cause invalid
>> executions
>> if we are resuming for deeper power state (gunit was powergated).
> If possible, please write pm_pc8.c subtests that reproduce all these
> problems you found :)
>
Above scenarios are only valid for non-KMS mode. I missed it, so looks like
we should be fine with the current implementation and your outstanding patches

>> solutions:
>>  From design perspective, we can cover all accesses at low level, but this
>> means a lot of get/put
>> and also will have to make sure that we cover future accesses as well. As an
>> other solution we
>> can cover these ioctls individually or can have a wrapper function (as
>> purposed in this patch)
>> to cover the accesses (TODO: make them conditional to do get/put on few
>> ioclts only).
>> I will try to upload refined patch with conditional get/put.
>>
>> Thanks,
>> Naresh
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>
>

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

* Re: [RFC 3/6] drm/i915: introduce runtime get/put based on display activity
  2014-01-22 13:40   ` Paulo Zanoni
@ 2014-02-24  5:21     ` Naresh Kumar Kachhi
  0 siblings, 0 replies; 23+ messages in thread
From: Naresh Kumar Kachhi @ 2014-02-24  5:21 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development

On 01/22/2014 07:10 PM, Paulo Zanoni wrote:
> Hi
>
> 2014/1/22  <naresh.kumar.kachhi@intel.com>:
>> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>>
>> Once the display is disabled, we need to call runtime_put to
>> make sure Runtime framework triggers runtime_suspend based on
>> idleness. Similarly when display gets enabled, runtime_get should
>> be called. We have similiar function for pc8 feature, but some
>> platform(BYT) might not have pc8 feature, so creating a generic
>> function for runtime_pm
> Does this patch series help you somehow?
> http://lists.freedesktop.org/archives/intel-gfx/2013-December/037721.html

Yes, this patch series helps here. Do we know when these patches will
bemerged to nightly build?

>> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>> ---
>>   drivers/gpu/drm/i915/i915_drv.h  |  2 ++
>>   drivers/gpu/drm/i915/intel_drv.h |  1 +
>>   drivers/gpu/drm/i915/intel_pm.c  | 50 ++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 53 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index d1399f9..6a6f046 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -1325,6 +1325,8 @@ struct i915_package_c8 {
>>   struct i915_runtime_pm {
>>          bool suspended;
>>          bool gpu_idle;
>> +       bool disp_idle;
>> +       struct mutex lock;
>>   };
>>
>>   enum intel_pipe_crc_source {
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 9061aa7..94a6127 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -887,6 +887,7 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
>>   void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
>>   void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv);
>>   void intel_runtime_pm_gpu_idle(struct drm_i915_private *dev_priv);
>> +void intel_runtime_update_disp_state(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 991ff62..9d6d0e1 100644
>> --- a/drivers/gpu/drm/i915/intel_pm.c
>> +++ b/drivers/gpu/drm/i915/intel_pm.c
>> @@ -5501,6 +5501,54 @@ void intel_runtime_pm_gpu_busy(struct drm_i915_private *dev_priv)
>>          }
>>   }
>>
>> +static void intel_runtime_pm_disp_idle(struct drm_i915_private *dev_priv)
>> +{
>> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
>> +               return;
>> +
>> +       mutex_lock(&dev_priv->pm.lock);
>> +       if (!dev_priv->pm.disp_idle) {
>> +               dev_priv->pm.disp_idle = true;
>> +               intel_runtime_pm_put(dev_priv);
>> +       }
>> +       mutex_unlock(&dev_priv->pm.lock);
>> +}
>> +
>> +static void intel_runtime_pm_disp_busy(struct drm_i915_private *dev_priv)
>> +{
>> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
>> +               return;
>> +
>> +       mutex_lock(&dev_priv->pm.lock);
>> +       if (dev_priv->pm.disp_idle) {
>> +               dev_priv->pm.disp_idle = false;
>> +               /* This call is coming from an IOCTL so we have already done a
>> +                * get_sync. get_noresume should suffice here
>> +                */
>> +               intel_runtime_pm_get_noresume(dev_priv);
>> +       }
>> +       mutex_unlock(&dev_priv->pm.lock);
>> +}
>> +
>> +void intel_runtime_update_disp_state(struct drm_i915_private *dev_priv)
>> +{
>> +       struct drm_device *dev = dev_priv->dev;
>> +       struct intel_crtc *crtc;
>> +       bool enabled = false;
>> +
>> +       if (!HAS_RUNTIME_PM(dev_priv->dev))
>> +               return;
>> +
>> +       list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
>> +               enabled |= crtc->base.enabled;
>> +
>> +       if (enabled)
>> +               intel_runtime_pm_disp_busy(dev_priv);
>> +       else
>> +               intel_runtime_pm_disp_idle(dev_priv);
>> +
>> +}
>> +
>>   void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
>>   {
>>          struct drm_device *dev = dev_priv->dev;
>> @@ -5547,6 +5595,8 @@ void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
>>
>>          dev_priv->pm.suspended = false;
>>          dev_priv->pm.gpu_idle = true;
>> +       dev_priv->pm.disp_idle = true;
>> +       mutex_init(&dev_priv->pm.lock);
>>
>>          if (!HAS_RUNTIME_PM(dev))
>>                  return;
>> --
>> 1.8.1.2
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>

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

* Re: [RFC 1/6] drm/i915: cover ioctls with runtime_get/put
  2014-02-21 20:07           ` Jesse Barnes
@ 2014-02-24  5:30             ` Naresh Kumar Kachhi
  0 siblings, 0 replies; 23+ messages in thread
From: Naresh Kumar Kachhi @ 2014-02-24  5:30 UTC (permalink / raw)
  To: Jesse Barnes, imre.deak; +Cc: intel-gfx, Satyanantha, Rama Gopal M

On 02/22/2014 01:37 AM, Jesse Barnes wrote:
> On Fri, 24 Jan 2014 19:23:54 +0200
> Imre Deak <imre.deak@intel.com> wrote:
>
>> On Fri, 2014-01-24 at 20:35 +0530, Naresh Kumar Kachhi wrote:
>>> On 01/22/2014 06:53 PM, Imre Deak wrote:
>>>
>>>> On Wed, 2014-01-22 at 13:51 +0100, Daniel Vetter wrote:
>>>>> On Wed, Jan 22, 2014 at 05:34:17PM +0530, naresh.kumar.kachhi@intel.com wrote:
>>>>>> From: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>>>>>>
>>>>>> With runtime PM enabled, we need to make sure that all HW access
>>>>>> are valid (i.e.  Gfx is in D0). Invalid accesses might end up in
>>>>>> HW hangs. Ex. A hang is seen if display register is accessed on
>>>>>> BYT while display power island is power gated.
>>>>>>
>>>>>> This patch is covering all the IOCTLs with get/put.
>>>>>> TODO: limit runtime_get/put to IOCTLs that accesses HW
>>>>>>
>>>>>> Signed-off-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com>
>>>>> Nack on the concept. We need to have get/put calls for the individual
>>>>> functional blocks of the hw, which then in turn (if it's not the top-level
>>>>> power domain) need to grab references to the next up power domain.
>>>>> Splattering unconditional get/puts over all driver entry points is bad
>>>>> style and imo also too fragile.
>>>>>
>>>>> Also, with Paulos final runtime pm/pc8 unification patches and Imre's
>>>>> display power well patches for byt we should have full coverage already.
>>>>> Have you looked at the work of these too?
>>>> I'm still in debt with the BYT specific power domain patches, I want to
>>>> post them (this week) after I sorted out spurious pipe stat IRQs we'd
>>>> receive atm with the power well off. Until then there is only the WIP
>>>> version at: https://github.com/ideak/linux/commits/powerwells
>>>>
>>>> But in practice, as you point out the plan was to only call
>>>> modeset_update_power_wells() during modeset time and that will end up
>>>> doing the proper RPM get/put as necessary. Similarly on some other code
>>>> paths like connector detect and HW state read-out code, we'd ask only
>>>> for the needed power domains which would end up doing the RPM get/put.
>>>>
>>>> --Imre
>>>>
>>> Hi Imre,
>>> I tried to go through your and Paulo's patches (http://patchwork.freedesktop.org/patch/16952/).
>>> As per my understanding we are doing disp power well gate/ungate independent of we are in
>>> runtime_suspend/resume state we might face problem here as on BYT interrupts are routed through
>>> display power well, so we might have a situation where display power island is power gated,
>>> but render workload is still active. As we won't be receiving any interrupt __wait_seq_no will
>>> stall and we might end up in a TDR. We will not see the issue until display power gating is
>>> enabled. I will try to include a test to cover this test
>> Hm, which exact interrupt routing are you referring to? At least on my
>> BYT I manage to power off only the display power well and keep the
>> render well on, while still being able to run for example
>> igt/tests/gem_render_copy, gem_render_linear_blits. I can see that
>> through /proc/interrupts that GT interrupts are properly generated. The
>> display side interrupt routing is of course off, for example the
>> PIPESTAT registers will read all 0xffffffff, but DEIIR, DEIMR, DEISR are
>> all seem to work ok.
> I think Naresh is referring to full D3 state shutdown, where the Gunit
> goes away too.  But in that case the GT will be shut down as well, so I
> don't think the display vs GT thing by itself is a problem.
>
Please ignore my previous comment as I confused interrupts being routed through display unit on VLV.
But this comment will be valid on some platforms like HSW, where render interrupts are routed
through display unit. So, display power gating in such platforms has to be done by taking
render/media also into consideration.
-Naresh

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

end of thread, other threads:[~2014-02-24  5:31 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-22 12:04 [RFC 0/6] enabling runtime on BYT naresh.kumar.kachhi
2014-01-22 12:04 ` [RFC 1/6] drm/i915: cover ioctls with runtime_get/put naresh.kumar.kachhi
2014-01-22 12:51   ` Daniel Vetter
2014-01-22 13:23     ` Imre Deak
2014-01-24 15:05       ` Naresh Kumar Kachhi
2014-01-24 15:56         ` Paulo Zanoni
2014-02-24  5:17           ` Naresh Kumar Kachhi
2014-01-24 17:23         ` Imre Deak
2014-02-21 20:07           ` Jesse Barnes
2014-02-24  5:30             ` Naresh Kumar Kachhi
2014-01-22 13:35   ` Paulo Zanoni
2014-01-22 12:04 ` [RFC 2/6] drm/i915: cover ring access with rpm get/put naresh.kumar.kachhi
2014-01-22 13:39   ` Paulo Zanoni
2014-01-22 12:04 ` [RFC 3/6] drm/i915: introduce runtime get/put based on display activity naresh.kumar.kachhi
2014-01-22 13:40   ` Paulo Zanoni
2014-02-24  5:21     ` Naresh Kumar Kachhi
2014-01-22 12:04 ` [RFC 4/6] drm/i915/vlv: call runtime get/put based on disp activity naresh.kumar.kachhi
2014-01-22 12:04 ` [RFC 5/6] drm/i915: device specific runtime suspend/resume naresh.kumar.kachhi
2014-01-22 12:58   ` Daniel Vetter
2014-01-24 15:23     ` Naresh Kumar Kachhi
2014-01-22 12:04 ` [RFC 6/6] FOR_UPSTREAM [VPG]: drm/i915: call init_runtime_pm before gem_init naresh.kumar.kachhi
2014-01-22 13:44   ` Paulo Zanoni
2014-01-24 15:11     ` Naresh Kumar Kachhi

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.