Received: by 10.213.65.68 with SMTP id h4csp132678imn; Tue, 27 Mar 2018 23:57:35 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+1WkfhA27Jfi7KMd9Bdz2L++8TORRdJk7vxTXjlaoWD7g5jHYOqB8zWM22EFtpfBnGmxq7 X-Received: by 2002:a17:902:534f:: with SMTP id b73-v6mr2533092pli.148.1522220255066; Tue, 27 Mar 2018 23:57:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522220255; cv=none; d=google.com; s=arc-20160816; b=eFj+zuM/50pUQ4MWRCPSb9s+l/OX8V5AGrbWVDuil97yYrsAz2+GQPS9c1/71u2fFR 5YAdeU5fmTfxo929piJ49GwJSPxJEfPjZ9lMnBU0O2pfS0oa7hMCOqI09fQr3R9dV0IR N6wyyAAl96erCNkQs9VCyylGxe5yjU/YLZWmeFvUw/UCmSZpVN6JRdLYXnqxp0KpCiK+ 1tWL5mgOIOir0MNQBGB53nMgat0P+Hyqn17TP24P+jJzdRAcKCibXIFpMUu30ZxU6gJk j8NqH3PqDLH9IWmWpXf9w3uB94bDeukXFItIzD9tfacVklPS9crKIFNmKzumkVDbVKYV bW9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=0ITn2xmNMQrbObMW0PcUgdhrYxHSSz1uouzF6123nvo=; b=nPgZ1WuW/326bQXvNy44b4tESvW94K/e9ovaxniBI6x30lTm8A4LY8CMoKqQaN796T EaBfC+rN7TAah0E7eAPIez5iHUOI169Z7kwwLpsYxQ1FOFxyTYGx9XcoupwV/F6nRHdu l9Elib6iaRrFS59ygvAvVOQp0nM/NdtA2h5wPcGCX4ONKr1JyKb1JNssGAIqQXZBJMe4 risPCbrlikSvEtO1U3vCdBEsOlNk2q5f/4P73yE9AUZ7MuqFL9xICMHwgxULLY1iwlaa crrgGH7Lt6Yu+H1h6pR0MoL+Nil9biumwDPefYN50WZcanhtp8ki/RiG+9COcm3WJ2wj aw8A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ENbYh83x; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l64si1393348pga.342.2018.03.27.23.57.21; Tue, 27 Mar 2018 23:57:35 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ENbYh83x; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752925AbeC1Gr4 (ORCPT + 99 others); Wed, 28 Mar 2018 02:47:56 -0400 Received: from mail-lf0-f67.google.com ([209.85.215.67]:33383 "EHLO mail-lf0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752390AbeC1Grw (ORCPT ); Wed, 28 Mar 2018 02:47:52 -0400 Received: by mail-lf0-f67.google.com with SMTP id x205-v6so1892064lfa.0 for ; Tue, 27 Mar 2018 23:47:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0ITn2xmNMQrbObMW0PcUgdhrYxHSSz1uouzF6123nvo=; b=ENbYh83xIadglpcRqxpcSyNBRRiF0B925KC1FV1GAoXjtOkl4/ObTh3yQK8QsSffc8 goT+d12NkbSum601zTTayVhjuKiktqG7xLkUMoUoYyDagyKgN2dm0YeivGiCgQGOWdar 3r3xIADXoauiMQN0oh8dUERS899LFlXLsMHg4OzjRTqSfLMnzCyV0z+DSVltqvDGEGmQ Py8Lj0yl8FEUcQwuVHsPFkLvtxguBs0oqm/Lb2TVvuwqpp9krfaZkXEFD+XzyhZ11qlL rxnG4LelIFPeYUWewMVS0hi+tkfaGFEcaiHWjFzdT/QIzeZebgCM3NjxH1esIOc4mO6b bzdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0ITn2xmNMQrbObMW0PcUgdhrYxHSSz1uouzF6123nvo=; b=r+aFA/VR3wfBbXSboreBzO1pFwnPrU3Lq1IrTvyQClxrHW0xCyCeNyLyKsHt2S2sQL 6olz3H5WkwoYbL+1OBJJeMHLN6SEkX5MJhU9mv1uoIgp5QcLTxgHa7plqv6nA8xwfLyq Z6Yd8EldCcUxrnJqdUG0Jh8mrW00ZrsnACu2NwlzBSRJn7S2Da+CJbxkIEoTbjp3wE0C KMPq82iYedYkwkhTBLfZfvJF0+UxCFfFQG1Go9k/exFZ8Lp3MjvDlJjkwtya9FgKqrjn ei7F+kmb/74r/+ocUI26MAlTm/bGMnenw2dxiO0Ddi9bkO51kTcoTCtswsbwGh+o2Dbi HFjg== X-Gm-Message-State: AElRT7Grr1HmwoSxa4LRcwjugy+O2Px1QofOF0ecsHVNFb5TsuOSLixN gWX8n8VNHx4AnRbJ2ReuM3c= X-Received: by 2002:a19:cf89:: with SMTP id f131-v6mr1430478lfg.130.1522219671285; Tue, 27 Mar 2018 23:47:51 -0700 (PDT) Received: from a2k-HP-ProDesk-600-G2-SFF.kyiv.epam.com (ll-55.209.223.85.sovam.net.ua. [85.223.209.55]) by smtp.gmail.com with ESMTPSA id x70-v6sm546081lfd.82.2018.03.27.23.47.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 27 Mar 2018 23:47:50 -0700 (PDT) From: Oleksandr Andrushchenko To: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, airlied@linux.ie, daniel.vetter@intel.com, seanpaul@chromium.org, gustavo@padovan.org, jgross@suse.com, boris.ostrovsky@oracle.com, konrad.wilk@oracle.com Cc: andr2000@gmail.com, =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= , intel-gfx@lists.freedesktop.org Subject: [PATCH v4 1/2] drm: Use srcu to protect drm_device.unplugged Date: Wed, 28 Mar 2018 09:47:40 +0300 Message-Id: <1522219661-26827-2-git-send-email-andr2000@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1522219661-26827-1-git-send-email-andr2000@gmail.com> References: <1522219661-26827-1-git-send-email-andr2000@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Noralf Trønnes Use srcu to protect drm_device.unplugged in a race free manner. Drivers can use drm_dev_enter()/drm_dev_exit() to protect and mark sections preventing access to device resources that are not available after the device is gone. Suggested-by: Daniel Vetter Signed-off-by: Noralf Trønnes Reviewed-by: Oleksandr Andrushchenko Tested-by: Oleksandr Andrushchenko Cc: intel-gfx@lists.freedesktop.org --- drivers/gpu/drm/drm_drv.c | 54 ++++++++++++++++++++++++++++++++++++++++++----- include/drm/drm_device.h | 9 +++++++- include/drm/drm_drv.h | 15 +++++++++---- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index a1b9338736e3..32a83b41ab61 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,8 @@ static bool drm_core_init_complete = false; static struct dentry *drm_debugfs_root; +DEFINE_STATIC_SRCU(drm_unplug_srcu); + /* * DRM Minors * A DRM device can provide several char-dev interfaces on the DRM-Major. Each @@ -318,18 +321,51 @@ void drm_put_dev(struct drm_device *dev) } EXPORT_SYMBOL(drm_put_dev); -static void drm_device_set_unplugged(struct drm_device *dev) +/** + * drm_dev_enter - Enter device critical section + * @dev: DRM device + * @idx: Pointer to index that will be passed to the matching drm_dev_exit() + * + * This function marks and protects the beginning of a section that should not + * be entered after the device has been unplugged. The section end is marked + * with drm_dev_exit(). Calls to this function can be nested. + * + * Returns: + * True if it is OK to enter the section, false otherwise. + */ +bool drm_dev_enter(struct drm_device *dev, int *idx) +{ + *idx = srcu_read_lock(&drm_unplug_srcu); + + if (dev->unplugged) { + srcu_read_unlock(&drm_unplug_srcu, *idx); + return false; + } + + return true; +} +EXPORT_SYMBOL(drm_dev_enter); + +/** + * drm_dev_exit - Exit device critical section + * @idx: index returned from drm_dev_enter() + * + * This function marks the end of a section that should not be entered after + * the device has been unplugged. + */ +void drm_dev_exit(int idx) { - smp_wmb(); - atomic_set(&dev->unplugged, 1); + srcu_read_unlock(&drm_unplug_srcu, idx); } +EXPORT_SYMBOL(drm_dev_exit); /** * drm_dev_unplug - unplug a DRM device * @dev: DRM device * * This unplugs a hotpluggable DRM device, which makes it inaccessible to - * userspace operations. Entry-points can use drm_dev_is_unplugged(). This + * userspace operations. Entry-points can use drm_dev_enter() and + * drm_dev_exit() to protect device resources in a race free manner. This * essentially unregisters the device like drm_dev_unregister(), but can be * called while there are still open users of @dev. */ @@ -338,10 +374,18 @@ void drm_dev_unplug(struct drm_device *dev) drm_dev_unregister(dev); mutex_lock(&drm_global_mutex); - drm_device_set_unplugged(dev); if (dev->open_count == 0) drm_dev_put(dev); mutex_unlock(&drm_global_mutex); + + /* + * After synchronizing any critical read section is guaranteed to see + * the new value of ->unplugged, and any critical section which might + * still have seen the old value of ->unplugged is guaranteed to have + * finished. + */ + dev->unplugged = true; + synchronize_srcu(&drm_unplug_srcu); } EXPORT_SYMBOL(drm_dev_unplug); diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 7c4fa32f3fc6..3a0eac2885b7 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -46,7 +46,14 @@ struct drm_device { /* currently active master for this device. Protected by master_mutex */ struct drm_master *master; - atomic_t unplugged; /**< Flag whether dev is dead */ + /** + * @unplugged: + * + * Flag to tell if the device has been unplugged. + * See drm_dev_enter() and drm_dev_is_unplugged(). + */ + bool unplugged; + struct inode *anon_inode; /**< inode for private address-space */ char *unique; /**< unique name of the device */ /*@} */ diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index d23dcdd1bd95..7e545f5f94d3 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -624,6 +624,8 @@ void drm_dev_get(struct drm_device *dev); void drm_dev_put(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev); void drm_put_dev(struct drm_device *dev); +bool drm_dev_enter(struct drm_device *dev, int *idx); +void drm_dev_exit(int idx); void drm_dev_unplug(struct drm_device *dev); /** @@ -635,11 +637,16 @@ void drm_dev_unplug(struct drm_device *dev); * unplugged, these two functions guarantee that any store before calling * drm_dev_unplug() is visible to callers of this function after it completes */ -static inline int drm_dev_is_unplugged(struct drm_device *dev) +static inline bool drm_dev_is_unplugged(struct drm_device *dev) { - int ret = atomic_read(&dev->unplugged); - smp_rmb(); - return ret; + int idx; + + if (drm_dev_enter(dev, &idx)) { + drm_dev_exit(idx); + return false; + } + + return true; } -- 2.7.4