From patchwork Tue Mar 19 13:05:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 10859545 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5690217E9 for ; Tue, 19 Mar 2019 13:05:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3CFC128346 for ; Tue, 19 Mar 2019 13:05:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3155D2969B; Tue, 19 Mar 2019 13:05:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B07929698 for ; Tue, 19 Mar 2019 13:05:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726466AbfCSNFX (ORCPT ); Tue, 19 Mar 2019 09:05:23 -0400 Received: from mailout2.w1.samsung.com ([210.118.77.12]:54643 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726002AbfCSNFX (ORCPT ); Tue, 19 Mar 2019 09:05:23 -0400 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20190319130519euoutp02c3fff0406c4e10414e2955f1788ea1e4~NXe02Ssh20511505115euoutp02U; Tue, 19 Mar 2019 13:05:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20190319130519euoutp02c3fff0406c4e10414e2955f1788ea1e4~NXe02Ssh20511505115euoutp02U DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1553000719; bh=1tJAEAFaCc/liEzSCpUoopgDrNttQIwBokwwWn1HXpc=; h=From:To:Cc:Subject:Date:References:From; b=ZU8cxGIiDQl5hvkaCkUjAnd+C/UdRxFvLd/snTNmtgL3xjEJashFIn/Mauah0/nH1 aUf67Hf+xTimjkGPGHkPFktWphk1h6CKLzJBo8Tw/YgQU538cwyA4+l4tdeOrQcP76 rULUFdb4SPYVT9QSHaITL3AnMqOcER1etHFccm2k= Received: from eusmges2new.samsung.com (unknown [203.254.199.244]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20190319130519eucas1p2734f2972cd1dacc81c716251187a5bf0~NXe0Td60s2796127961eucas1p2n; Tue, 19 Mar 2019 13:05:19 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges2new.samsung.com (EUCPMTA) with SMTP id 99.14.04294.F09E09C5; Tue, 19 Mar 2019 13:05:19 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20190319130518eucas1p138ba1c2026a1d83959c2bdeaf6575ab5~NXezuxHDO1495414954eucas1p1X; Tue, 19 Mar 2019 13:05:18 +0000 (GMT) X-AuditID: cbfec7f4-84fff700000010c6-a2-5c90e90ff47f Received: from eusync1.samsung.com ( [203.254.199.211]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id F7.36.04128.E09E09C5; Tue, 19 Mar 2019 13:05:18 +0000 (GMT) Received: from AMDC3748.DIGITAL.local ([106.120.43.17]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0POM00IMD70TRE60@eusync1.samsung.com>; Tue, 19 Mar 2019 13:05:18 +0000 (GMT) From: Andrzej Hajda To: Inki Dae , Marian Mihailescu Cc: dri-devel@lists.freedesktop.org, linux-samsung-soc@vger.kernel.org, Andrzej Hajda , Bartlomiej Zolnierkiewicz , Marek Szyprowski Subject: [PATCH v2] drm/exynos/mixer: fix MIXER shadow registry synchronisation code Date: Tue, 19 Mar 2019 14:05:11 +0100 Message-id: <20190319130511.20729-1-a.hajda@samsung.com> X-Mailer: git-send-email 2.17.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupikeLIzCtJLcpLzFFi42LZduzneV3+lxNiDL5+Yre4te4cq8XGGetZ La58fc9mMen+BBaLGef3MVmsPXKX3WL9tJ+sDuweO2fdZfe4332cyaNvyypGj8+b5AJYorhs UlJzMstSi/TtErgy3q3tYSmY7lCxb+cn5gbGraZdjJwcEgImEk1P3rF3MXJxCAmsYJT42vGc EcL5zCjxbucU1i5GDrCq3odREPFljBI39v5mgXD+M0q0NaxlARnFJqAp8XfzTTaQBhGBQIkn ewVAwswCl4CmHtYHsYUFwiTmztrICmKzCKhKXF64hxnE5hWwkJi94CY7xEXyEqs3HGAGmS8h 8JZVovfILFaIhIvEi4e3oGwZicuTu1kg7HqJ+ytaoBo6GCW2btjJDJGwljh8/CIrxBV8EpO2 TWeG+IZXoqNNCKLEQ2JdyzsmEFtIIFZiddsitgmM4gsYGVYxiqeWFuempxYb5aWW6xUn5haX 5qXrJefnbmIExtDpf8e/7GDc9SfpEKMAB6MSD++F5xNihFgTy4orcw8xSnAwK4nw2mwHCvGm JFZWpRblxxeV5qQWH2KU5mBREuetZngQLSSQnliSmp2aWpBaBJNl4uCUamB0cOrr2h8Xv8lo tbJWllXR3cdXtlkaT+H4btzNVyC//2xq0/YXMzfJb4wt/dDz4YgTb/T2uGmZkW2uO2RU7Gw1 5HKD4vdVzf3WcrZ7UyVT1FzDwOPHe+reOWnY3YqUSuKpFt5zMb9xzb7dig88vBmn6wrrH83f +2NOn4aMcrnAn2mBiQqaVkosxRmJhlrMRcWJADExWsydAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrFJMWRmVeSWpSXmKPExsVy+t/xy7p8LyfEGHw4K2dxa905VouNM9az Wlz5+p7NYtL9CSwWM87vY7JYe+Quu8X6aT9ZHdg9ds66y+5xv/s4k0ffllWMHp83yQWwRHHZ pKTmZJalFunbJXBlvFvbw1Iw3aFi385PzA2MW027GDk4JARMJHofRnUxcnEICSxhlHg99S4j hNPIJLF9zhG2LkZODjYBTYm/m2+C2SIC/hKrHncxgxQxC1xhlOi6d5wFJCEsECZxdtYvRhCb RUBV4vLCPcwgNq+AhcTsBTfZQWwJAXmJ1RsOME9g5FrAyLCKUSS1tDg3PbfYSK84Mbe4NC9d Lzk/dxMjMAS2Hfu5ZQdj17vgQ4wCHIxKPLwrZvTHCLEmlhVX5h5ilOBgVhLhtdk+IUaINyWx siq1KD++qDQntfgQozQHi5I473mDyighgfTEktTs1NSC1CKYLBMHp1QDo/PCGzM+z1yvsLoy YWaEefjp4MYbUVEvBa5/uqHcsUDy8LETU2dkhJj5TNPqNLHYNDN94ZP524ML7u2dbDmb59nt A/Kfz7b0cL4tuZSTNy2wdO7rBI1f+44dfMQR4LkpxI4jcVPx95blAmEf3dctWcHu6qoa+E9/ wsOFCsXF3Du/X64PigovPajEUpyRaKjFXFScCABPw2vC/QEAAA== X-CMS-MailID: 20190319130518eucas1p138ba1c2026a1d83959c2bdeaf6575ab5 CMS-TYPE: 201P X-CMS-RootMailID: 20190319130518eucas1p138ba1c2026a1d83959c2bdeaf6575ab5 References: Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP MIXER on Exynos5 SoCs uses different synchronisation method than Exynos4 to update internal state (shadow registers). Apparently the driver implements it incorrectly. The rule should be as follows: - do not request updating registers until previous request was finished, ie. MXR_CFG_LAYER_UPDATE_COUNT must be 0. - before setting registers synchronisation on VSYNC should be turned off, ie. MXR_STATUS_SYNC_ENABLE should be reset, - after finishing MXR_STATUS_SYNC_ENABLE should be set again. The patch hopefully implements it correctly. Below sample kernel log from page fault caused by the bug: [ 25.670038] exynos-sysmmu 14650000.sysmmu: 14450000.mixer: PAGE FAULT occurred at 0x2247b800 [ 25.677888] ------------[ cut here ]------------ [ 25.682164] kernel BUG at ../drivers/iommu/exynos-iommu.c:450! [ 25.687971] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM [ 25.693778] Modules linked in: [ 25.696816] CPU: 5 PID: 1553 Comm: fb-release_test Not tainted 5.0.0-rc7-01157-g5f86b1566bdd #136 [ 25.705646] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [ 25.711710] PC is at exynos_sysmmu_irq+0x1c0/0x264 [ 25.716470] LR is at lock_is_held_type+0x44/0x64 v2: added missing MXR_CFG_LAYER_UPDATE bit setting in mixer_enable_sync Reported-by: Marian Mihailescu Signed-off-by: Andrzej Hajda --- Hi Inki and Marian, This is fixed version of my previous patch. The only difference is added missing MXR_CFG_LAYER_UPDATE setting in mixer_enable_sync. I hope this time it is correct. It should solve one page fault issue in MIXER, Marek is preparing fix for another issue (to low clock set by devfreq). I hope with both patches page faults will not happen anymore ;) Regards Andrzej --- drivers/gpu/drm/exynos/exynos_mixer.c | 110 +++++++++++++++----------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 0573eab0e190..f35e4ab55b27 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -20,6 +20,7 @@ #include "regs-vp.h" #include +#include #include #include #include @@ -352,15 +353,62 @@ static void mixer_cfg_vp_blend(struct mixer_context *ctx, unsigned int alpha) mixer_reg_write(ctx, MXR_VIDEO_CFG, val); } -static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) +static bool mixer_is_synced(struct mixer_context *ctx) { - /* block update on vsync */ - mixer_reg_writemask(ctx, MXR_STATUS, enable ? - MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); + u32 base, shadow; + if (ctx->mxr_ver == MXR_VER_16_0_33_0 || + ctx->mxr_ver == MXR_VER_128_0_0_184) + return !(mixer_reg_read(ctx, MXR_CFG) & + MXR_CFG_LAYER_UPDATE_COUNT_MASK); + + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) && + vp_reg_read(ctx, VP_SHADOW_UPDATE)) + return false; + + base = mixer_reg_read(ctx, MXR_CFG); + shadow = mixer_reg_read(ctx, MXR_CFG_S); + if (base != shadow) + return false; + + base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0)); + shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0)); + if (base != shadow) + return false; + + base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(1)); + shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(1)); + if (base != shadow) + return false; + + return true; +} + +static int mixer_wait_for_sync(struct mixer_context *ctx) +{ + ktime_t timeout = ktime_add_us(ktime_get(), 100000); + + while (!mixer_is_synced(ctx)) { + usleep_range(1000, 2000); + if (ktime_compare(ktime_get(), timeout) > 0) + return -ETIMEDOUT; + } + return 0; +} + +static void mixer_disable_sync(struct mixer_context *ctx) +{ + mixer_reg_writemask(ctx, MXR_STATUS, 0, MXR_STATUS_SYNC_ENABLE); +} + +static void mixer_enable_sync(struct mixer_context *ctx) +{ + if (ctx->mxr_ver == MXR_VER_16_0_33_0 || + ctx->mxr_ver == MXR_VER_128_0_0_184) + mixer_reg_writemask(ctx, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); + mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SYNC_ENABLE); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) - vp_reg_write(ctx, VP_SHADOW_UPDATE, enable ? - VP_SHADOW_UPDATE_ENABLE : 0); + vp_reg_write(ctx, VP_SHADOW_UPDATE, VP_SHADOW_UPDATE_ENABLE); } static void mixer_cfg_scan(struct mixer_context *ctx, int width, int height) @@ -498,7 +546,6 @@ static void vp_video_buffer(struct mixer_context *ctx, spin_lock_irqsave(&ctx->reg_slock, flags); - vp_reg_write(ctx, VP_SHADOW_UPDATE, 1); /* interlace or progressive scan mode */ val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP); @@ -553,11 +600,6 @@ static void vp_video_buffer(struct mixer_context *ctx, vp_regs_dump(ctx); } -static void mixer_layer_update(struct mixer_context *ctx) -{ - mixer_reg_writemask(ctx, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); -} - static void mixer_graph_buffer(struct mixer_context *ctx, struct exynos_drm_plane *plane) { @@ -640,11 +682,6 @@ static void mixer_graph_buffer(struct mixer_context *ctx, mixer_cfg_layer(ctx, win, priority, true); mixer_cfg_gfx_blend(ctx, win, pixel_alpha, state->base.alpha); - /* layer update mandatory for mixer 16.0.33.0 */ - if (ctx->mxr_ver == MXR_VER_16_0_33_0 || - ctx->mxr_ver == MXR_VER_128_0_0_184) - mixer_layer_update(ctx); - spin_unlock_irqrestore(&ctx->reg_slock, flags); mixer_regs_dump(ctx); @@ -709,7 +746,7 @@ static void mixer_win_reset(struct mixer_context *ctx) static irqreturn_t mixer_irq_handler(int irq, void *arg) { struct mixer_context *ctx = arg; - u32 val, base, shadow; + u32 val; spin_lock(&ctx->reg_slock); @@ -723,26 +760,9 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) val &= ~MXR_INT_STATUS_VSYNC; /* interlace scan need to check shadow register */ - if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { - if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) && - vp_reg_read(ctx, VP_SHADOW_UPDATE)) - goto out; - - base = mixer_reg_read(ctx, MXR_CFG); - shadow = mixer_reg_read(ctx, MXR_CFG_S); - if (base != shadow) - goto out; - - base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0)); - shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0)); - if (base != shadow) - goto out; - - base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(1)); - shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(1)); - if (base != shadow) - goto out; - } + if (test_bit(MXR_BIT_INTERLACE, &ctx->flags) + && !mixer_is_synced(ctx)) + goto out; drm_crtc_handle_vblank(&ctx->crtc->base); } @@ -917,12 +937,14 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) static void mixer_atomic_begin(struct exynos_drm_crtc *crtc) { - struct mixer_context *mixer_ctx = crtc->ctx; + struct mixer_context *ctx = crtc->ctx; - if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) + if (!test_bit(MXR_BIT_POWERED, &ctx->flags)) return; - mixer_vsync_set_update(mixer_ctx, false); + if (mixer_wait_for_sync(ctx)) + dev_err(ctx->dev, "timeout waiting for VSYNC\n"); + mixer_disable_sync(ctx); } static void mixer_update_plane(struct exynos_drm_crtc *crtc, @@ -964,7 +986,7 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc) if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return; - mixer_vsync_set_update(mixer_ctx, true); + mixer_enable_sync(mixer_ctx); exynos_crtc_handle_event(crtc); } @@ -979,7 +1001,7 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) exynos_drm_pipe_clk_enable(crtc, true); - mixer_vsync_set_update(ctx, false); + mixer_disable_sync(ctx); mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); @@ -992,7 +1014,7 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) mixer_commit(ctx); - mixer_vsync_set_update(ctx, true); + mixer_enable_sync(ctx); set_bit(MXR_BIT_POWERED, &ctx->flags); }