Re: [Intel-gfx] [PATCH v3] drm/i915/dsb: Pre allocate and late cleanup of cmd buffer
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
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
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