diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_frontbuffer.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_frontbuffer.c | 212 |
1 files changed, 70 insertions, 142 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 17a7aa8b28c2..03c4978fa5ec 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -55,7 +55,10 @@ * cancelled as soon as busyness is detected. */ -#include "i915_drv.h" +#include <drm/drm_gem.h> +#include <drm/drm_print.h> + +#include "intel_bo.h" #include "intel_display_trace.h" #include "intel_display_types.h" #include "intel_dp.h" @@ -63,10 +66,11 @@ #include "intel_fbc.h" #include "intel_frontbuffer.h" #include "intel_psr.h" +#include "intel_tdf.h" /** * frontbuffer_flush - flush frontbuffer - * @i915: i915 device + * @display: display device * @frontbuffer_bits: frontbuffer plane tracking bits * @origin: which operation caused the flush * @@ -76,74 +80,30 @@ * * Can be called without any locks held. */ -static void frontbuffer_flush(struct drm_i915_private *i915, +static void frontbuffer_flush(struct intel_display *display, unsigned int frontbuffer_bits, enum fb_op_origin origin) { /* Delay flushing when rings are still busy.*/ - spin_lock(&i915->display.fb_tracking.lock); - frontbuffer_bits &= ~i915->display.fb_tracking.busy_bits; - spin_unlock(&i915->display.fb_tracking.lock); + spin_lock(&display->fb_tracking.lock); + frontbuffer_bits &= ~display->fb_tracking.busy_bits; + spin_unlock(&display->fb_tracking.lock); if (!frontbuffer_bits) return; - trace_intel_frontbuffer_flush(i915, frontbuffer_bits, origin); + trace_intel_frontbuffer_flush(display, frontbuffer_bits, origin); might_sleep(); - intel_drrs_flush(i915, frontbuffer_bits); - intel_psr_flush(i915, frontbuffer_bits, origin); - intel_fbc_flush(i915, frontbuffer_bits, origin); -} - -/** - * intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip - * @i915: i915 device - * @frontbuffer_bits: frontbuffer plane tracking bits - * - * This function gets called after scheduling a flip on @obj. The actual - * frontbuffer flushing will be delayed until completion is signalled with - * intel_frontbuffer_flip_complete. If an invalidate happens in between this - * flush will be cancelled. - * - * Can be called without any locks held. - */ -void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915, - unsigned frontbuffer_bits) -{ - spin_lock(&i915->display.fb_tracking.lock); - i915->display.fb_tracking.flip_bits |= frontbuffer_bits; - /* Remove stale busy bits due to the old buffer. */ - i915->display.fb_tracking.busy_bits &= ~frontbuffer_bits; - spin_unlock(&i915->display.fb_tracking.lock); -} - -/** - * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip - * @i915: i915 device - * @frontbuffer_bits: frontbuffer plane tracking bits - * - * This function gets called after the flip has been latched and will complete - * on the next vblank. It will execute the flush if it hasn't been cancelled yet. - * - * Can be called without any locks held. - */ -void intel_frontbuffer_flip_complete(struct drm_i915_private *i915, - unsigned frontbuffer_bits) -{ - spin_lock(&i915->display.fb_tracking.lock); - /* Mask any cancelled flips. */ - frontbuffer_bits &= i915->display.fb_tracking.flip_bits; - i915->display.fb_tracking.flip_bits &= ~frontbuffer_bits; - spin_unlock(&i915->display.fb_tracking.lock); - - if (frontbuffer_bits) - frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP); + intel_td_flush(display); + intel_drrs_flush(display, frontbuffer_bits); + intel_psr_flush(display, frontbuffer_bits, origin); + intel_fbc_flush(display, frontbuffer_bits, origin); } /** * intel_frontbuffer_flip - synchronous frontbuffer flip - * @i915: i915 device + * @display: display device * @frontbuffer_bits: frontbuffer plane tracking bits * * This function gets called after scheduling a flip on @obj. This is for @@ -152,141 +112,109 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915, * * Can be called without any locks held. */ -void intel_frontbuffer_flip(struct drm_i915_private *i915, +void intel_frontbuffer_flip(struct intel_display *display, unsigned frontbuffer_bits) { - spin_lock(&i915->display.fb_tracking.lock); + spin_lock(&display->fb_tracking.lock); /* Remove stale busy bits due to the old buffer. */ - i915->display.fb_tracking.busy_bits &= ~frontbuffer_bits; - spin_unlock(&i915->display.fb_tracking.lock); + display->fb_tracking.busy_bits &= ~frontbuffer_bits; + spin_unlock(&display->fb_tracking.lock); - frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP); + frontbuffer_flush(display, frontbuffer_bits, ORIGIN_FLIP); } void __intel_fb_invalidate(struct intel_frontbuffer *front, enum fb_op_origin origin, unsigned int frontbuffer_bits) { - struct drm_i915_private *i915 = to_i915(front->obj->base.dev); + struct intel_display *display = front->display; if (origin == ORIGIN_CS) { - spin_lock(&i915->display.fb_tracking.lock); - i915->display.fb_tracking.busy_bits |= frontbuffer_bits; - i915->display.fb_tracking.flip_bits &= ~frontbuffer_bits; - spin_unlock(&i915->display.fb_tracking.lock); + spin_lock(&display->fb_tracking.lock); + display->fb_tracking.busy_bits |= frontbuffer_bits; + spin_unlock(&display->fb_tracking.lock); } - trace_intel_frontbuffer_invalidate(i915, frontbuffer_bits, origin); + trace_intel_frontbuffer_invalidate(display, frontbuffer_bits, origin); might_sleep(); - intel_psr_invalidate(i915, frontbuffer_bits, origin); - intel_drrs_invalidate(i915, frontbuffer_bits); - intel_fbc_invalidate(i915, frontbuffer_bits, origin); + intel_psr_invalidate(display, frontbuffer_bits, origin); + intel_drrs_invalidate(display, frontbuffer_bits); + intel_fbc_invalidate(display, frontbuffer_bits, origin); } void __intel_fb_flush(struct intel_frontbuffer *front, enum fb_op_origin origin, unsigned int frontbuffer_bits) { - struct drm_i915_private *i915 = to_i915(front->obj->base.dev); + struct intel_display *display = front->display; + + if (origin == ORIGIN_DIRTYFB) + intel_bo_frontbuffer_flush_for_display(front); if (origin == ORIGIN_CS) { - spin_lock(&i915->display.fb_tracking.lock); + spin_lock(&display->fb_tracking.lock); /* Filter out new bits since rendering started. */ - frontbuffer_bits &= i915->display.fb_tracking.busy_bits; - i915->display.fb_tracking.busy_bits &= ~frontbuffer_bits; - spin_unlock(&i915->display.fb_tracking.lock); + frontbuffer_bits &= display->fb_tracking.busy_bits; + display->fb_tracking.busy_bits &= ~frontbuffer_bits; + spin_unlock(&display->fb_tracking.lock); } if (frontbuffer_bits) - frontbuffer_flush(i915, frontbuffer_bits, origin); + frontbuffer_flush(display, frontbuffer_bits, origin); } -static int frontbuffer_active(struct i915_active *ref) +static void intel_frontbuffer_ref(struct intel_frontbuffer *front) { - struct intel_frontbuffer *front = - container_of(ref, typeof(*front), write); - - kref_get(&front->ref); - return 0; + intel_bo_frontbuffer_ref(front); } -static void frontbuffer_retire(struct i915_active *ref) +static void intel_frontbuffer_flush_work(struct work_struct *work) { struct intel_frontbuffer *front = - container_of(ref, typeof(*front), write); + container_of(work, struct intel_frontbuffer, flush_work); - intel_frontbuffer_flush(front, ORIGIN_CS); + intel_frontbuffer_flush(front, ORIGIN_DIRTYFB); intel_frontbuffer_put(front); } -static void frontbuffer_release(struct kref *ref) - __releases(&to_i915(front->obj->base.dev)->display.fb_tracking.lock) +/** + * intel_frontbuffer_queue_flush - queue flushing frontbuffer object + * @front: GEM object to flush + * + * This function is targeted for our dirty callback for queueing flush when + * dma fence is signals + */ +void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front) { - struct intel_frontbuffer *front = - container_of(ref, typeof(*front), ref); - struct drm_i915_gem_object *obj = front->obj; - struct i915_vma *vma; - - drm_WARN_ON(obj->base.dev, atomic_read(&front->bits)); - - spin_lock(&obj->vma.lock); - for_each_ggtt_vma(vma, obj) { - i915_vma_clear_scanout(vma); - vma->display_alignment = I915_GTT_MIN_ALIGNMENT; - } - spin_unlock(&obj->vma.lock); - - RCU_INIT_POINTER(obj->frontbuffer, NULL); - spin_unlock(&to_i915(obj->base.dev)->display.fb_tracking.lock); - - i915_active_fini(&front->write); + if (!front) + return; - i915_gem_object_put(obj); - kfree_rcu(front, rcu); + intel_frontbuffer_ref(front); + if (!schedule_work(&front->flush_work)) + intel_frontbuffer_put(front); } -struct intel_frontbuffer * -intel_frontbuffer_get(struct drm_i915_gem_object *obj) +void intel_frontbuffer_init(struct intel_frontbuffer *front, struct drm_device *drm) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct intel_frontbuffer *front; - - front = __intel_frontbuffer_get(obj); - if (front) - return front; - - front = kmalloc(sizeof(*front), GFP_KERNEL); - if (!front) - return NULL; - - front->obj = obj; - kref_init(&front->ref); + front->display = to_intel_display(drm); atomic_set(&front->bits, 0); - i915_active_init(&front->write, - frontbuffer_active, - frontbuffer_retire, - I915_ACTIVE_RETIRE_SLEEPS); + INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work); +} - spin_lock(&i915->display.fb_tracking.lock); - if (rcu_access_pointer(obj->frontbuffer)) { - kfree(front); - front = rcu_dereference_protected(obj->frontbuffer, true); - kref_get(&front->ref); - } else { - i915_gem_object_get(obj); - rcu_assign_pointer(obj->frontbuffer, front); - } - spin_unlock(&i915->display.fb_tracking.lock); +void intel_frontbuffer_fini(struct intel_frontbuffer *front) +{ + drm_WARN_ON(front->display->drm, atomic_read(&front->bits)); +} - return front; +struct intel_frontbuffer *intel_frontbuffer_get(struct drm_gem_object *obj) +{ + return intel_bo_frontbuffer_get(obj); } void intel_frontbuffer_put(struct intel_frontbuffer *front) { - kref_put_lock(&front->ref, - frontbuffer_release, - &to_i915(front->obj->base.dev)->display.fb_tracking.lock); + intel_bo_frontbuffer_put(front); } /** @@ -315,13 +243,13 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old, BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE); if (old) { - drm_WARN_ON(old->obj->base.dev, + drm_WARN_ON(old->display->drm, !(atomic_read(&old->bits) & frontbuffer_bits)); atomic_andnot(frontbuffer_bits, &old->bits); } if (new) { - drm_WARN_ON(new->obj->base.dev, + drm_WARN_ON(new->display->drm, atomic_read(&new->bits) & frontbuffer_bits); atomic_or(frontbuffer_bits, &new->bits); } |
