From patchwork Fri Apr 13 16:53:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10340589 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 50CAC60329 for ; Fri, 13 Apr 2018 16:57:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F1B525EF7 for ; Fri, 13 Apr 2018 16:57:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 33E7E28389; Fri, 13 Apr 2018 16:57:38 +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=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A5E3A25EF7 for ; Fri, 13 Apr 2018 16:57:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E766B6EB6C; Fri, 13 Apr 2018 16:56:35 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id A92C86EB20; Fri, 13 Apr 2018 16:56:25 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:55982 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpa (Exim 4.84_2) (envelope-from ) id 1f71zr-000155-Ng; Fri, 13 Apr 2018 18:56:23 +0200 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Date: Fri, 13 Apr 2018 18:53:46 +0200 Message-Id: <20180413165354.8331-18-noralf@tronnes.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180413165354.8331-1-noralf@tronnes.org> References: <20180413165354.8331-1-noralf@tronnes.org> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC v4 17/25] drm/client: Bail out if there's a DRM master X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org, =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= , laurent.pinchart@ideasonboard.com, mstaudt@suse.de, dh.herrmann@gmail.com Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP If there's a DRM master, return -EBUSY. Block userspace from becoming master by taking the master lock while the client is setting the mode. Suggested-by: Daniel Vetter Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_auth.c | 33 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_client.c | 34 +++++++++++++++++++++++++++++----- drivers/gpu/drm/drm_fb_helper.c | 8 ++++---- drivers/gpu/drm/drm_internal.h | 2 ++ include/drm/drm_client.h | 4 ++-- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index d9c0f7573905..d656d0d93da3 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -366,3 +366,36 @@ void drm_master_put(struct drm_master **master) *master = NULL; } EXPORT_SYMBOL(drm_master_put); + +/** + * drm_master_block - Block DRM master operations + * @dev: DRM device + * + * This function checks if there is a master on @dev. If there is no master it + * blocks anyone from becoming master. In-kernel clients can use this to know + * when they can act as master. Use drm_master_unblock() to unblock. + * + * Returns: + * True if there is no master, false otherwise. + */ +bool drm_master_block(struct drm_device *dev) +{ + mutex_lock(&dev->master_mutex); + if (dev->master) { + mutex_unlock(&dev->master_mutex); + return false; + } + + return true; +} + +/** + * drm_master_unblock - Unblock DRM master operations + * @dev: DRM device + * + * Unblock and allow userspace to become master. + */ +void drm_master_unblock(struct drm_device *dev) +{ + mutex_unlock(&dev->master_mutex); +} diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 27818a467b09..764c556630b8 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -18,6 +18,8 @@ #include #include +#include "drm_internal.h" + struct drm_client_display_offset { int x, y; }; @@ -313,18 +315,30 @@ static int drm_client_display_restore_legacy(struct drm_client_display *display) /** * drm_client_display_restore() - Restore client display * @display: Client display + * @force: If true, restore even if there's a DRM master * * Restore client display using the current modeset configuration. * * Return: * Zero on succes or negative error code on failure. */ -int drm_client_display_restore(struct drm_client_display *display) +int drm_client_display_restore(struct drm_client_display *display, bool force) { - if (drm_drv_uses_atomic_modeset(display->dev)) - return drm_client_display_restore_atomic(display, true); + struct drm_device *dev = display->dev; + int ret; + + if (!force && !drm_master_block(dev)) + return -EBUSY; + + if (drm_drv_uses_atomic_modeset(dev)) + ret = drm_client_display_restore_atomic(display, true); else - return drm_client_display_restore_legacy(display); + ret = drm_client_display_restore_legacy(display); + + if (!force) + drm_master_unblock(dev); + + return ret; } EXPORT_SYMBOL(drm_client_display_restore); @@ -354,13 +368,23 @@ static void drm_client_display_dpms_legacy(struct drm_client_display *display, i * drm_client_display_dpms() - Set display DPMS mode * @display: Client display * @mode: DPMS mode + * + * Returns: + * Zero on success, -EBUSY if there's a DRM master. */ -void drm_client_display_dpms(struct drm_client_display *display, int mode) +int drm_client_display_dpms(struct drm_client_display *display, int mode) { + if (!drm_master_block(display->dev)) + return -EBUSY; + if (drm_drv_uses_atomic_modeset(display->dev)) drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON); else drm_client_display_dpms_legacy(display, mode); + + drm_master_unblock(display->dev); + + return 0; } EXPORT_SYMBOL(drm_client_display_dpms); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 01d8840930a3..98e5bc92c9f2 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -181,7 +181,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) return 0; mutex_lock(&fb_helper->lock); - ret = drm_client_display_restore(fb_helper->display); + ret = drm_client_display_restore(fb_helper->display, false); do_delayed = fb_helper->delayed_hotplug; if (do_delayed) @@ -243,7 +243,7 @@ static bool drm_fb_helper_force_kernel_mode(void) continue; mutex_lock(&helper->lock); - ret = drm_client_display_restore(helper->display); + ret = drm_client_display_restore(helper->display, true); if (ret) error = true; mutex_unlock(&helper->lock); @@ -1254,7 +1254,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var, pan_set(fb_helper, var->xoffset, var->yoffset); - ret = drm_client_display_restore(fb_helper->display); + ret = drm_client_display_restore(fb_helper->display, false); if (!ret) { info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; @@ -1423,7 +1423,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, /* First time: disable all crtc's.. */ if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master)) - drm_client_display_restore(fb_helper->display); + drm_client_display_restore(fb_helper->display, false); return -EAGAIN; } diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 3f5d7706bcc9..f38dcaf139d7 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -92,6 +92,8 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int drm_master_open(struct drm_file *file_priv); void drm_master_release(struct drm_file *file_priv); +bool drm_master_block(struct drm_device *dev); +void drm_master_unblock(struct drm_device *dev); /* drm_sysfs.c */ extern struct class *drm_class; diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 27d2a46cd94a..3befd879a0b0 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -46,8 +46,8 @@ drm_client_display_find_modeset(struct drm_client_display *display, struct drm_c bool drm_client_display_panel_rotation(struct drm_connector *connector, struct drm_plane *plane, unsigned int *rotation); -int drm_client_display_restore(struct drm_client_display *display); -void drm_client_display_dpms(struct drm_client_display *display, int mode); +int drm_client_display_restore(struct drm_client_display *display, bool force); +int drm_client_display_dpms(struct drm_client_display *display, int mode); struct drm_client_display * drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned int height);