From patchwork Tue Apr 19 07:52:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maarten Lankhorst X-Patchwork-Id: 8877501 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 514289F1C1 for ; Tue, 19 Apr 2016 07:52:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D90E720263 for ; Tue, 19 Apr 2016 07:52:55 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 5484F20145 for ; Tue, 19 Apr 2016 07:52:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CBAE66E6C9; Tue, 19 Apr 2016 07:52:51 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mblankhorst.nl (mblankhorst.nl [141.105.120.124]) by gabe.freedesktop.org (Postfix) with ESMTPS id 860B16E6CD for ; Tue, 19 Apr 2016 07:52:49 +0000 (UTC) From: Maarten Lankhorst To: intel-gfx@lists.freedesktop.org Date: Tue, 19 Apr 2016 09:52:31 +0200 Message-Id: <1461052359-24154-12-git-send-email-maarten.lankhorst@linux.intel.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1461052359-24154-1-git-send-email-maarten.lankhorst@linux.intel.com> References: <1461052359-24154-1-git-send-email-maarten.lankhorst@linux.intel.com> Subject: [Intel-gfx] [PATCH 11/19] drm/i915: Remove cs based page flip support. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP With mmio flips now available on all platforms it's time to remove support for cs flips. Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_debugfs.c | 19 +-- drivers/gpu/drm/i915/intel_display.c | 287 +---------------------------------- drivers/gpu/drm/i915/intel_drv.h | 6 +- 3 files changed, 10 insertions(+), 302 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5c6f25c54ef1..41e66035508e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -596,7 +596,6 @@ static void i915_dump_pageflip(struct seq_file *m, { const char pipe = pipe_name(crtc->pipe); u32 pending; - u32 addr; int i; pending = atomic_read(&work->pending); @@ -608,7 +607,6 @@ static void i915_dump_pageflip(struct seq_file *m, pipe, plane_name(crtc->plane)); } - for (i = 0; i < work->num_planes; i++) { struct intel_plane_state *old_plane_state = work->old_plane_state[i]; struct drm_plane *plane = old_plane_state->base.plane; @@ -632,22 +630,9 @@ static void i915_dump_pageflip(struct seq_file *m, i915_gem_request_completed(req, true)); } - seq_printf(m, "Flip queued on frame %d, (was ready on frame %d), now %d\n", - work->flip_queued_vblank, - work->flip_ready_vblank, + seq_printf(m, "Flip queued on frame %d, now %d\n", + pending ? work->flip_queued_vblank : -1, intel_crtc_get_vblank_counter(crtc)); - seq_printf(m, "%d prepares\n", atomic_read(&work->pending)); - - if (INTEL_INFO(dev_priv)->gen >= 4) - addr = I915_HI_DISPBASE(I915_READ(DSPSURF(crtc->plane))); - else - addr = I915_READ(DSPADDR(crtc->plane)); - seq_printf(m, "Current scanout address 0x%08x\n", addr); - - if (work->flip_queued_req) { - seq_printf(m, "New framebuffer address 0x%08lx\n", (long)work->gtt_offset); - seq_printf(m, "MMIO update completed? %d\n", addr == work->gtt_offset); - } } static int i915_gem_pageflip_info(struct seq_file *m, void *data) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f24fd5938475..b6e1b34bf6dd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -48,11 +48,6 @@ #include #include -static bool is_mmio_work(struct intel_flip_work *work) -{ - return !work->flip_queued_req; -} - /* Primary plane formats for gen <= 3 */ static const uint32_t i8xx_primary_formats[] = { DRM_FORMAT_C8, @@ -3921,21 +3916,7 @@ static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) if (ret < 0) return ret; - if (ret == 0) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_flip_work *work; - - spin_lock_irq(&dev->event_lock); - work = list_first_entry_or_null(&intel_crtc->flip_work, - struct intel_flip_work, head); - - if (work && !is_mmio_work(work) && - !work_busy(&work->unpin_work)) { - WARN_ONCE(1, "Removing stuck page flip\n"); - page_flip_completed(intel_crtc, work); - } - spin_unlock_irq(&dev->event_lock); - } + WARN(ret == 0, "Stuck page flip\n"); return 0; } @@ -11018,9 +10999,6 @@ static void intel_unpin_work_fn(struct work_struct *__work) intel_crtc_destroy_state(crtc, &work->old_crtc_state->base); - if (work->flip_queued_req) - i915_gem_request_unreference__unlocked(work->flip_queued_req); - for (i = 0; i < work->num_planes; i++) { struct intel_plane_state *old_plane_state = work->old_plane_state[i]; @@ -11052,63 +11030,6 @@ static void intel_unpin_work_fn(struct work_struct *__work) kfree(work); } -/* Is 'a' after or equal to 'b'? */ -static bool g4x_flip_count_after_eq(u32 a, u32 b) -{ - return !((a - b) & 0x80000000); -} - -static bool page_flip_finished(struct intel_crtc *crtc, - struct intel_flip_work *work) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned reset_counter; - - /* ensure that the unpin work is consistent wrt ->pending. */ - smp_mb__after_atomic(); - - reset_counter = i915_reset_counter(&dev_priv->gpu_error); - if (crtc->reset_counter != reset_counter) - return true; - - /* - * The relevant registers doen't exist on pre-ctg. - * As the flip done interrupt doesn't trigger for mmio - * flips on gmch platforms, a flip count check isn't - * really needed there. But since ctg has the registers, - * include it in the check anyway. - */ - if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev)) - return true; - - /* - * BDW signals flip done immediately if the plane - * is disabled, even if the plane enable is already - * armed to occur at the next vblank :( - */ - - /* - * A DSPSURFLIVE check isn't enough in case the mmio and CS flips - * used the same base address. In that case the mmio flip might - * have completed, but the CS hasn't even executed the flip yet. - * - * A flip count check isn't enough as the CS might have updated - * the base address just after start of vblank, but before we - * managed to process the interrupt. This means we'd complete the - * CS flip too soon. - * - * Combining both checks should get us a good enough result. It may - * still happen that the CS flip has been executed, but has not - * yet actually completed. But in case the base address is the same - * anyway, we don't really care. - */ - return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) == - work->gtt_offset && - g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_G4X(crtc->pipe)), - work->flip_count); -} - static void do_intel_finish_page_flip(struct drm_device *dev, struct drm_crtc *crtc) { @@ -11131,7 +11052,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev, if (work != NULL && atomic_read(&work->pending) == INTEL_FLIP_PENDING && - page_flip_finished(intel_crtc, work) && !work_busy(&work->unpin_work)) page_flip_completed(intel_crtc, work); @@ -11154,16 +11074,6 @@ void intel_finish_page_flip_plane(struct drm_device *dev, int plane) do_intel_finish_page_flip(dev, crtc); } -static inline void intel_mark_page_flip_active(struct intel_crtc *crtc, - struct intel_flip_work *work) -{ - work->flip_queued_vblank = intel_crtc_get_vblank_counter(crtc); - - /* Ensure that the work item is consistent when activating it ... */ - smp_mb__before_atomic(); - atomic_set(&work->pending, INTEL_FLIP_PENDING); -} - static int intel_gen2_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -11395,154 +11305,6 @@ static int intel_gen7_queue_flip(struct drm_device *dev, return 0; } -static struct intel_engine_cs * -intel_get_flip_engine(struct drm_device *dev, - struct drm_i915_private *dev_priv, - struct drm_i915_gem_object *obj) -{ - if (IS_VALLEYVIEW(dev) || IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) - return &dev_priv->engine[BCS]; - - if (dev_priv->info.gen >= 7) { - struct intel_engine_cs *engine; - - engine = i915_gem_request_get_engine(obj->last_write_req); - if (engine && engine->id == RCS) - return engine; - - return &dev_priv->engine[BCS]; - } else - return &dev_priv->engine[RCS]; -} - -static bool -flip_fb_compatible(struct drm_device *dev, - struct drm_framebuffer *fb, - struct drm_framebuffer *old_fb) -{ - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb); - - if (old_fb->pixel_format != fb->pixel_format) - return false; - - if (INTEL_INFO(dev)->gen > 3 && - (fb->offsets[0] != old_fb->offsets[0] || - fb->pitches[0] != old_fb->pitches[0])) - return false; - - /* vlv: DISPLAY_FLIP fails to change tiling */ - if (IS_VALLEYVIEW(dev) && obj->tiling_mode != old_obj->tiling_mode) - return false; - - return true; -} - -static void -intel_display_flip_prepare(struct drm_device *dev, struct drm_crtc *crtc, - struct intel_flip_work *work) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - if (work->flip_prepared) - return; - - work->flip_prepared = true; - - if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) - work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(intel_crtc->pipe)) + 1; - work->flip_queued_vblank = drm_crtc_vblank_count(crtc); - - intel_frontbuffer_flip_prepare(dev, work->new_crtc_state->fb_bits); -} - -static void intel_flip_schedule_request(struct intel_flip_work *work, struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_plane_state *new_state = work->new_plane_state[0]; - struct intel_plane_state *old_state = work->old_plane_state[0]; - struct drm_framebuffer *fb, *old_fb; - struct drm_i915_gem_request *request = NULL; - struct intel_engine_cs *engine; - struct drm_i915_gem_object *obj; - struct fence *fence; - int ret; - - to_intel_crtc(crtc)->reset_counter = i915_reset_counter(&dev_priv->gpu_error); - if (__i915_reset_in_progress_or_wedged(to_intel_crtc(crtc)->reset_counter)) - goto mmio; - - if (i915_terminally_wedged(&dev_priv->gpu_error) || - i915_reset_in_progress(&dev_priv->gpu_error) || - i915.enable_execlists || i915.use_mmio_flip > 0 || - !dev_priv->display.queue_flip) - goto mmio; - - /* Not right after modesetting, surface parameters need to be updated */ - if (needs_modeset(crtc->state) || - to_intel_crtc_state(crtc->state)->update_pipe) - goto mmio; - - /* Only allow a mmio flip for a primary plane without a dma-buf fence */ - if (work->num_planes != 1 || - new_state->base.plane != crtc->primary || - new_state->base.fence) - goto mmio; - - fence = work->old_plane_state[0]->base.fence; - if (fence && !fence_is_signaled(fence)) - goto mmio; - - old_fb = old_state->base.fb; - fb = new_state->base.fb; - obj = intel_fb_obj(fb); - - trace_i915_flip_request(to_intel_crtc(crtc)->plane, obj); - - /* Only when updating a already visible fb. */ - if (!new_state->visible || !old_state->visible) - goto mmio; - - if (!flip_fb_compatible(dev, fb, old_fb)) - goto mmio; - - engine = intel_get_flip_engine(dev, dev_priv, obj); - if (i915.use_mmio_flip == 0 && obj->last_write_req && - i915_gem_request_get_engine(obj->last_write_req) != engine) - goto mmio; - - work->gtt_offset = intel_plane_obj_offset(to_intel_plane(crtc->primary), obj, 0); - work->gtt_offset += to_intel_crtc(crtc)->dspaddr_offset; - - ret = i915_gem_object_sync(obj, engine, &request); - if (!ret && !request) { - request = i915_gem_request_alloc(engine, NULL); - ret = PTR_ERR_OR_ZERO(request); - - if (ret) - request = NULL; - } - - intel_display_flip_prepare(dev, crtc, work); - - if (!ret) - ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, request, 0); - - if (!ret) { - i915_gem_request_assign(&work->flip_queued_req, request); - intel_mark_page_flip_active(to_intel_crtc(crtc), work); - i915_add_request_no_flush(request); - return; - } - if (request) - i915_add_request_no_flush(request); - -mmio: - schedule_work(&work->mmio_work); -} - static void intel_mmio_flip_work_func(struct work_struct *w) { struct intel_flip_work *work = @@ -11570,7 +11332,7 @@ static void intel_mmio_flip_work_func(struct work_struct *w) &dev_priv->rps.mmioflips)); } - intel_display_flip_prepare(dev, crtc, work); + intel_frontbuffer_flip_prepare(dev, crtc_state->fb_bits); intel_pipe_update_start(intel_crtc); if (!needs_modeset(&crtc_state->base)) { @@ -11599,9 +11361,7 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev, struct drm_crtc *crtc, struct intel_flip_work *work) { - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - u32 addr, vblank; u32 pending; pending = atomic_read(&work->pending); @@ -11613,35 +11373,9 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev, return false; smp_mb__after_atomic(); - vblank = intel_crtc_get_vblank_counter(intel_crtc); - - if (is_mmio_work(work)) - /* MMIO work completes when vblank is different from flip_queued_vblank. */ - return vblank != work->flip_queued_vblank; - - if (work->flip_ready_vblank == 0) { - if (work->flip_queued_req && - !i915_gem_request_completed(work->flip_queued_req, true)) - return false; - - work->flip_ready_vblank = vblank; - } - - if (vblank - work->flip_ready_vblank < 3) - return false; - - /* Potential stall - if we see that the flip has happened, - * assume a missed interrupt. */ - if (INTEL_INFO(dev)->gen >= 4) - addr = I915_HI_DISPBASE(I915_READ(DSPSURF(intel_crtc->plane))); - else - addr = I915_READ(DSPADDR(intel_crtc->plane)); - /* There is a potential issue here with a false positive after a flip - * to the same address. We could address this by checking for a - * non-incrementing frame counter. - */ - return addr == work->gtt_offset; + /* MMIO work completes when vblank is different from flip_queued_vblank. */ + return work->flip_queued_vblank != intel_crtc_get_vblank_counter(intel_crtc); } void intel_check_page_flip(struct drm_device *dev, int pipe) @@ -11660,16 +11394,8 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) work = list_first_entry_or_null(&intel_crtc->flip_work, struct intel_flip_work, head); - if (work != NULL && __intel_pageflip_stall_check(dev, crtc, work)) { - WARN_ONCE(!is_mmio_work(work), - "Kicking stuck page flip: queued at %d, now %d\n", - work->flip_queued_vblank, intel_crtc_get_vblank_counter(intel_crtc)); + if (work != NULL && __intel_pageflip_stall_check(dev, crtc, work)) page_flip_completed(intel_crtc, work); - work = NULL; - } - if (work != NULL && !is_mmio_work(work) && - intel_crtc_get_vblank_counter(intel_crtc) - work->flip_queued_vblank > 1) - intel_queue_rps_boost_for_request(dev, work->flip_queued_req); spin_unlock(&dev->event_lock); } @@ -11836,7 +11562,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, intel_fbc_pre_update(intel_crtc); - intel_flip_schedule_request(work, crtc); + intel_crtc->reset_counter = i915_reset_counter(&dev_priv->gpu_error); + schedule_work(&work->mmio_work); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 19a74d9f550e..b18a0d117820 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -944,16 +944,12 @@ struct intel_flip_work { atomic_t pending; #define INTEL_FLIP_INACTIVE 0 #define INTEL_FLIP_PENDING 1 - u32 flip_count; - u32 gtt_offset; - struct drm_i915_gem_request *flip_queued_req; u32 flip_queued_vblank; - u32 flip_ready_vblank; unsigned put_power_domains; unsigned num_planes; - bool can_async_unpin, flip_prepared; + bool can_async_unpin; unsigned fb_bits; struct intel_crtc_state *old_crtc_state, *new_crtc_state;