Re: [Intel-gfx] [PATCH v3] drm/i915/dsb: Pre allocate and late cleanup of cmd buffer

2020-04-02 Thread Maarten Lankhorst
Hey,

Op 12-02-2020 om 15:45 schreef Animesh Manna:
> Pre-allocate command buffer in atomic_commit using intel_dsb_prepare
> function which also includes pinning and map in cpu domain.
>
> No change is dsb write/commit functions.
>
> Now dsb get/put function is refactored and currently used only for
> reference counting. Below dsb api added to do respective job
> mentioned below.
>
> intel_dsb_prepare - Allocate, pin and map the buffer.
> intel_dsb_cleanup - Unpin and release the gem object.
>
> RFC: Initial patch for design review.
> v2: included _init() part in _prepare(). [Daniel, Ville]
> v3: dsb_cleanup called after cleanup_planes. [Daniel]
>
> Cc: Ville Syrjälä 
> Cc: Jani Nikula 
> Cc: Daniel Vetter 
> Signed-off-by: Animesh Manna 
> ---
>  drivers/gpu/drm/i915/display/intel_display.c |  36 -
>  drivers/gpu/drm/i915/display/intel_dsb.c | 132 ---
>  drivers/gpu/drm/i915/display/intel_dsb.h |   2 +
>  3 files changed, 116 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 61ba1f2256a0..ae90687e3a6b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -15076,6 +15076,19 @@ static int intel_atomic_check(struct drm_device *dev,
>  
>  static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
>  {
> + struct intel_crtc_state *crtc_state;
> + struct intel_crtc *crtc;
> + int i;
> +
> + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> + bool mode_changed = needs_modeset(crtc_state);
> +
> + if (mode_changed || crtc_state->update_pipe ||
> + crtc_state->uapi.color_mgmt_changed) {
> + intel_dsb_prepare(crtc);
> + }
> + }
> +
>   return drm_atomic_helper_prepare_planes(state->base.dev,
>   >base);
>  }

DSB should be moved to crtc_state, as we may otherwise race between concurrent 
dsb_prepare() and dsb_cleanup().

Additionally, there should probably be some error handling like this:


int err = drm_atomic_helper_prepare_planes(state->base.dev, >base);

if (err) return err;

err = intel_dsb_prepare();

if (err)

intel_dsb_cleanup(previous); and drm_atomic_helper_cleanup_planes();

return err;


Otherwise looks good. :)



