Re: [Intel-gfx] [PATCH 1/2] drm/i915: make CRTC enable/disable asynchronous v2

2014-05-30 Thread Jesse Barnes
On Fri, 30 May 2014 19:56:22 +0100
Chris Wilson  wrote:

> On Fri, May 30, 2014 at 11:05:21AM -0700, Jesse Barnes wrote:
> > +static void intel_queue_crtc_enable(struct drm_crtc *crtc)
> > +{
> > +   struct drm_device *dev = crtc->dev;
> > +   struct drm_i915_private *dev_priv = dev->dev_private;
> > +   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > +   struct intel_crtc_work *work;
> > +
> > +   WARN(!mutex_is_locked(&dev->mode_config.mutex),
> > +"need mode_config mutex\n");
> > +
> > +   work = kmalloc(sizeof(*work), GFP_KERNEL);
> > +   if (!work) {
> > +   dev_priv->display._crtc_disable(&intel_crtc->base);
> > +   return;
> > +   }
> > +
> > +   work->enable = true;
> > +   work->intel_crtc = intel_crtc;
> > +   INIT_LIST_HEAD(&work->head);
> (redundant, list_add doesn't care)

Will fix.

> > +
> > +   list_add_tail(&dev_priv->crtc_work_queue, &work->head);
> > +   schedule_work(&dev_priv->crtc_work);
> > +}
> 
> If we tracked one queued item per crtc, we could avoid the allocation
> and allow for elision of pending operations.

Yeah I thought about that too, might make for a good optimization, but
I figured this was simplest to start with.

-- 
Jesse Barnes, Intel Open Source Technology Center
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/2] drm/i915: make CRTC enable/disable asynchronous v2

2014-05-30 Thread Chris Wilson
On Fri, May 30, 2014 at 11:05:21AM -0700, Jesse Barnes wrote:
> +static void intel_queue_crtc_enable(struct drm_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + struct intel_crtc_work *work;
> +
> + WARN(!mutex_is_locked(&dev->mode_config.mutex),
> +  "need mode_config mutex\n");
> +
> + work = kmalloc(sizeof(*work), GFP_KERNEL);
> + if (!work) {
> + dev_priv->display._crtc_disable(&intel_crtc->base);
> + return;
> + }
> +
> + work->enable = true;
> + work->intel_crtc = intel_crtc;
> + INIT_LIST_HEAD(&work->head);
(redundant, list_add doesn't care)

> +
> + list_add_tail(&dev_priv->crtc_work_queue, &work->head);
> + schedule_work(&dev_priv->crtc_work);
> +}

If we tracked one queued item per crtc, we could avoid the allocation
and allow for elision of pending operations.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/2] drm/i915: make CRTC enable/disable asynchronous v2

2014-05-30 Thread Chris Wilson
On Fri, May 30, 2014 at 11:05:21AM -0700, Jesse Barnes wrote:
> @@ -8166,6 +8296,8 @@ static int intel_crtc_cursor_move(struct drm_crtc 
> *crtc, int x, int y)
>   intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX);
>   intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX);
>  
> + intel_sync_crtcs(crtc->dev->dev_private);
> +
>   if (intel_crtc->active)
>   intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
>  

Since the pending CRTC enable/disable will set the cursor anyway, this
sync could be avoided if intel_crtc->active was accurate.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/2] drm/i915: make CRTC enable/disable asynchronous v2

2014-05-30 Thread Jesse Barnes
On Fri, 30 May 2014 19:47:56 +0100
Chris Wilson  wrote:

> On Fri, May 30, 2014 at 11:05:21AM -0700, Jesse Barnes wrote:
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c 
> > b/drivers/gpu/drm/i915/i915_drv.c
> > index e2bfdda..e7fa84f 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -530,7 +530,7 @@ static int i915_drm_freeze(struct drm_device *dev)
> > mutex_lock(&dev->mode_config.mutex);
> > for_each_crtc(dev, crtc) {
> > mutex_lock(&crtc->mutex);
> > -   dev_priv->display.crtc_disable(crtc);
> > +   dev_priv->display._crtc_disable(crtc);
> 
> Don't you want to cancel the pending work here or it will be run on
> resume - but on resume, we just want to send the hotplug event and let
> userspace set itself up in the new configuration.

No you're right I need to cancel it here and in unload, thanks.

-- 
Jesse Barnes, Intel Open Source Technology Center
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/2] drm/i915: make CRTC enable/disable asynchronous v2

2014-05-30 Thread Chris Wilson
On Fri, May 30, 2014 at 11:05:21AM -0700, Jesse Barnes wrote:
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index e2bfdda..e7fa84f 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -530,7 +530,7 @@ static int i915_drm_freeze(struct drm_device *dev)
>   mutex_lock(&dev->mode_config.mutex);
>   for_each_crtc(dev, crtc) {
>   mutex_lock(&crtc->mutex);
> - dev_priv->display.crtc_disable(crtc);
> + dev_priv->display._crtc_disable(crtc);

Don't you want to cancel the pending work here or it will be run on
resume - but on resume, we just want to send the hotplug event and let
userspace set itself up in the new configuration.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 1/2] drm/i915: make CRTC enable/disable asynchronous v2

