From: Tomasz Figa Date: Wed, 14 Sep 2016 12:54:58 +0000 (+0900) Subject: UPSTREAM: drm/rockchip: Replace custom wait_for_vblanks with helper X-Git-Tag: release-20171130_firefly~4^2~174 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2c47c0d0c955fd3b90396ca6bcf13ed6e385229a;p=firefly-linux-kernel-4.4.55.git UPSTREAM: drm/rockchip: Replace custom wait_for_vblanks with helper Currently the driver uses a custom function to wait for flip to complete after an atomic commit. It was needed before because of two problems: - there is no hardware vblank counter, so the original helper would have a race condition with the vblank interrupt, - the driver didn't support unreferencing cursor framebuffers asynchronously to the commit, which was what the helper expected. Since both problems have been solved by previous patches, we can now make the driver use the generic helper and remove custom waiting code. Signed-off-by: Tomasz Figa (cherry picked from commit 81c248f75a130c1ce46c67e8b05b37e8ffbbb33e) Change-Id: Ida5a38b71f9e7812f415eb8889d906d2fe3b093e Signed-off-by: Mark Yao --- diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 189866876106..600f4a1a7f20 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -42,7 +42,6 @@ struct rockchip_crtc_funcs { int (*loader_protect)(struct drm_crtc *crtc, bool on); int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); - void (*wait_for_update)(struct drm_crtc *crtc); void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv); int (*debugfs_dump)(struct drm_crtc *crtc, struct seq_file *s); void (*regs_dump)(struct drm_crtc *crtc, struct seq_file *s); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 15fe607f2bc1..deb1b8374b0c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -208,68 +208,6 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev) drm_fb_helper_hotplug_event(fb_helper); } -static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc) -{ - struct rockchip_drm_private *priv = crtc->dev->dev_private; - int pipe = drm_crtc_index(crtc); - const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe]; - - if (crtc_funcs && crtc_funcs->wait_for_update) - crtc_funcs->wait_for_update(crtc); -} - -/* - * We can't use drm_atomic_helper_wait_for_vblanks() because rk3288 and rk3066 - * have hardware counters for neither vblanks nor scanlines, which results in - * a race where: - * | <-- HW vsync irq and reg take effect - * plane_commit --> | - * get_vblank and wait --> | - * | <-- handle_vblank, vblank->count + 1 - * cleanup_fb --> | - * iommu crash --> | - * | <-- HW vsync irq and reg take effect - * - * This function is equivalent but uses rockchip_crtc_wait_for_update() instead - * of waiting for vblank_count to change. - */ -static void -rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_state *old_state) -{ - struct drm_crtc_state *old_crtc_state; - struct drm_crtc *crtc; - int i, ret; - - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { - /* No one cares about the old state, so abuse it for tracking - * and store whether we hold a vblank reference (and should do a - * vblank wait) in the ->enable boolean. - */ - old_crtc_state->enable = false; - - if (!crtc->state->active) - continue; - - if (!drm_atomic_helper_framebuffer_changed(dev, - old_state, crtc)) - continue; - - ret = drm_crtc_vblank_get(crtc); - if (ret != 0) - continue; - - old_crtc_state->enable = true; - } - - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { - if (!old_crtc_state->enable) - continue; - - rockchip_crtc_wait_for_update(crtc); - drm_crtc_vblank_put(crtc); - } -} - static void rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit) { @@ -301,7 +239,7 @@ rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit) drm_atomic_helper_commit_planes(dev, state, true); - rockchip_atomic_wait_for_complete(dev, state); + drm_atomic_helper_wait_for_vblanks(dev, state); drm_atomic_helper_cleanup_planes(dev, state); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 451899d4fd56..7f287f745768 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -184,7 +184,8 @@ struct vop { bool vsync_work_pending; bool loader_protect; struct completion dsp_hold_completion; - struct completion wait_update_complete; + + /* protected by dev->event_lock */ struct drm_pending_vblank_event *event; struct drm_flip_work fb_unref_work; @@ -1440,15 +1441,6 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc) spin_unlock_irqrestore(&vop->irq_lock, flags); } -static void vop_crtc_wait_for_update(struct drm_crtc *crtc) -{ - struct vop *vop = to_vop(crtc); - - reinit_completion(&vop->wait_update_complete); - WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, - msecs_to_jiffies(1000))); -} - static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc, struct drm_file *file_priv) { @@ -1625,7 +1617,6 @@ static const struct rockchip_crtc_funcs private_crtc_funcs = { .loader_protect = vop_crtc_loader_protect, .enable_vblank = vop_crtc_enable_vblank, .disable_vblank = vop_crtc_disable_vblank, - .wait_for_update = vop_crtc_wait_for_update, .cancel_pending_vblank = vop_crtc_cancel_pending_vblank, .debugfs_dump = vop_crtc_debugfs_dump, .regs_dump = vop_crtc_regs_dump, @@ -2388,8 +2379,6 @@ static void vop_handle_vblank(struct vop *vop) spin_unlock_irqrestore(&drm->event_lock, flags); } - if (!completion_done(&vop->wait_update_complete)) - complete(&vop->wait_update_complete); if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending)) drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq); @@ -2579,7 +2568,6 @@ static int vop_create_crtc(struct vop *vop) vop_fb_unref_worker); init_completion(&vop->dsp_hold_completion); - init_completion(&vop->wait_update_complete); init_completion(&vop->line_flag_completion); crtc->port = port; rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);