From patchwork Wed Mar 6 15:05:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 10841267 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 73C1B14DE for ; Wed, 6 Mar 2019 15:06:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 52CA62E186 for ; Wed, 6 Mar 2019 15:06:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 46DE02E18C; Wed, 6 Mar 2019 15:06:11 +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 519622E186 for ; Wed, 6 Mar 2019 15:06:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727593AbfCFPGJ (ORCPT ); Wed, 6 Mar 2019 10:06:09 -0500 Received: from mailout2.w1.samsung.com ([210.118.77.12]:37780 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727818AbfCFPGJ (ORCPT ); Wed, 6 Mar 2019 10:06:09 -0500 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20190306150607euoutp02694fabc07eae04a8dd12701c845f749b~JZvk6hB5r0035700357euoutp02e; Wed, 6 Mar 2019 15:06:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20190306150607euoutp02694fabc07eae04a8dd12701c845f749b~JZvk6hB5r0035700357euoutp02e DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1551884767; bh=RzODMa7enp5iZoz/muB+Tb6clX3eKNlmve3P1ovTwVQ=; h=From:To:Cc:Subject:Date:References:From; b=io3ZDvfDbPTIhBoS3FpbbbJkEdI94IqSQxZj8hg3oaedONzZ88e8EoKZ5gs0GCior icyhMMpxrhGjcMDAL6fhN1JuVierE4P82o0Ww8OplIsLlbkt9u157UnDlzMT9LVq4L 5bT/mU1ipyKpXxXdCLCv2Yjn8Vj1fmou4/RU7XgE= Received: from eusmges1new.samsung.com (unknown [203.254.199.242]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20190306150606eucas1p2d9b9f34e9219c8bbffe670b08756ca0f~JZvkBNAP61796717967eucas1p2H; Wed, 6 Mar 2019 15:06:06 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges1new.samsung.com (EUCPMTA) with SMTP id 98.19.04441.DD1EF7C5; Wed, 6 Mar 2019 15:06:05 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20190306150605eucas1p2fada42624ed864bfe1b7fff69afdceb9~JZvjTwufL2349623496eucas1p23; Wed, 6 Mar 2019 15:06:05 +0000 (GMT) X-AuditID: cbfec7f2-5e3ff70000001159-1d-5c7fe1dd3e2e Received: from eusync3.samsung.com ( [203.254.199.213]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id E1.BF.04128.DD1EF7C5; Wed, 6 Mar 2019 15:06:05 +0000 (GMT) Received: from AMDC3748.DIGITAL.local ([106.120.43.17]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0PNY00C0Q9Y4TQ40@eusync3.samsung.com>; Wed, 06 Mar 2019 15:06:05 +0000 (GMT) From: Andrzej Hajda To: Inki Dae Cc: dri-devel@lists.freedesktop.org, linux-samsung-soc@vger.kernel.org, Marian Mihailescu , Andrzej Hajda , Bartlomiej Zolnierkiewicz , Marek Szyprowski Subject: [PATCH] drm/exynos/mixer: fix MIXER shadow registry synchronisation code Date: Wed, 06 Mar 2019 16:05:59 +0100 Message-id: <20190306150559.20987-1-a.hajda@samsung.com> X-Mailer: git-send-email 2.17.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupkkeLIzCtJLcpLzFFi42LZduzned27D+tjDCZttLS4te4cq8XGGetZ La58fc9mMen+BBaLGef3MVmsPXKX3WL9tJ+sDuweO2fdZfe4332cyaNvyypGj8+b5AJYorhs UlJzMstSi/TtErgy2s9MZS5YZF2xdv4TlgbGjYZdjJwcEgImEte3f2YFsYUEVjBKrO6y6GLk ArI/M0qcPrONFabo0PRmRoiiZYwSuzd6QBT9Z5Q4/O0AM0iCTUBT4u/mm2wgtoiAssSqfe3s IEXMAg1MEjv3TmcHSQgLBEt8+fkLaBIHB4uAqsSLdm+QMK+AhcSah81sEMvkJVZvgJgpIfCU VeLIBk0I20Xi8sYmqBoZicuTu1kg7HqJpplXmEF2SQh0MEqcWLwcqsha4vDxi2AfMAvwSUza Np0ZZK+EAK9ER5sQRImHxMrpu9ghHouVuP7qHvMERvEFjAyrGMVTS4tz01OLDfNSy/WKE3OL S/PS9ZLzczcxAiPo9L/jn3Ywfr2UdIhRgINRiYeX40J9jBBrYllxZe4hRgkOZiURXvc1QCHe lMTKqtSi/Pii0pzU4kOM0hwsSuK81QwPooUE0hNLUrNTUwtSi2CyTBycUg2MjjX7bBNS3lVE lC1feyFNWMsvtmuj4+v0DbLGAUdZ/9stjljDKH3+8ynu+9pPmE8mzfy+f9r/Vfc7d1XNO7F4 8SzWC4vkNXpWcSxaFxhhkD9v4tuy05paNxg/8m9sWfrOeX6QdZik7uVtq+p1vmv0v3R3Eyqu 0M22yL9dI5+9zzlYO9A0eGuDEktxRqKhFnNRcSIA5cB32JwCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrJJMWRmVeSWpSXmKPExsVy+t/xq7p3H9bHGPx5xWdxa905VouNM9az Wlz5+p7NYtL9CSwWM87vY7JYe+Quu8X6aT9ZHdg9ds66y+5xv/s4k0ffllWMHp83yQWwRHHZ pKTmZJalFunbJXBltJ+ZylywyLpi7fwnLA2MGw27GDk5JARMJA5Nb2bsYuTiEBJYwigxoaeB BcJpZJLYMuMEI0gVm4CmxN/NN9lAbBEBZYlV+9rZQWxmgSYmiY0neUFsYYFgiS8/fwHVc3Cw CKhKvGj3BgnzClhIrHnYzAaxTF5i9YYDzBMYuRYwMqxiFEktLc5Nzy020itOzC0uzUvXS87P 3cQIDIBtx35u2cHY9S74EKMAB6MSDy/DyfoYIdbEsuLK3EOMEhzMSiK87muAQrwpiZVVqUX5 8UWlOanFhxilOViUxHnPG1RGCQmkJ5akZqemFqQWwWSZODilGhibS8+x7PaydPZ/VK2gumLm npsuXFbXduyO3lzaM2syW9FlprJtExoKzDJv2vGsWK/iVV+h+YQvRfgUn/Ls5NPV2WJzoqvU Oi9wql6ZyX1M8n7Y/3cmvp9CAuM0n2t8Un9rsfhOVLLQvF57hn8MT59N/LNX92bBqUrvSb3H M5R1w22n3z3oxKfEUpyRaKjFXFScCADYOLio/AEAAA== X-CMS-MailID: 20190306150605eucas1p2fada42624ed864bfe1b7fff69afdceb9 CMS-TYPE: 201P X-CMS-RootMailID: 20190306150605eucas1p2fada42624ed864bfe1b7fff69afdceb9 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 Reported-by: Marian Mihailescu Signed-off-by: Andrzej Hajda --- drivers/gpu/drm/exynos/exynos_mixer.c | 107 +++++++++++++++----------- 1 file changed, 63 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 0573eab0e190..42ce01c226ef 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,59 @@ 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) +{ + 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 +543,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 +597,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 +679,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 +743,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 +757,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 +934,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 +983,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 +998,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 +1011,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); }