> @@ -15643,15 +15656,26 @@ static void intel_atomic_commit_fence_wait(struct 
> intel_atomic_state *intel_stat
>   _reset);
>  }
>  
> +static void intel_cleanup_dsbs(struct intel_atomic_state *state)
> +{
> + struct intel_crtc_state *crtc_state;
> + struct intel_crtc *crtc;
> + int i;
> +
> + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i)
> + intel_dsb_cleanup(crtc);
> +}
> +
>  static void intel_atomic_cleanup_work(struct work_struct *work)
>  {
> - struct drm_atomic_state *state =
> - container_of(work, struct drm_atomic_state, commit_work);
> - struct drm_i915_private *i915 = to_i915(state->dev);
> + struct intel_atomic_state *state =
> + container_of(work, struct intel_atomic_state, base.commit_work);
> + struct drm_i915_private *i915 = to_i915(state->base.dev);
>  
> - drm_atomic_helper_cleanup_planes(>drm, state);
> - drm_atomic_helper_commit_cleanup_done(state);
> - drm_atomic_state_put(state);
> + drm_atomic_helper_cleanup_planes(>drm, >base);
> + intel_cleanup_dsbs(state);
> + drm_atomic_helper_commit_cleanup_done(>base);
> + drm_atomic_state_put(>base);
>  
>   intel_atomic_helper_free_state(i915);
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
> b/drivers/gpu/drm/i915/display/intel_dsb.c
> index 76ae01277fd6..c31132c41e0f 100644
> --- a/drivers/gpu/drm/i915/display/intel_dsb.c
> +++ b/drivers/gpu/drm/i915/display/intel_dsb.c
> @@ -34,6 +34,86 @@
>  #define DSB_BYTE_EN_SHIFT20
>  #define DSB_REG_VALUE_MASK   0xf
>  
> +/**
> + * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer.
> + * @crtc: intel_crtc structure to get pipe info.
> + *
> + * This function prepare the command buffer which is used to store dsb
> + * instructions with data.
> + */
> +
> +void intel_dsb_prepare(struct intel_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *i915 = to_i915(dev);
> + struct intel_dsb *dsb = >dsb;
> + struct drm_i915_gem_object *obj;
> + struct i915_vma *vma;
> + u32 *buf;
> + intel_wakeref_t wakeref;
> +
> + if (!HAS_DSB(i915) || dsb->cmd_buf)
> + return;
> +
> + wakeref = intel_runtime_pm_get(>runtime_pm);
> +
> + obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
> + if (IS_ERR(obj)) {
> + DRM_ERROR("Gem object creation failed\n");
> + goto out;
> + }
> +
> + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);

Re: [Intel-gfx] [PATCH v3] drm/i915/dsb: Pre allocate and late cleanup of cmd buffer

2020-03-05 Thread Daniel Vetter
On Wed, Feb 12, 2020 at 08:15:22PM +0530, Animesh Manna wrote:
> Pre-allocate command buffer in atomic_commit using intel_dsb_prepare
> function which also includes pinning and map in cpu domain.
> 
> No change is dsb write/commit functions.
> 
> Now dsb get/put function is refactored and currently used only for
> reference counting. Below dsb api added to do respective job
> mentioned below.
> 
> intel_dsb_prepare - Allocate, pin and map the buffer.
> intel_dsb_cleanup - Unpin and release the gem object.
> 
> RFC: Initial patch for design review.
> v2: included _init() part in _prepare(). [Daniel, Ville]
> v3: dsb_cleanup called after cleanup_planes. [Daniel]
> 
> Cc: Ville Syrjälä 
> Cc: Jani Nikula 
> Cc: Daniel Vetter 
> Signed-off-by: Animesh Manna 

I think this should fit a lot better wrt the dma_resv locking rework
that's ongoing.

Acked-by: Daniel Vetter 

Cheers, Daniel

> ---
>  drivers/gpu/drm/i915/display/intel_display.c |  36 -
>  drivers/gpu/drm/i915/display/intel_dsb.c | 132 ---
>  drivers/gpu/drm/i915/display/intel_dsb.h |   2 +
>  3 files changed, 116 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 61ba1f2256a0..ae90687e3a6b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -15076,6 +15076,19 @@ static int intel_atomic_check(struct drm_device *dev,
>  
>  static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
>  {
> + struct intel_crtc_state *crtc_state;
> + struct intel_crtc *crtc;
> + int i;
> +
> + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
> + bool mode_changed = needs_modeset(crtc_state);
> +
> + if (mode_changed || crtc_state->update_pipe ||
> + crtc_state->uapi.color_mgmt_changed) {
> + intel_dsb_prepare(crtc);
> + }
> + }
> +
>   return drm_atomic_helper_prepare_planes(state->base.dev,
>   >base);
>  }
> @@ -15643,15 +15656,26 @@ static void intel_atomic_commit_fence_wait(struct 
> intel_atomic_state *intel_stat
>   _reset);
>  }
>  
> +static void intel_cleanup_dsbs(struct intel_atomic_state *state)
> +{
> + struct intel_crtc_state *crtc_state;
> + struct intel_crtc *crtc;
> + int i;
> +
> + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i)
> + intel_dsb_cleanup(crtc);
> +}
> +
>  static void intel_atomic_cleanup_work(struct work_struct *work)
>  {
> - struct drm_atomic_state *state =
> - container_of(work, struct drm_atomic_state, commit_work);
> - struct drm_i915_private *i915 = to_i915(state->dev);
> + struct intel_atomic_state *state =
> + container_of(work, struct intel_atomic_state, base.commit_work);
> + struct drm_i915_private *i915 = to_i915(state->base.dev);
>  
> - drm_atomic_helper_cleanup_planes(>drm, state);
> - drm_atomic_helper_commit_cleanup_done(state);
> - drm_atomic_state_put(state);
> + drm_atomic_helper_cleanup_planes(>drm, >base);
> + intel_cleanup_dsbs(state);
> + drm_atomic_helper_commit_cleanup_done(>base);
> + drm_atomic_state_put(>base);
>  
>   intel_atomic_helper_free_state(i915);
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
> b/drivers/gpu/drm/i915/display/intel_dsb.c
> index 76ae01277fd6..c31132c41e0f 100644
> --- a/drivers/gpu/drm/i915/display/intel_dsb.c
> +++ b/drivers/gpu/drm/i915/display/intel_dsb.c
> @@ -34,6 +34,86 @@
>  #define DSB_BYTE_EN_SHIFT20
>  #define DSB_REG_VALUE_MASK   0xf
>  
> +/**
> + * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer.
> + * @crtc: intel_crtc structure to get pipe info.
> + *
> + * This function prepare the command buffer which is used to store dsb
> + * instructions with data.
> + */
> +
> +void intel_dsb_prepare(struct intel_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *i915 = to_i915(dev);
> + struct intel_dsb *dsb = >dsb;
> + struct drm_i915_gem_object *obj;
> + struct i915_vma *vma;
> + u32 *buf;
> + intel_wakeref_t wakeref;
> +
> + if (!HAS_DSB(i915) || dsb->cmd_buf)
> + return;
> +
> + wakeref = intel_runtime_pm_get(>runtime_pm);
> +
> + obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
> + if (IS_ERR(obj)) {
> + DRM_ERROR("Gem object creation failed\n");
> + goto out;
> + }
> +
> + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
> + if (IS_ERR(vma)) {
> + DRM_ERROR("Vma creation failed\n");
> + i915_gem_object_put(obj);
> + goto out;
> + }
> +
> + buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
> + if (IS_ERR(buf)) {
> + 

[Intel-gfx] [PATCH v3] drm/i915/dsb: Pre allocate and late cleanup of cmd buffer

2020-02-12 Thread Animesh Manna
Pre-allocate command buffer in atomic_commit using intel_dsb_prepare
function which also includes pinning and map in cpu domain.

No change is dsb write/commit functions.

Now dsb get/put function is refactored and currently used only for
reference counting. Below dsb api added to do respective job
mentioned below.

intel_dsb_prepare - Allocate, pin and map the buffer.
intel_dsb_cleanup - Unpin and release the gem object.

RFC: Initial patch for design review.
v2: included _init() part in _prepare(). [Daniel, Ville]
v3: dsb_cleanup called after cleanup_planes. [Daniel]

Cc: Ville Syrjälä 
Cc: Jani Nikula 
Cc: Daniel Vetter 
Signed-off-by: Animesh Manna 
---
 drivers/gpu/drm/i915/display/intel_display.c |  36 -
 drivers/gpu/drm/i915/display/intel_dsb.c | 132 ---
 drivers/gpu/drm/i915/display/intel_dsb.h |   2 +
 3 files changed, 116 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 61ba1f2256a0..ae90687e3a6b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -15076,6 +15076,19 @@ static int intel_atomic_check(struct drm_device *dev,
 
 static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
 {
+   struct intel_crtc_state *crtc_state;
+   struct intel_crtc *crtc;
+   int i;
+
+   for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
+   bool mode_changed = needs_modeset(crtc_state);
+
+   if (mode_changed || crtc_state->update_pipe ||
+   crtc_state->uapi.color_mgmt_changed) {
+   intel_dsb_prepare(crtc);
+   }
+   }
+
return drm_atomic_helper_prepare_planes(state->base.dev,
>base);
 }
@@ -15643,15 +15656,26 @@ static void intel_atomic_commit_fence_wait(struct 
intel_atomic_state *intel_stat
_reset);
 }
 
+static void intel_cleanup_dsbs(struct intel_atomic_state *state)
+{
+   struct intel_crtc_state *crtc_state;
+   struct intel_crtc *crtc;
+   int i;
+
+   for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i)
+   intel_dsb_cleanup(crtc);
+}
+
 static void intel_atomic_cleanup_work(struct work_struct *work)
 {
-   struct drm_atomic_state *state =
-   container_of(work, struct drm_atomic_state, commit_work);
-   struct drm_i915_private *i915 = to_i915(state->dev);
+   struct intel_atomic_state *state =
+   container_of(work, struct intel_atomic_state, base.commit_work);
+   struct drm_i915_private *i915 = to_i915(state->base.dev);
 
-   drm_atomic_helper_cleanup_planes(>drm, state);
-   drm_atomic_helper_commit_cleanup_done(state);
-   drm_atomic_state_put(state);
+   drm_atomic_helper_cleanup_planes(>drm, >base);
+   intel_cleanup_dsbs(state);
+   drm_atomic_helper_commit_cleanup_done(>base);
+   drm_atomic_state_put(>base);
 
intel_atomic_helper_free_state(i915);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c 
b/drivers/gpu/drm/i915/display/intel_dsb.c
index 76ae01277fd6..c31132c41e0f 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -34,6 +34,86 @@
 #define DSB_BYTE_EN_SHIFT  20
 #define DSB_REG_VALUE_MASK 0xf
 
+/**
+ * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer.
+ * @crtc: intel_crtc structure to get pipe info.
+ *
+ * This function prepare the command buffer which is used to store dsb
+ * instructions with data.
+ */
+
+void intel_dsb_prepare(struct intel_crtc *crtc)
+{
+   struct drm_device *dev = crtc->base.dev;
+   struct drm_i915_private *i915 = to_i915(dev);
+   struct intel_dsb *dsb = >dsb;
+   struct drm_i915_gem_object *obj;
+   struct i915_vma *vma;
+   u32 *buf;
+   intel_wakeref_t wakeref;
+
+   if (!HAS_DSB(i915) || dsb->cmd_buf)
+   return;
+
+   wakeref = intel_runtime_pm_get(>runtime_pm);
+
+   obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
+   if (IS_ERR(obj)) {
+   DRM_ERROR("Gem object creation failed\n");
+   goto out;
+   }
+
+   vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
+   if (IS_ERR(vma)) {
+   DRM_ERROR("Vma creation failed\n");
+   i915_gem_object_put(obj);
+   goto out;
+   }
+
+   buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
+   if (IS_ERR(buf)) {
+   DRM_ERROR("Command buffer creation failed\n");
+   goto out;
+   }
+
+   dsb->id = DSB1;
+   dsb->vma = vma;
+   dsb->cmd_buf = buf;
+
+out:
+   /*
+* On error dsb->cmd_buf will continue to be NULL, making the writes
+* pass-through. Leave the dangling ref to be removed later by the
+* corresponding