2014-05-30 Thread Jesse Barnes
This lets us return to userspace more quickly and should improve init
and suspend/resume times as well, allowing us to return to userspace
sooner.

This was initially motivated by slow resume time on some machines with
very long panel power sequencing times, and it should also improve boot
time when a full mode set is required.

v2: use a single enable/disable queue (Jesse/Chris)
fixup locking, test with lockdep (Jesse)
move hw state checks to sync_crtcs (Jesse)
make userspace initiated mode sets stay synchronous (Chris)

Signed-off-by: Jesse Barnes 
---
 drivers/gpu/drm/i915/i915_drv.c  |   2 +-
 drivers/gpu/drm/i915/i915_drv.h  |  12 ++-
 drivers/gpu/drm/i915/intel_display.c | 170 +++
 drivers/gpu/drm/i915/intel_drv.h |   2 +-
 4 files changed, 165 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e2bfdda..e7fa84f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -530,7 +530,7 @@ static int i915_drm_freeze(struct drm_device *dev)
mutex_lock(&dev->mode_config.mutex);
for_each_crtc(dev, crtc) {
mutex_lock(&crtc->mutex);
-   dev_priv->display.crtc_disable(crtc);
+   dev_priv->display._crtc_disable(crtc);
mutex_unlock(&crtc->mutex);
}
mutex_unlock(&dev->mode_config.mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bea9ab40..bbfe402 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -447,8 +447,8 @@ struct drm_i915_display_funcs {
int (*crtc_mode_set)(struct drm_crtc *crtc,
 int x, int y,
 struct drm_framebuffer *old_fb);
-   void (*crtc_enable)(struct drm_crtc *crtc);
-   void (*crtc_disable)(struct drm_crtc *crtc);
+   void (*_crtc_enable)(struct drm_crtc *crtc);
+   void (*_crtc_disable)(struct drm_crtc *crtc);
void (*off)(struct drm_crtc *crtc);
void (*write_eld)(struct drm_connector *connector,
  struct drm_crtc *crtc,
@@ -1432,6 +1432,14 @@ struct drm_i915_private {
/* Display functions */
struct drm_i915_display_funcs display;
 
+   /**
+* CRTC work queue handling.  Enable/disable calls are queued
+* into the list and processed by the CRTC work function at some
+* later time, or inline by a call to intel_sync_crtcs().
+*/
+   struct list_head crtc_work_queue;
+   struct work_struct crtc_work;
+
/* PCH chipset type */
enum intel_pch pch_type;
unsigned short pch_id;
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 731cd01..8c52038 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1973,6 +1973,135 @@ static void lpt_disable_pch_transcoder(struct 
drm_i915_private *dev_priv)
I915_WRITE(_TRANSA_CHICKEN2, val);
 }
 
+struct intel_crtc_work {
+   /**
+* Whether to enable or disable the given CRTC
+*/
+   bool enable;
+   /**
+* CRTC to operate on
+*/
+   struct intel_crtc *intel_crtc;
+   /**
+* Used to link to dev_priv->crtc_work_queue, protected
+* by mode_config mutex.
+*/
+   struct list_head head;
+};
+
+/**
+ * intel_sync_crtcs - complete any pending CRTC enable/disable calls
+ * @dev_priv: i915 driver struct
+ *
+ * Walk the CRTC work queue and perform the enable/disable calls in the
+ * order they were added.
+ *
+ * This function will return when the enable/disable calls have been completed,
+ * and so may take many milliseconds before returning.
+ */
+static void intel_sync_crtcs(struct drm_i915_private *dev_priv)
+{
+   struct drm_device *dev = dev_priv->dev;
+   struct intel_crtc_work *crtc_work, *tmp;
+
+   WARN(!mutex_is_locked(&dev->mode_config.mutex),
+"need mode_config mutex\n");
+
+   list_for_each_entry_safe(crtc_work, tmp, &dev_priv->crtc_work_queue,
+head) {
+   struct drm_crtc *crtc = &crtc_work->intel_crtc->base;
+
+   if (crtc_work->enable)
+   dev_priv->display._crtc_enable(crtc);
+   else
+   dev_priv->display._crtc_disable(crtc);
+   list_del(&crtc_work->head);
+   kfree(crtc_work);
+   }
+
+   intel_modeset_check_state(dev);
+}
+
+/**
+ * intel_crtc_work - CRTC queue processing function
+ * @work: crtc_work struct from drm_i915_private
+ *
+ * Just calls intel_sync_crtcs() to take the lock and process the list if any
+ * entries are present.
+ */
+static void intel_crtc_work(struct work_struct *work)
+{
+   struct drm_i915_private *dev_priv =
+