From patchwork Wed Nov 14 08:59:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inki Dae X-Patchwork-Id: 1739981 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id CE7DADF264 for ; Wed, 14 Nov 2012 09:03:21 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AB0E99F70C for ; Wed, 14 Nov 2012 01:03:21 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by gabe.freedesktop.org (Postfix) with ESMTP id CA9479F6DC for ; Wed, 14 Nov 2012 01:01:11 -0800 (PST) Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MDG00830ZJWE140@mailout4.samsung.com> for dri-devel@lists.freedesktop.org; Wed, 14 Nov 2012 17:59:40 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [203.254.230.41]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 4E.79.12699.C7D53A05; Wed, 14 Nov 2012 17:59:40 +0900 (KST) X-AuditID: cbfee61b-b7f616d00000319b-1f-50a35d7cf09a Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 0D.79.12699.C7D53A05; Wed, 14 Nov 2012 17:59:40 +0900 (KST) Received: from daeinki-desktop.10.32.193.11 ([10.90.51.53]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MDG00IF6ZNC0Z50@mmp2.samsung.com> for dri-devel@lists.freedesktop.org; Wed, 14 Nov 2012 17:59:40 +0900 (KST) From: Inki Dae To: airlied@linux.ie, dri-devel@lists.freedesktop.org Subject: [PATCH 2/2] drm/exynos: release fb pended by page flip Date: Wed, 14 Nov 2012 17:59:36 +0900 Message-id: <1352883576-25552-2-git-send-email-inki.dae@samsung.com> X-Mailer: git-send-email 1.7.4.1 In-reply-to: <1352883576-25552-1-git-send-email-inki.dae@samsung.com> References: <1352883576-25552-1-git-send-email-inki.dae@samsung.com> DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrDLMWRmVeSWpSXmKPExsVy+t8zTd2a2MUBBk+OKFlc+fqezYHR4373 caYAxigum5TUnMyy1CJ9uwSujJWfj7AUfLSo2D7/LlMD42m9LkZODgkBE4m9ByczQdhiEhfu rWfrYuTiEBJYxijxcEUPI0zR3e/LWEFsIYHpjBKdf6wgitYzSaztPMECkmATUJWYuOI+G4gt ImAq0TFpKVicWaBQYmHPUzBbWMBe4suMZcwgNgtQ/ean68BsXgEXifO9c1ghlilILLj3FmwO p4CrRN/p52wQi10kbqzsYIHoFZD4NvkQkM0BVC8rsekAM8g9EgIn2CRuNF+AmiMpcXDFDZYJ jMILGBlWMYqmFiQXFCel5xrpFSfmFpfmpesl5+duYoQEofQOxlUNFocYBTgYlXh4A/oXBQix JpYVV+YeYpTgYFYS4Y21WhwgxJuSWFmVWpQfX1Sak1p8iNEH6JKJzFKiyfnACMkriTc0NjA2 NLQ0NDO1NDXAIawkztvskRIgJJCeWJKanZpakFoEM46Jg1OqgVHKRyez9uRNP55Wkb5v384Z ejT1713kpSSzZbl/sXxQY4Wdw8XqedVb9i0x4Zv27tSc0ya9C/csVUuZPtdxvdicCvYvGf4e 8p12DnoPxfl/MSVeKkhc+unirfsBoS1d66/t99oauev7Xf22gLnKQmZbbXK1X8mFnc92kV30 6/+7pg9yv/+En1JiKc5INNRiLipOBACydGskbwIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupmkeLIzCtJLcpLzFFi42I5/e+xoG5N7OIAg9apMhZXvr5nc2D0uN99 nCmAMaqB0SYjNTEltUghNS85PyUzL91WyTs43jne1MzAUNfQ0sJcSSEvMTfVVsnFJ0DXLTMH aKySQlliTilQKCCxuFhJ3w7ThNAQN10LmMYIXd+QILgeIwM0kLCOMWPl5yMsBR8tKrbPv8vU wHhar4uRk0NCwETi7vdlrBC2mMSFe+vZQGwhgemMEp1/rLoYuYDs9UwSaztPsIAk2ARUJSau uA9WJCJgKtExaSlYnFmgUGJhz1MwW1jAXuLLjGXMIDYLUP3mp+vAbF4BF4nzvXOglilILLj3 FmwOp4CrRN/p51CLXSRurOxgmcDIu4CRYRWjaGpBckFxUnqukV5xYm5xaV66XnJ+7iZGcIg/ k97BuKrB4hCjAAejEg9vQP+iACHWxLLiytxDjBIczEoivLFWiwOEeFMSK6tSi/Lji0pzUosP MfoAXTWRWUo0OR8Yf3kl8YbGJmZGlkZmxibmxsY4hJXEeZs9UgKEBNITS1KzU1MLUotgxjFx cEo1MG5e8aTreJXMxsNz/0SoKAjGL+YJ2WF5PPrG5S1JimmxbeWGG9xiG3MK9E45KK/Vy7Lq m88bPfO/2bJtWVYXBDTs2t8cLhFREfqys2Lm9h0sSdHab5ISp8UfKMzwZz979cae75s+MjGe 2q4p89RtXfiMT7v32Fe6J/4tuJve6Kiu9XVVwt6Zt5VYijMSDbWYi4oTAeMBhZ2eAgAA X-CFilter-Loop: Reflected Cc: kyungmin.park@samsung.com, sw0312.kim@samsung.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org This patch releases the fb pended by page flip after fbdev is restored propely. And fixes invalid memory access when drm is released while doing pageflip. This patch makes fb's refcount to be increased when setcrtc and pageflip are requested. In other words, it increases fb's refcount only if dma is going to access memory region to fb and decreases old fb's because the old fb isn't accessed by dma anymore. This could guarantee releasing gem buffer to the fb after dma access to the gem buffer has been completed. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 42 ++++++++++++++++++++++++++++- drivers/gpu/drm/exynos/exynos_drm_fb.c | 23 ++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_fb.h | 6 ++++ drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 9 ++++++ drivers/gpu/drm/exynos/exynos_drm_plane.c | 18 +++++++++++- 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 2efa4b0..2a52b7e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -32,6 +32,7 @@ #include "exynos_drm_drv.h" #include "exynos_drm_encoder.h" #include "exynos_drm_plane.h" +#include "exynos_drm_fb.h" #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ drm_crtc) @@ -137,8 +138,26 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, return ret; plane->crtc = crtc; + + /* + * If old_fb exists, unreference the fb. + * + * This means that memory region to the fb isn't accessed by the dma + * of this plane anymore. + */ + if (old_fb) + drm_framebuffer_unreference(old_fb); + plane->fb = crtc->fb; + /* + * Take a reference to new fb. + * + * Taking a reference means that this plane's dma is going to access + * memory region to the new fb. + */ + drm_framebuffer_reference(plane->fb); + exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe); return 0; @@ -168,6 +187,24 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, x, y, crtc_w, crtc_h); if (ret) return ret; + /* + * If old_fb exists, unreference the fb. + * + * This means that memory region to the fb isn't accessed by the dma + * of this plane anymore. + */ + if (old_fb) + drm_framebuffer_unreference(old_fb); + + plane->fb = crtc->fb; + + /* + * Take a reference to new fb. + * + * Taking a reference means that this plane's dma is going to access + * memory region to the new fb. + */ + drm_framebuffer_reference(plane->fb); exynos_drm_crtc_commit(crtc); @@ -243,7 +280,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, crtc->fb = fb; ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, - NULL); + old_fb); if (ret) { crtc->fb = old_fb; @@ -254,6 +291,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, goto out; } + + exynos_drm_fb_set_pending(old_fb, false); + exynos_drm_fb_set_pending(fb, true); } out: mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 4ef4cd3..f100035 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -43,11 +43,15 @@ * @fb: drm framebuffer obejct. * @buf_cnt: a buffer count to drm framebuffer. * @exynos_gem_obj: array of exynos specific gem object containing a gem object. + * @pending: indicate whehter a fb was pended by page flip. + * if true, the fb should be released after fbdev is restored to avoid + * accessing invalid memory region. */ struct exynos_drm_fb { struct drm_framebuffer fb; unsigned int buf_cnt; struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; + bool pending; }; static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) @@ -228,6 +232,25 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, return fb; } +void exynos_drm_fb_set_pending(struct drm_framebuffer *fb, bool pending) +{ + struct exynos_drm_fb *exynos_fb; + + exynos_fb = to_exynos_fb(fb); + + exynos_fb->pending = pending; +} + +void exynos_drm_release_pended_fb(struct drm_framebuffer *fb) +{ + struct exynos_drm_fb *exynos_fb; + + exynos_fb = to_exynos_fb(fb); + + if (exynos_fb->pending) + drm_framebuffer_unreference(fb); +} + struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, int index) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h index 96262e5..6b63bb1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h @@ -33,6 +33,12 @@ exynos_drm_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object *obj); +/* set fb->pending variable to desired value. */ +void exynos_drm_fb_set_pending(struct drm_framebuffer *fb, bool pending); + +/* release a fb pended by page flip. */ +void exynos_drm_release_pended_fb(struct drm_framebuffer *fb); + /* get memory information of a drm framebuffer */ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, int index); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index e7466c4..62f3b9e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -314,9 +314,18 @@ void exynos_drm_fbdev_fini(struct drm_device *dev) void exynos_drm_fbdev_restore_mode(struct drm_device *dev) { struct exynos_drm_private *private = dev->dev_private; + struct drm_framebuffer *fb, *fbt; if (!private || !private->fb_helper) return; drm_fb_helper_restore_fbdev_mode(private->fb_helper); + + mutex_lock(&dev->mode_config.mutex); + + /* Release fb pended by page flip. */ + list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) + exynos_drm_release_pended_fb(fb); + + mutex_unlock(&dev->mode_config.mutex); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 862ca1e..37a2f68 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -203,8 +203,24 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret < 0) return ret; - plane->crtc = crtc; + /* + * If this plane already has a fb, unreference the fb. + * + * This means that memory region to the fb isn't accessed by the dma + * of this plane anymore. + */ + if (plane->fb) + drm_framebuffer_unreference(plane->fb); + + /* + * Take a reference to new fb. + * + * Taking a reference means that this plane's dma is going to access + * memory region to the new fb. + */ + drm_framebuffer_reference(fb); + plane->crtc = crtc; exynos_plane_commit(plane); exynos_plane_dpms(plane, DRM_MODE_DPMS_ON);