drm/rockchip: vop: reference vblank before queue to flip worker
authorMark Yao <mark.yao@rock-chips.com>
Wed, 2 Aug 2017 01:48:43 +0000 (09:48 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Wed, 2 Aug 2017 06:19:55 +0000 (14:19 +0800)
Reference vblank after the fb_unref_worker may have a problem:
    queue fb_unref_work
                         <--- unfer_worker:drm_crtc_vblank_put()
    drm_crtc_vblank_get

Following Warning may cause by this race:

[11749.638812] WARNING: at drivers/gpu/drm/drm_irq.c:1272
[11749.638818] Modules linked in:
[11749.638825]
[11749.638833] CPU: 4 PID: 8446 Comm: kworker/u12:1 Not tainted 4.4.77 #2428
[11749.638841] Hardware name: Rockchip RK3399 Excavator Board edp (Android) (DT)
[11749.638864] Workqueue: events_unbound flip_worker
[11749.638873] task: ffffffc0f1a7db00 ti: ffffffc0da3f8000 task.ti: ffffffc0da3f8000
[11749.638884] PC is at drm_vblank_put+0x34/0xac
[11749.638890] LR is at drm_crtc_vblank_put+0x20/0x2c
[11749.642771] [<ffffff8008473cb0>] drm_vblank_put+0x34/0xac
[11749.642778] [<ffffff8008473d48>] drm_crtc_vblank_put+0x20/0x2c
[11749.642786] [<ffffff80084a2894>] vop_fb_unref_worker+0x14/0x28
[11749.642792] [<ffffff800848c2a0>] flip_worker+0xa8/0xe8
[11749.642801] [<ffffff80080b73f4>] process_one_work+0x218/0x3e0
[11749.642808] [<ffffff80080b7df4>] worker_thread+0x2e8/0x404
[11749.642814] [<ffffff80080bc738>] kthread+0xf8/0x100
[11749.642821] [<ffffff8008082840>] ret_from_fork+0x10/0x50

Change-Id: I2b7f8a84d18e4635122b5028d39ec8192c6ca70b
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_vop.c

index 4549fcfec4485afd4c6e17b3c8005afb53b6d426..7b4e9ac4895659f02a7211db84a8ac8ecbdbbcc5 100644 (file)
@@ -2323,9 +2323,9 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
                        continue;
 
                drm_framebuffer_reference(old_plane_state->fb);
+               WARN_ON(drm_crtc_vblank_get(crtc) != 0);
                drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
                set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
-               WARN_ON(drm_crtc_vblank_get(crtc) != 0);
        }
 }