From patchwork Wed Jul 30 08:34:51 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 4646491 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 5E459C0338 for ; Wed, 30 Jul 2014 08:34:51 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5C10E20138 for ; Wed, 30 Jul 2014 08:34:50 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 68FAA20122 for ; Wed, 30 Jul 2014 08:34:49 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A85EC6E5A3; Wed, 30 Jul 2014 01:34:48 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wi0-f177.google.com (mail-wi0-f177.google.com [209.85.212.177]) by gabe.freedesktop.org (Postfix) with ESMTP id D47AE6E59F for ; Wed, 30 Jul 2014 01:34:46 -0700 (PDT) Received: by mail-wi0-f177.google.com with SMTP id ho1so1883264wib.4 for ; Wed, 30 Jul 2014 01:34:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9v/CzcB82NtY3+2eJXZBTGyj4foZjsrXmSeBKFnneWs=; b=ZKWXnluoZuqmg2TJWsa1gslsEftaGuuvizlKGAM2/MEzwchr4PTUOjSkuljBsL5aY1 C6i3wGwv2PtjaEgbYSziRK6/OORgN/neAS8/apduwUYEVuscSivkRJ9f/1YxMAsCY+Ct BoWoESZBbMYuDzzknIAG0e3piOxNFbNmDDRIY= 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:in-reply-to :references; bh=9v/CzcB82NtY3+2eJXZBTGyj4foZjsrXmSeBKFnneWs=; b=glTi9NfA407+dgPEYDFUVnGIJOKxb4ZrOLq5ymoiFISweAgyS5ncebZ5w6KcjCmTxq PeIR3tWcUYTnXH3jfFdZ40xDefe3ORu1fUorXU/uZKPysHLQZTvTzkglmFyigUYVhDOh Li/BtcDHb7Vq8fax8olggTHHKAQYuHgZ8wWavq/Xc9Azhv/zVZTIHoY2zfntqed+XS+o ezPGlqOd8r3J0wCq2GcxzYSYXpAE5dzgKhaikQ5hsWeg8XAdiokwG8ZH1uPHGIfAWTXe LvgNUt94oeyNdf5o9epKzzZpTILM2rLirRuzIcD6iVYbl3AThLbReSqgU7dBp9WocHQC L31g== X-Gm-Message-State: ALoCoQkaOa2D3DCGL5wsu0/ECFLl0F5xHtzo0q8lmM/+01I63Ovq8Y5kLwpdTzYEw43qHh9pOgq4 X-Received: by 10.180.95.66 with SMTP id di2mr3871387wib.60.1406709285590; Wed, 30 Jul 2014 01:34:45 -0700 (PDT) Received: from phenom.ffwll.local (84-73-67-144.dclient.hispeed.ch. [84.73.67.144]) by mx.google.com with ESMTPSA id j6sm3827983wje.29.2014.07.30.01.34.44 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 30 Jul 2014 01:34:44 -0700 (PDT) From: Daniel Vetter To: DRI Development Subject: [PATCH] drm: Move ->old_fb from crtc to plane Date: Wed, 30 Jul 2014 10:34:51 +0200 Message-Id: <1406709291-32434-1-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 2.0.1 In-Reply-To: <1406669543-31213-5-git-send-email-daniel.vetter@ffwll.ch> References: <1406669543-31213-5-git-send-email-daniel.vetter@ffwll.ch> Cc: Daniel Vetter , Intel Graphics Development , Dave Airlie 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.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,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 Atomic implemenations for legacy ioctls must be able to drop locks. Which doesn't cause havoc since we only do that while constructing the new state, so no driver or hardware state change has happened. The only troubling bit is the fb refcounting the core does - if someone else has snuck in then it might potentially unref an outdated framebuffer. To fix that move the old_fb temporary storage into struct drm_plane for all ioctls, so that the atomic helpers can update it. v2: Fix up the error case handling as suggested by Matt Roper and just grab locks uncoditionally - there's no point in optimizing the locking for when userspace gets it wrong. Cc: Matt Roper Cc: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 46 ++++++++++++++++++++++++---------------------- include/drm/drm_crtc.h | 8 ++++---- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index cb741cd8bfe9..c8f9911bd238 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1200,19 +1200,21 @@ EXPORT_SYMBOL(drm_plane_index); */ void drm_plane_force_disable(struct drm_plane *plane) { - struct drm_framebuffer *old_fb = plane->fb; int ret; - if (!old_fb) + if (!plane->fb) return; + plane->old_fb = plane->fb; ret = plane->funcs->disable_plane(plane); if (ret) { DRM_ERROR("failed to disable plane with busy fb\n"); + plane->old_fb = NULL; return; } /* disconnect the plane from the fb and crtc: */ - __drm_framebuffer_unreference(old_fb); + __drm_framebuffer_unreference(plane->old_fb); + plane->old_fb = NULL; plane->fb = NULL; plane->crtc = NULL; } @@ -2188,23 +2190,21 @@ static int setplane_internal(struct drm_plane *plane, uint32_t src_w, uint32_t src_h) { struct drm_device *dev = plane->dev; - struct drm_framebuffer *old_fb = NULL; int ret = 0; unsigned int fb_width, fb_height; int i; + drm_modeset_lock_all(dev); /* No fb means shut it down */ if (!fb) { - drm_modeset_lock_all(dev); - old_fb = plane->fb; + plane->old_fb = plane->fb; ret = plane->funcs->disable_plane(plane); if (!ret) { plane->crtc = NULL; plane->fb = NULL; } else { - old_fb = NULL; + plane->old_fb = NULL; } - drm_modeset_unlock_all(dev); goto out; } @@ -2244,8 +2244,7 @@ static int setplane_internal(struct drm_plane *plane, goto out; } - drm_modeset_lock_all(dev); - old_fb = plane->fb; + plane->old_fb = plane->fb; ret = plane->funcs->update_plane(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h); @@ -2254,15 +2253,16 @@ static int setplane_internal(struct drm_plane *plane, plane->fb = fb; fb = NULL; } else { - old_fb = NULL; + plane->old_fb = NULL; } - drm_modeset_unlock_all(dev); out: if (fb) drm_framebuffer_unreference(fb); - if (old_fb) - drm_framebuffer_unreference(old_fb); + if (plane->old_fb) + drm_framebuffer_unreference(plane->old_fb); + plane->old_fb = NULL; + drm_modeset_unlock_all(dev); return ret; @@ -2369,7 +2369,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) * crtcs. Atomic modeset will have saner semantics ... */ list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) - tmp->old_fb = tmp->primary->fb; + tmp->primary->old_fb = tmp->primary->fb; fb = set->fb; @@ -2382,8 +2382,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { if (tmp->primary->fb) drm_framebuffer_reference(tmp->primary->fb); - if (tmp->old_fb) - drm_framebuffer_unreference(tmp->old_fb); + if (tmp->primary->old_fb) + drm_framebuffer_unreference(tmp->primary->old_fb); + tmp->primary->old_fb = NULL; } return ret; @@ -4458,7 +4459,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, { struct drm_mode_crtc_page_flip *page_flip = data; struct drm_crtc *crtc; - struct drm_framebuffer *fb = NULL, *old_fb = NULL; + struct drm_framebuffer *fb = NULL; struct drm_pending_vblank_event *e = NULL; unsigned long flags; int ret = -EINVAL; @@ -4530,7 +4531,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, (void (*) (struct drm_pending_event *)) kfree; } - old_fb = crtc->primary->fb; + crtc->primary->old_fb = crtc->primary->fb; ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); if (ret) { if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { @@ -4540,7 +4541,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, kfree(e); } /* Keep the old fb, don't unref it. */ - old_fb = NULL; + crtc->primary->old_fb = NULL; } else { /* * Warn if the driver hasn't properly updated the crtc->fb @@ -4556,8 +4557,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, out: if (fb) drm_framebuffer_unreference(fb); - if (old_fb) - drm_framebuffer_unreference(old_fb); + if (crtc->primary->old_fb) + drm_framebuffer_unreference(crtc->primary->old_fb); + crtc->primary->old_fb = NULL; drm_modeset_unlock_crtc(crtc); return ret; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 8350afe96fa9..8b826ddb7ecb 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -341,10 +341,6 @@ struct drm_crtc { int cursor_x; int cursor_y; - /* Temporary tracking of the old fb while a modeset is ongoing. Used - * by drm_mode_set_config_internal to implement correct refcounting. */ - struct drm_framebuffer *old_fb; - bool enabled; /* Requested mode from modesetting. */ @@ -622,6 +618,10 @@ struct drm_plane { struct drm_crtc *crtc; struct drm_framebuffer *fb; + /* Temporary tracking of the old fb while a modeset is ongoing. Used + * by drm_mode_set_config_internal to implement correct refcounting. */ + struct drm_framebuffer *old_fb; + const struct drm_plane_funcs *funcs; struct drm_object_properties properties;