From patchwork Mon Sep 15 18:52:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Drake X-Patchwork-Id: 4907401 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 77D2F9F349 for ; Mon, 15 Sep 2014 18:49:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4AAE320219 for ; Mon, 15 Sep 2014 18:52:32 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id B7078201BF for ; Mon, 15 Sep 2014 18:52:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C84736E2CB; Mon, 15 Sep 2014 11:52:29 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-yh0-f54.google.com (mail-yh0-f54.google.com [209.85.213.54]) by gabe.freedesktop.org (Postfix) with ESMTP id 793166E2CB for ; Mon, 15 Sep 2014 11:52:28 -0700 (PDT) Received: by mail-yh0-f54.google.com with SMTP id z6so2309557yhz.13 for ; Mon, 15 Sep 2014 11:52:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=YgjNwaED0Hem0KYuaCM5B+yHAISowRSgzfVtmDXJf3Y=; b=nLa160POvdb87Z6PXz37sdc2feQq5ni18LJtATDhJmgp7Yex/LBzMPKxziyc6DDCVR 4/R/WCmuADdxvfS3/J9qLoVeaXfEr6180iHTMdo45ebM8YmXE9RcfhNd/UvH+AMk7YNJ psYz1XFHbXfQQRDe5OElWNctgkuBqFn4829GjepyfrqOA0JznOqBmetdMNhHks4QSNoT naIo9QfMkac4hXrXnaHhxmFYF3/hnwaqJXLQ3mYG2PFCczIGGY4224/TesTsGmD1OMNv gGpBJWujgONWnbdt9uFploJBGYFEi8rRMigwZK8Yj7y6pJk7QsdFonchm5X7I13KfyxO kZ0g== X-Gm-Message-State: ALoCoQlKNNQFHbk3uC2Y7GRcjWN/s/RTZLOJMp98BGKQ9ygCiOeZuO6LLJDlt2r5A1c5C4S3QbRB X-Received: by 10.236.190.133 with SMTP id e5mr36369007yhn.13.1410807147625; Mon, 15 Sep 2014 11:52:27 -0700 (PDT) Received: from dsd-ubuntu.gallo.pinto ([190.181.183.137]) by mx.google.com with ESMTPSA id g22sm5555558yhb.18.2014.09.15.11.52.24 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 15 Sep 2014 11:52:26 -0700 (PDT) From: Daniel Drake To: inki.dae@samsung.com, jy0922.shim@samsung.com, sw0312.kim@samsung.com, kyungmin.park@samsung.com Subject: [PATCH] drm/exynos: fix plane-framebuffer linkage Date: Mon, 15 Sep 2014 12:52:17 -0600 Message-Id: <1410807137-8323-1-git-send-email-drake@endlessm.com> X-Mailer: git-send-email 1.9.1 Cc: a.hajda@samsung.com, linux-samsung-soc@vger.kernel.org, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Pageflipping currently causes some inconsistencies that lead to crashes. Just run an app that causes a CRTC pageflip in a raw X session and check that it exits cleanly and can be restarted - you'll see crashes like: Unable to handle kernel NULL pointer dereference at virtual address 00000334 PC is at exynos_drm_crtc_plane_commit+0x20/0x40 LR is at exynos_drm_crtc_plane_commit+0x20/0x40 [] (exynos_drm_crtc_plane_commit) from [] (exynos_drm_crtc_commit+0x44/0x70) [] (exynos_drm_crtc_commit) from [] (exynos_drm_crtc_mode_set_commit.isra.2+0xb4/0xc4) [] (exynos_drm_crtc_mode_set_commit.isra.2) from [] (exynos_drm_crtc_page_flip+0x140/0x1a8) [] (exynos_drm_crtc_page_flip) from [] (drm_mode_page_flip_ioctl+0x224/0x2dc) [] (drm_mode_page_flip_ioctl) from [] (drm_ioctl+0x338/0x4fc) These crashes happen because drm_plane_force_disable has previously set plane->crtc to NULL. When drm_mode_page_flip_ioctl() is used to flip another framebuffer onto the primary plane, crtc->primary->fb is correctly updated (this is a virtual plane created by plane_helper), but plane->fb is not (this plane is the real one, created by exynos_drm_crtc_create). We then come to handle rmfb of the backbuffer, which the "real" primary plane is incorrectly pointing at. So drm_framebuffer_remove() decides that the buffer is actually active on a plane and force-disables the plane. Ensuring that plane->fb is kept up-to-date solves that issue, but exposes a reference counting problem. Now we see crashes when rmfb is called on the front-buffer, because the rmfb code expects to drop 3 references here, and there are only 2. That can be fixed by adopting the reference management found in omapdrm: Framebuffer references are not taken directly in crtc mode_set context, but rather in the context of updating the plane, which also covers flips. Like omapdrm we also unreference the old framebuffer here. Signed-off-by: Daniel Drake --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 12 ++---------- drivers/gpu/drm/exynos/exynos_drm_plane.c | 8 ++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index b68e58f..7aa9dee 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -140,16 +140,8 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, if (manager->ops->mode_set) manager->ops->mode_set(manager, &crtc->mode); - ret = exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, crtc_w, crtc_h, - x, y, crtc_w, crtc_h); - if (ret) - return ret; - - plane->crtc = crtc; - plane->fb = crtc->primary->fb; - drm_framebuffer_reference(plane->fb); - - return 0; + return exynos_plane_mode_set(plane, crtc, crtc->primary->fb, 0, 0, + crtc_w, crtc_h, x, y, crtc_w, crtc_h); } static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 8371cbd..df27e35 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -139,6 +139,14 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, overlay->crtc_x, overlay->crtc_y, overlay->crtc_width, overlay->crtc_height); + if (plane->fb) + drm_framebuffer_unreference(plane->fb); + + drm_framebuffer_reference(fb); + + plane->fb = fb; + plane->crtc = crtc; + exynos_drm_crtc_plane_mode_set(crtc, overlay); return 0;