From patchwork Tue Jan 26 21:46:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048397 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D988FC433E0 for ; Tue, 26 Jan 2021 21:44:47 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A0B8E20656 for ; Tue, 26 Jan 2021 21:44:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A0B8E20656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8BF3889AC6; Tue, 26 Jan 2021 21:44:39 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id D3FFB6E171; Tue, 26 Jan 2021 21:44:37 +0000 (UTC) IronPort-SDR: czDphdFDFSSebhkpN1AfIxsFWFVeVVre7XpD+ZiomSwypPelfgYXXEbLx2y5GMn87JQ+B+cjFT BpCUb8ws9GMA== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770827" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770827" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: jB94TEEMFBkJrl7atXpKz+il2NJU9Q8ef60DYeuRMlLjJ1PRfvZy1XoNdkK7mqYeAUktlL3zX+ GDY761QES78A== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139884" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:36 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:18 -0800 Message-Id: <20210126214626.16260-2-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 1/9] cgroup: Introduce cgroup for drm subsystem X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Kenny Ho With the increased importance of machine learning, data science and other cloud-based applications, GPUs are already in production use in data centers today. Existing GPU resource management is very coarse grain, however, as sysadmins are only able to distribute workload on a per-GPU basis. An alternative is to use GPU virtualization (with or without SRIOV) but it generally acts on the entire GPU instead of the specific resources in a GPU. With a drm cgroup controller, we can enable alternate, fine-grain, sub-GPU resource management (in addition to what may be available via GPU virtualization.) Signed-off-by: Kenny Ho --- Documentation/admin-guide/cgroup-v2.rst | 18 ++++- Documentation/cgroup-v1/drm.rst | 1 + include/linux/cgroup_drm.h | 92 +++++++++++++++++++++++++ include/linux/cgroup_subsys.h | 4 ++ init/Kconfig | 5 ++ kernel/cgroup/Makefile | 1 + kernel/cgroup/drm.c | 42 +++++++++++ 7 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 Documentation/cgroup-v1/drm.rst create mode 100644 include/linux/cgroup_drm.h create mode 100644 kernel/cgroup/drm.c diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index 63521cd36ce5..b099e1d71098 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -63,8 +63,10 @@ v1 is available under :ref:`Documentation/admin-guide/cgroup-v1/index.rst + +#ifdef CONFIG_CGROUP_DRM + +/** + * The DRM cgroup controller data structure. + */ +struct drmcg { + struct cgroup_subsys_state css; +}; + +/** + * css_to_drmcg - get the corresponding drmcg ref from a cgroup_subsys_state + * @css: the target cgroup_subsys_state + * + * Return: DRM cgroup that contains the @css + */ +static inline struct drmcg *css_to_drmcg(struct cgroup_subsys_state *css) +{ + return css ? container_of(css, struct drmcg, css) : NULL; +} + +/** + * drmcg_get - get the drmcg reference that a task belongs to + * @task: the target task + * + * This increase the reference count of the css that the @task belongs to + * + * Return: reference to the DRM cgroup the task belongs to + */ +static inline struct drmcg *drmcg_get(struct task_struct *task) +{ + return css_to_drmcg(task_get_css(task, gpu_cgrp_id)); +} + +/** + * drmcg_put - put a drmcg reference + * @drmcg: the target drmcg + * + * Put a reference obtained via drmcg_get + */ +static inline void drmcg_put(struct drmcg *drmcg) +{ + if (drmcg) + css_put(&drmcg->css); +} + +/** + * drmcg_parent - find the parent of a drm cgroup + * @cg: the target drmcg + * + * This does not increase the reference count of the parent cgroup + * + * Return: parent DRM cgroup of @cg + */ +static inline struct drmcg *drmcg_parent(struct drmcg *cg) +{ + return css_to_drmcg(cg->css.parent); +} + +#else /* CONFIG_CGROUP_DRM */ + +struct drmcg { +}; + +static inline struct drmcg *css_to_drmcg(struct cgroup_subsys_state *css) +{ + return NULL; +} + +static inline struct drmcg *drmcg_get(struct task_struct *task) +{ + return NULL; +} + +static inline void drmcg_put(struct drmcg *drmcg) +{ +} + +static inline struct drmcg *drmcg_parent(struct drmcg *cg) +{ + return NULL; +} + +#endif /* CONFIG_CGROUP_DRM */ +#endif /* _CGROUP_DRM_H */ diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index acb77dcff3b4..f4e627942115 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -61,6 +61,10 @@ SUBSYS(pids) SUBSYS(rdma) #endif +#if IS_ENABLED(CONFIG_CGROUP_DRM) +SUBSYS(gpu) +#endif + /* * The following subsystems are not supported on the default hierarchy. */ diff --git a/init/Kconfig b/init/Kconfig index b77c60f8b963..bee29f51e380 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1027,6 +1027,11 @@ config CGROUP_RDMA Attaching processes with active RDMA resources to the cgroup hierarchy is allowed even if can cross the hierarchy's limit. +config CGROUP_DRM + bool "DRM controller (EXPERIMENTAL)" + help + Provides accounting and enforcement of resources in the DRM subsystem. + config CGROUP_FREEZER bool "Freezer controller" help diff --git a/kernel/cgroup/Makefile b/kernel/cgroup/Makefile index 5d7a76bfbbb7..31f186f58121 100644 --- a/kernel/cgroup/Makefile +++ b/kernel/cgroup/Makefile @@ -4,5 +4,6 @@ obj-y := cgroup.o rstat.o namespace.o cgroup-v1.o freezer.o obj-$(CONFIG_CGROUP_FREEZER) += legacy_freezer.o obj-$(CONFIG_CGROUP_PIDS) += pids.o obj-$(CONFIG_CGROUP_RDMA) += rdma.o +obj-$(CONFIG_CGROUP_DRM) += drm.o obj-$(CONFIG_CPUSETS) += cpuset.o obj-$(CONFIG_CGROUP_DEBUG) += debug.o diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c new file mode 100644 index 000000000000..5e38a8230922 --- /dev/null +++ b/kernel/cgroup/drm.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +// Copyright 2019 Advanced Micro Devices, Inc. +#include +#include +#include + +static struct drmcg *root_drmcg __read_mostly; + +static void drmcg_css_free(struct cgroup_subsys_state *css) +{ + struct drmcg *drmcg = css_to_drmcg(css); + + kfree(drmcg); +} + +static struct cgroup_subsys_state * +drmcg_css_alloc(struct cgroup_subsys_state *parent_css) +{ + struct drmcg *parent = css_to_drmcg(parent_css); + struct drmcg *drmcg; + + drmcg = kzalloc(sizeof(struct drmcg), GFP_KERNEL); + if (!drmcg) + return ERR_PTR(-ENOMEM); + + if (!parent) + root_drmcg = drmcg; + + return &drmcg->css; +} + +struct cftype files[] = { + { } /* terminate */ +}; + +struct cgroup_subsys gpu_cgrp_subsys = { + .css_alloc = drmcg_css_alloc, + .css_free = drmcg_css_free, + .early_init = false, + .legacy_cftypes = files, + .dfl_cftypes = files, +}; From patchwork Tue Jan 26 21:46:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048399 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4CE17C433E9 for ; Tue, 26 Jan 2021 21:44:50 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1709920656 for ; Tue, 26 Jan 2021 21:44:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1709920656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 87D2E6E49C; Tue, 26 Jan 2021 21:44:40 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4914F6E171; Tue, 26 Jan 2021 21:44:38 +0000 (UTC) IronPort-SDR: 78/eRlEvNkkR8qf7PBlMeKsmzGXEHeBH5z3/1c14GMoeENQHKjov/NWVSDUyOPeacEAPKIILP0 fnkuCkdZ8JTQ== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770828" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770828" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: tIdx5mzUYWnmP9Naq10L31XyFyKJMLQZTtXw82/SLdxN/7YkQ4w8MmNV01yngExONP6ZgG/XHX VLknynncDPPQ== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139887" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:19 -0800 Message-Id: <20210126214626.16260-3-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 2/9] drm, cgroup: Bind drm and cgroup subsystem X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Kenny Ho Since the drm subsystem can be compiled as a module and drm devices can be added and removed during run time, add several functions to bind the drm subsystem as well as drm devices with drmcg. Two pairs of functions: drmcg_bind/drmcg_unbind - used to bind/unbind the drm subsystem to the cgroup subsystem as the drm core initialize/exit. drmcg_register_dev/drmcg_unregister_dev - used to register/unregister drm devices to the cgroup subsystem as the devices are presented/removed from userspace. Signed-off-by: Kenny Ho --- drivers/gpu/drm/drm_drv.c | 8 +++ include/drm/drm_cgroup.h | 39 +++++++++++ include/linux/cgroup_drm.h | 4 ++ kernel/cgroup/drm.c | 131 +++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 include/drm/drm_cgroup.h diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 20d22e41d7ce..3b940926d672 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -893,6 +894,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_register_all(dev); + drmcg_register_dev(dev); + DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, @@ -928,6 +931,8 @@ EXPORT_SYMBOL(drm_dev_register); */ void drm_dev_unregister(struct drm_device *dev) { + drmcg_unregister_dev(dev); + if (drm_core_check_feature(dev, DRIVER_LEGACY)) drm_lastclose(dev); @@ -1030,6 +1035,7 @@ static const struct file_operations drm_stub_fops = { static void drm_core_exit(void) { + drmcg_unbind(); unregister_chrdev(DRM_MAJOR, "drm"); debugfs_remove(drm_debugfs_root); drm_sysfs_destroy(); @@ -1056,6 +1062,8 @@ static int __init drm_core_init(void) if (ret < 0) goto error; + drmcg_bind(&drm_minor_acquire, &drm_dev_put); + drm_core_init_complete = true; DRM_DEBUG("Initialized\n"); diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h new file mode 100644 index 000000000000..530c9a0b3238 --- /dev/null +++ b/include/drm/drm_cgroup.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: MIT + * Copyright 2019 Advanced Micro Devices, Inc. + */ +#ifndef __DRM_CGROUP_H__ +#define __DRM_CGROUP_H__ + +#ifdef CONFIG_CGROUP_DRM + +void drmcg_bind(struct drm_minor (*(*acq_dm)(unsigned int minor_id)), + void (*put_ddev)(struct drm_device *dev)); + +void drmcg_unbind(void); + +void drmcg_register_dev(struct drm_device *dev); + +void drmcg_unregister_dev(struct drm_device *dev); + +#else + +static inline void drmcg_bind( + struct drm_minor (*(*acq_dm)(unsigned int minor_id)), + void (*put_ddev)(struct drm_device *dev)) +{ +} + +static inline void drmcg_unbind(void) +{ +} + +static inline void drmcg_register_dev(struct drm_device *dev) +{ +} + +static inline void drmcg_unregister_dev(struct drm_device *dev) +{ +} + +#endif /* CONFIG_CGROUP_DRM */ +#endif /* __DRM_CGROUP_H__ */ diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h index 345af54a5d41..307bb75db248 100644 --- a/include/linux/cgroup_drm.h +++ b/include/linux/cgroup_drm.h @@ -5,6 +5,10 @@ #define _CGROUP_DRM_H #include +#include + +/* limit defined per the way drm_minor_alloc operates */ +#define MAX_DRM_DEV (64 * DRM_MINOR_RENDER) #ifdef CONFIG_CGROUP_DRM diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index 5e38a8230922..061bb9c458e4 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -1,11 +1,142 @@ // SPDX-License-Identifier: MIT // Copyright 2019 Advanced Micro Devices, Inc. +#include +#include #include #include #include +#include +#include +#include static struct drmcg *root_drmcg __read_mostly; +/* global mutex for drmcg across all devices */ +static DEFINE_MUTEX(drmcg_mutex); + +static DECLARE_BITMAP(known_devs, MAX_DRM_DEV); + +static struct drm_minor (*(*acquire_drm_minor)(unsigned int minor_id)); + +static void (*put_drm_dev)(struct drm_device *dev); + +/** + * drmcg_bind - Bind DRM subsystem to cgroup subsystem + * @acq_dm: function pointer to the drm_minor_acquire function + * @put_ddev: function pointer to the drm_dev_put function + * + * This function binds some functions from the DRM subsystem and make + * them available to the drmcg subsystem. + * + * drmcg_unbind does the opposite of this function + */ +void drmcg_bind(struct drm_minor (*(*acq_dm)(unsigned int minor_id)), + void (*put_ddev)(struct drm_device *dev)) +{ + mutex_lock(&drmcg_mutex); + acquire_drm_minor = acq_dm; + put_drm_dev = put_ddev; + mutex_unlock(&drmcg_mutex); +} +EXPORT_SYMBOL(drmcg_bind); + +/** + * drmcg_unbind - Unbind DRM subsystem from cgroup subsystem + * + * drmcg_bind does the opposite of this function + */ +void drmcg_unbind(void) +{ + mutex_lock(&drmcg_mutex); + acquire_drm_minor = NULL; + put_drm_dev = NULL; + mutex_unlock(&drmcg_mutex); +} +EXPORT_SYMBOL(drmcg_unbind); + +/** + * drmcg_register_dev - register a DRM device for usage in drm cgroup + * @dev: DRM device + * + * This function make a DRM device visible to the cgroup subsystem. + * Once the drmcg is aware of the device, drmcg can start tracking and + * control resource usage for said device. + * + * drmcg_unregister_dev reverse the operation of this function + */ +void drmcg_register_dev(struct drm_device *dev) +{ + if (WARN_ON(dev->primary->index >= MAX_DRM_DEV)) + return; + + mutex_lock(&drmcg_mutex); + set_bit(dev->primary->index, known_devs); + mutex_unlock(&drmcg_mutex); +} +EXPORT_SYMBOL(drmcg_register_dev); + +/** + * drmcg_unregister_dev - Iterate through all stored DRM minors + * @dev: DRM device + * + * Unregister @dev so that drmcg no longer control resource usage + * of @dev. The @dev was registered to drmcg using + * drmcg_register_dev function + */ +void drmcg_unregister_dev(struct drm_device *dev) +{ + if (WARN_ON(dev->primary->index >= MAX_DRM_DEV)) + return; + + mutex_lock(&drmcg_mutex); + clear_bit(dev->primary->index, known_devs); + mutex_unlock(&drmcg_mutex); +} +EXPORT_SYMBOL(drmcg_unregister_dev); + +/** + * drm_minor_for_each - Iterate through all stored DRM minors + * @fn: Function to be called for each pointer. + * @data: Data passed to callback function. + * + * The callback function will be called for each registered device, passing + * the minor, the @drm_minor entry and @data. + * + * If @fn returns anything other than %0, the iteration stops and that + * value is returned from this function. + */ +static int drm_minor_for_each(int (*fn)(int id, void *p, void *data), + void *data) +{ + int rc = 0; + + mutex_lock(&drmcg_mutex); + if (acquire_drm_minor) { + unsigned int minor; + struct drm_minor *dm; + + minor = find_next_bit(known_devs, MAX_DRM_DEV, 0); + while (minor < MAX_DRM_DEV) { + dm = acquire_drm_minor(minor); + + if (IS_ERR(dm)) + continue; + + rc = fn(minor, (void *)dm, data); + + put_drm_dev(dm->dev); /* release from acquire_drm_minor */ + + if (rc) + break; + + minor = find_next_bit(known_devs, MAX_DRM_DEV, minor+1); + } + } + mutex_unlock(&drmcg_mutex); + + return rc; +} + static void drmcg_css_free(struct cgroup_subsys_state *css) { struct drmcg *drmcg = css_to_drmcg(css); From patchwork Tue Jan 26 21:46:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048403 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70F4AC433DB for ; Tue, 26 Jan 2021 21:45:00 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2747320684 for ; Tue, 26 Jan 2021 21:45:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2747320684 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3743C6E4B0; Tue, 26 Jan 2021 21:44:41 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7C1F96E441; Tue, 26 Jan 2021 21:44:38 +0000 (UTC) IronPort-SDR: zpmRRWNsv2ZC3MT+/wJ578z7Xf0F+pNStj05QtsZwZvhO/BuUk3FjW9HIks0F+BjnbEr8Qkedz T7UV6k1LjJUA== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770829" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770829" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: 2ae6tLysyhXYthrpXKJY7bn1HEolCNzb8kVzjeOw1gYWAb9q6U2u4NBMDYgFtUTNzIk+XORYCO RuLb09byOB9A== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139891" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:20 -0800 Message-Id: <20210126214626.16260-4-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 3/9] drm, cgroup: Initialize drmcg properties X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Kenny Ho drmcg initialization involves allocating a per cgroup, per device data structure and setting the defaults. There are two entry points for drmcg init: 1) When struct drmcg is created via css_alloc, initialization is done for each device 2) When DRM devices are created after drmcgs are created, per device drmcg data structure is allocated at the beginning of DRM device creation such that drmcg can begin tracking usage statistics Entry point #2 usually applies to the root cgroup since it can be created before DRM devices are available. The drmcg controller will go through all existing drm cgroups and initialize them with the new device accordingly. Extending Kenny's original work, this has been simplified some and the custom_init callback has been removed. (Brian) Signed-off-by Kenny Ho Signed-off-by: Brian Welty --- drivers/gpu/drm/drm_drv.c | 3 ++ include/drm/drm_cgroup.h | 17 +++++++ include/drm/drm_device.h | 7 +++ include/linux/cgroup_drm.h | 13 ++++++ kernel/cgroup/drm.c | 95 +++++++++++++++++++++++++++++++++++++- 5 files changed, 134 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3b940926d672..dac742445b38 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -570,6 +570,7 @@ static void drm_dev_init_release(struct drm_device *dev, void *res) /* Prevent use-after-free in drm_managed_release when debugging is * enabled. Slightly awkward, but can't really be helped. */ dev->dev = NULL; + mutex_destroy(&dev->drmcg_mutex); mutex_destroy(&dev->master_mutex); mutex_destroy(&dev->clientlist_mutex); mutex_destroy(&dev->filelist_mutex); @@ -612,6 +613,7 @@ static int drm_dev_init(struct drm_device *dev, mutex_init(&dev->filelist_mutex); mutex_init(&dev->clientlist_mutex); mutex_init(&dev->master_mutex); + mutex_init(&dev->drmcg_mutex); ret = drmm_add_action(dev, drm_dev_init_release, NULL); if (ret) @@ -652,6 +654,7 @@ static int drm_dev_init(struct drm_device *dev, if (ret) goto err; + drmcg_device_early_init(dev); return 0; err: diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h index 530c9a0b3238..43caf1b6a0de 100644 --- a/include/drm/drm_cgroup.h +++ b/include/drm/drm_cgroup.h @@ -4,6 +4,17 @@ #ifndef __DRM_CGROUP_H__ #define __DRM_CGROUP_H__ +#include + +struct drm_device; + +/** + * Per DRM device properties for DRM cgroup controller for the purpose + * of storing per device defaults + */ +struct drmcg_props { +}; + #ifdef CONFIG_CGROUP_DRM void drmcg_bind(struct drm_minor (*(*acq_dm)(unsigned int minor_id)), @@ -15,6 +26,8 @@ void drmcg_register_dev(struct drm_device *dev); void drmcg_unregister_dev(struct drm_device *dev); +void drmcg_device_early_init(struct drm_device *device); + #else static inline void drmcg_bind( @@ -35,5 +48,9 @@ static inline void drmcg_unregister_dev(struct drm_device *dev) { } +static inline void drmcg_device_early_init(struct drm_device *device) +{ +} + #endif /* CONFIG_CGROUP_DRM */ #endif /* __DRM_CGROUP_H__ */ diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index d647223e8390..1cdccc9a653c 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -8,6 +8,7 @@ #include #include +#include struct drm_driver; struct drm_minor; @@ -318,6 +319,12 @@ struct drm_device { */ struct drm_fb_helper *fb_helper; + /** \name DRM Cgroup */ + /*@{ */ + struct mutex drmcg_mutex; + struct drmcg_props drmcg_props; + /*@} */ + /* Everything below here is for legacy driver, never use! */ /* private: */ #if IS_ENABLED(CONFIG_DRM_LEGACY) diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h index 307bb75db248..50f055804400 100644 --- a/include/linux/cgroup_drm.h +++ b/include/linux/cgroup_drm.h @@ -12,11 +12,19 @@ #ifdef CONFIG_CGROUP_DRM +/** + * Per DRM cgroup, per device resources (such as statistics and limits) + */ +struct drmcg_device_resource { + /* for per device stats */ +}; + /** * The DRM cgroup controller data structure. */ struct drmcg { struct cgroup_subsys_state css; + struct drmcg_device_resource *dev_resources[MAX_DRM_DEV]; }; /** @@ -40,6 +48,8 @@ static inline struct drmcg *css_to_drmcg(struct cgroup_subsys_state *css) */ static inline struct drmcg *drmcg_get(struct task_struct *task) { + if (!cgroup_subsys_enabled(gpu_cgrp_subsys)) + return NULL; return css_to_drmcg(task_get_css(task, gpu_cgrp_id)); } @@ -70,6 +80,9 @@ static inline struct drmcg *drmcg_parent(struct drmcg *cg) #else /* CONFIG_CGROUP_DRM */ +struct drmcg_device_resource { +}; + struct drmcg { }; diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index 061bb9c458e4..836929c27de8 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -1,11 +1,15 @@ // SPDX-License-Identifier: MIT -// Copyright 2019 Advanced Micro Devices, Inc. +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright © 2021 Intel Corporation + */ #include #include #include #include #include #include +#include #include #include @@ -54,6 +58,26 @@ void drmcg_unbind(void) } EXPORT_SYMBOL(drmcg_unbind); +/* caller must hold dev->drmcg_mutex */ +static inline int init_drmcg_single(struct drmcg *drmcg, struct drm_device *dev) +{ + int minor = dev->primary->index; + struct drmcg_device_resource *ddr = drmcg->dev_resources[minor]; + + if (ddr == NULL) { + ddr = kzalloc(sizeof(struct drmcg_device_resource), + GFP_KERNEL); + + if (!ddr) + return -ENOMEM; + } + + /* set defaults here */ + drmcg->dev_resources[minor] = ddr; + + return 0; +} + /** * drmcg_register_dev - register a DRM device for usage in drm cgroup * @dev: DRM device @@ -137,23 +161,61 @@ static int drm_minor_for_each(int (*fn)(int id, void *p, void *data), return rc; } +static int drmcg_css_free_fn(int id, void *ptr, void *data) +{ + struct drm_minor *minor = ptr; + struct drmcg *drmcg = data; + + if (minor->type != DRM_MINOR_PRIMARY) + return 0; + + kfree(drmcg->dev_resources[minor->index]); + + return 0; +} + static void drmcg_css_free(struct cgroup_subsys_state *css) { struct drmcg *drmcg = css_to_drmcg(css); + drm_minor_for_each(&drmcg_css_free_fn, drmcg); + kfree(drmcg); } +static int init_drmcg_fn(int id, void *ptr, void *data) +{ + struct drm_minor *minor = ptr; + struct drmcg *drmcg = data; + int rc; + + if (minor->type != DRM_MINOR_PRIMARY) + return 0; + + mutex_lock(&minor->dev->drmcg_mutex); + rc = init_drmcg_single(drmcg, minor->dev); + mutex_unlock(&minor->dev->drmcg_mutex); + + return rc; +} + static struct cgroup_subsys_state * drmcg_css_alloc(struct cgroup_subsys_state *parent_css) { struct drmcg *parent = css_to_drmcg(parent_css); struct drmcg *drmcg; + int rc; drmcg = kzalloc(sizeof(struct drmcg), GFP_KERNEL); if (!drmcg) return ERR_PTR(-ENOMEM); + rc = drm_minor_for_each(&init_drmcg_fn, drmcg); + if (rc) { + drmcg_css_free(&drmcg->css); + return ERR_PTR(rc); + } + if (!parent) root_drmcg = drmcg; @@ -171,3 +233,34 @@ struct cgroup_subsys gpu_cgrp_subsys = { .legacy_cftypes = files, .dfl_cftypes = files, }; + +/** + * drmcg_device_early_init - initialize device specific resources for DRM cgroups + * @dev: the target DRM device + * + * Allocate and initialize device specific resources for existing DRM cgroups. + * Typically only the root cgroup exists before the initialization of @dev. + */ +void drmcg_device_early_init(struct drm_device *dev) +{ + struct cgroup_subsys_state *pos; + + if (root_drmcg == NULL) + return; + + /* init cgroups created before registration (i.e. root cgroup) */ + rcu_read_lock(); + css_for_each_descendant_pre(pos, &root_drmcg->css) { + css_get(pos); + rcu_read_unlock(); + + mutex_lock(&dev->drmcg_mutex); + init_drmcg_single(css_to_drmcg(pos), dev); + mutex_unlock(&dev->drmcg_mutex); + + rcu_read_lock(); + css_put(pos); + } + rcu_read_unlock(); +} +EXPORT_SYMBOL(drmcg_device_early_init); From patchwork Tue Jan 26 21:46:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048401 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5F37C433E6 for ; Tue, 26 Jan 2021 21:44:57 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B296520656 for ; Tue, 26 Jan 2021 21:44:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B296520656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A77D56E499; Tue, 26 Jan 2021 21:44:39 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id A81FC6E171; Tue, 26 Jan 2021 21:44:38 +0000 (UTC) IronPort-SDR: dqGHWBPCwJtOL62md5ftqlE2LP5ddcd9eXG5nTdPQDzc4X+we9T1XtYmyNFr+hRvK7uFNODShF RU+GZDx27jUQ== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770830" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770830" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: OfkL2jyeVJD0ADEkQs01vPNC8EYhXhZqLWDvifr1sAW3vHpmZx6di1vf+NueX71l7Z9hPJ6sGc DsdvaaXNBPZw== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139893" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:21 -0800 Message-Id: <20210126214626.16260-5-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 4/9] drmcg: Add skeleton seq_show and write for drmcg files X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add basic .seq_show and .write functions for use with DRM cgroup control files. This is based on original work from Kenny Ho and extracted from patches [1] and [2]. Has been simplified to remove having different file types and functions for each. [1] https://lists.freedesktop.org/archives/dri-devel/2020-February/254986.html [2] https://lists.freedesktop.org/archives/dri-devel/2020-February/254990.html Co-developed-by: Kenny Ho Signed-off-by: Brian Welty --- include/drm/drm_cgroup.h | 5 ++ kernel/cgroup/drm.c | 102 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h index 43caf1b6a0de..12526def9fbf 100644 --- a/include/drm/drm_cgroup.h +++ b/include/drm/drm_cgroup.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: MIT * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright © 2021 Intel Corporation */ #ifndef __DRM_CGROUP_H__ #define __DRM_CGROUP_H__ @@ -15,6 +16,10 @@ struct drm_device; struct drmcg_props { }; +enum drmcg_res_type { + __DRMCG_TYPE_LAST, +}; + #ifdef CONFIG_CGROUP_DRM void drmcg_bind(struct drm_minor (*(*acq_dm)(unsigned int minor_id)), diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index 836929c27de8..aece11faa0bc 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include static struct drmcg *root_drmcg __read_mostly; @@ -222,6 +224,106 @@ drmcg_css_alloc(struct cgroup_subsys_state *parent_css) return &drmcg->css; } +static int drmcg_apply_value(struct drmcg_device_resource *ddr, + enum drmcg_res_type type, char *buf) +{ + int ret = 0; + unsigned long val; + + switch (type) { + default: + break; + } + + return ret; +} + +static int drmcg_seq_show_fn(int id, void *ptr, void *data) +{ + struct drm_minor *minor = ptr; + struct seq_file *sf = data; + struct drmcg *drmcg = css_to_drmcg(seq_css(sf)); + enum drmcg_res_type type = seq_cft(sf)->private; + struct drmcg_device_resource *ddr; + + if (minor->type != DRM_MINOR_PRIMARY) + return 0; + + ddr = drmcg->dev_resources[minor->index]; + if (ddr == NULL) + return 0; + + seq_printf(sf, "%d:%d ", DRM_MAJOR, minor->index); + switch (type) { + default: + seq_puts(sf, "\n"); + break; + } + + return 0; +} + +static int drmcg_seq_show(struct seq_file *sf, void *v) +{ + return drm_minor_for_each(&drmcg_seq_show_fn, sf); +} + +static ssize_t drmcg_write(struct kernfs_open_file *of, char *buf, + size_t nbytes, loff_t off) +{ + struct drmcg *drmcg = css_to_drmcg(of_css(of)); + enum drmcg_res_type type = of_cft(of)->private; + char *cft_name = of_cft(of)->name; + char *limits = strstrip(buf); + struct drmcg_device_resource *ddr; + struct drm_minor *dm; + char *line; + char sattr[256]; + int minor, ret = 0; + + while (!ret && limits != NULL) { + line = strsep(&limits, "\n"); + + if (sscanf(line, + __stringify(DRM_MAJOR)":%u %255[^\t\n]", + &minor, sattr) != 2) { + pr_err("drmcg: error parsing %s ", cft_name); + pr_cont_cgroup_name(drmcg->css.cgroup); + pr_cont("\n"); + + continue; + } + + mutex_lock(&drmcg_mutex); + if (acquire_drm_minor) + dm = acquire_drm_minor(minor); + else + dm = NULL; + mutex_unlock(&drmcg_mutex); + + if (IS_ERR_OR_NULL(dm)) { + pr_err("drmcg: invalid minor %d for %s ", + minor, cft_name); + pr_cont_cgroup_name(drmcg->css.cgroup); + pr_cont("\n"); + + continue; + } + + mutex_lock(&dm->dev->drmcg_mutex); + ddr = drmcg->dev_resources[minor]; + ret = drmcg_apply_value(ddr, type, sattr); + mutex_unlock(&dm->dev->drmcg_mutex); + + mutex_lock(&drmcg_mutex); + if (put_drm_dev) + put_drm_dev(dm->dev); /* release from acquire_drm_minor */ + mutex_unlock(&drmcg_mutex); + } + + return ret ?: nbytes; +} + struct cftype files[] = { { } /* terminate */ }; From patchwork Tue Jan 26 21:46:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048405 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7FDBC433E0 for ; Tue, 26 Jan 2021 21:45:01 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 848F820656 for ; Tue, 26 Jan 2021 21:45:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 848F820656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8BC216E4A1; Tue, 26 Jan 2021 21:44:40 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id AC2A76E454; Tue, 26 Jan 2021 21:44:38 +0000 (UTC) IronPort-SDR: hun3bJ0V0QOcYRSTlRcGoXwT/WZ0Y5CZkwyRUSU/K8Z6LfeNWhq+CjZHhnEBIqB/JkJeGPec3r af3xeK6mgFvQ== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770831" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770831" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: FzYxckzEHP5AdU4pW4zaw6I6XIsoOUFpNykAB8xd8wufq1tt23CgscMqeq1nTB5dJOAYHtw4fS WSyezQdLOLIA== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139897" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:22 -0800 Message-Id: <20210126214626.16260-6-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 5/9] drmcg: Add support for device memory accounting via page counter X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Here we introduce a general purpose drm_cgroup_try_charge and uncharge pair of functions. This is modelled after the existing RDMA cgroup controller, and the idea is for these functions to be used for charging/uncharging all current and future DRM resource controls. Two new controls are added in order to allow DRM device drivers to expose memories attached to the device for purposes of memory accounting and enforcing allocation limit. Following controls are introduced and are intended to provide equivalent behavior and functionality where possible as the MEM controller: memory.current Read-only value, displays current device memory usage for all DRM device memory in terms of allocated physical backing store. memory.max Read-write value, displays the maximum memory usage limit of device memory. If memory usage reaches this limit, then subsequent memory allocations will fail. The expectation is that the DRM device driver simply lets allocations fail when memory.max is reached. Future work might be to introduce the device memory concept of memory.high or memory.low controls, such that DRM device might be able to invoke memory eviction when these lower threshold are hit. With provided charging functions, support for memory accounting/charging is functional. The intent is for DRM device drivers to charge against memory.current as device memory is physically allocated. Implementation is simplified by making use of page counters underneath. Nested cgroups will correctly maintain the parent for the memory page counters, such that hierarchial charging to parent's memory.current is supported. Note, this is only for tracking of allocations from device-backed memory. Memory charging for objects that are backed by system memory is already handled by the mm subsystem and existing memory accounting controls. Signed-off-by: Brian Welty --- Documentation/admin-guide/cgroup-v2.rst | 29 ++++- include/drm/drm_cgroup.h | 20 ++++ include/linux/cgroup_drm.h | 4 +- kernel/cgroup/drm.c | 145 +++++++++++++++++++++++- 4 files changed, 191 insertions(+), 7 deletions(-) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index b099e1d71098..405912710b3a 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -2171,8 +2171,35 @@ of GPU-related resources. GPU Interface Files ~~~~~~~~~~~~~~~~~~~~ -TODO +GPU controller supports usage of multiple DRM devices within a cgroup. +As such, for all interface files, output is keyed by device major:minor +and is not ordered. +The first set of control files are for regulating the accounting and +allocation of memories attached to DRM devices. The controls are intended +to provide equivalent behavior and functionality where possible as the +MEM controller. All memory amounts are in bytes. + + memory.current + Read-only value, displays current device memory usage for the DRM + device memory in terms of allocated physical backing store. + + memory.max + Read-write value, displays the maximum memory usage limit for the + DRM device memory. If memory usage reaches this limit, + subsequent device memory allocations will fail. + +While some DRM devices may be capable to present multiple memory segments +to the user, the intent with above controls is to aggregate all user +allocatable backing store. Any support for multiple memory segments is +left as future work. + +The expectation is that the DRM device driver simply lets allocations fail +when memory.max is reached. Future work might be to introduce the device +memory concept of memory.high or memory.low controls. When these lower +thresholds are hit, this would then allow the DRM device driver to invoke +some equivalent to OOM-killer or forced memory eviction for the device +backed memory in order to attempt to free additional space. Misc ---- diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h index 12526def9fbf..8b4c4e798b11 100644 --- a/include/drm/drm_cgroup.h +++ b/include/drm/drm_cgroup.h @@ -8,6 +8,7 @@ #include struct drm_device; +struct drmcg; /** * Per DRM device properties for DRM cgroup controller for the purpose @@ -17,6 +18,8 @@ struct drmcg_props { }; enum drmcg_res_type { + DRMCG_TYPE_MEM_CURRENT, + DRMCG_TYPE_MEM_MAX, __DRMCG_TYPE_LAST, }; @@ -33,6 +36,11 @@ void drmcg_unregister_dev(struct drm_device *dev); void drmcg_device_early_init(struct drm_device *device); +int drm_cgroup_try_charge(struct drmcg *drmcg, struct drm_device *dev, + enum drmcg_res_type type, u64 usage); +void drm_cgroup_uncharge(struct drmcg *drmcg, struct drm_device *dev, + enum drmcg_res_type type, u64 usage); + #else static inline void drmcg_bind( @@ -57,5 +65,17 @@ static inline void drmcg_device_early_init(struct drm_device *device) { } +static inline +int drm_cgroup_try_charge(struct drmcg *drmcg, struct drm_device *dev, + enum drmcg_res_type res, u64 usage) +{ + return 0; +} + +static inline +void drm_cgroup_uncharge(struct drmcg *drmcg,struct drm_device *dev, + enum drmcg_res_type type, u64 usage) +{ +} #endif /* CONFIG_CGROUP_DRM */ #endif /* __DRM_CGROUP_H__ */ diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h index 50f055804400..3570636473cf 100644 --- a/include/linux/cgroup_drm.h +++ b/include/linux/cgroup_drm.h @@ -1,10 +1,12 @@ /* SPDX-License-Identifier: MIT * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright © 2021 Intel Corporation */ #ifndef _CGROUP_DRM_H #define _CGROUP_DRM_H #include +#include #include /* limit defined per the way drm_minor_alloc operates */ @@ -16,7 +18,7 @@ * Per DRM cgroup, per device resources (such as statistics and limits) */ struct drmcg_device_resource { - /* for per device stats */ + struct page_counter memory; }; /** diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index aece11faa0bc..bec41f343208 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -64,6 +64,7 @@ EXPORT_SYMBOL(drmcg_unbind); static inline int init_drmcg_single(struct drmcg *drmcg, struct drm_device *dev) { int minor = dev->primary->index; + struct drmcg_device_resource *parent_ddr = NULL; struct drmcg_device_resource *ddr = drmcg->dev_resources[minor]; if (ddr == NULL) { @@ -74,7 +75,12 @@ static inline int init_drmcg_single(struct drmcg *drmcg, struct drm_device *dev) return -ENOMEM; } + if (drmcg_parent(drmcg)) + parent_ddr = drmcg_parent(drmcg)->dev_resources[minor]; + /* set defaults here */ + page_counter_init(&ddr->memory, + parent_ddr ? &parent_ddr->memory : NULL); drmcg->dev_resources[minor] = ddr; return 0; @@ -212,6 +218,13 @@ drmcg_css_alloc(struct cgroup_subsys_state *parent_css) if (!drmcg) return ERR_PTR(-ENOMEM); + /* + * parent is normally set upon return in caller, but set here as + * is needed by init_drmcg_single so resource initialization can + * associate with parent for hierarchial charging + */ + drmcg->css.parent = parent_css; + rc = drm_minor_for_each(&init_drmcg_fn, drmcg); if (rc) { drmcg_css_free(&drmcg->css); @@ -231,6 +244,10 @@ static int drmcg_apply_value(struct drmcg_device_resource *ddr, unsigned long val; switch (type) { + case DRMCG_TYPE_MEM_MAX: + ret = page_counter_memparse(buf, "max", &val); + if (!ret) + ret = page_counter_set_max(&ddr->memory, val); default: break; } @@ -253,10 +270,21 @@ static int drmcg_seq_show_fn(int id, void *ptr, void *data) if (ddr == NULL) return 0; - seq_printf(sf, "%d:%d ", DRM_MAJOR, minor->index); switch (type) { + case DRMCG_TYPE_MEM_CURRENT: + seq_printf(sf, "%d:%d %ld\n", + DRM_MAJOR, minor->index, + page_counter_read(&ddr->memory) * PAGE_SIZE); + break; + case DRMCG_TYPE_MEM_MAX: + seq_printf(sf, "%d:%d ", DRM_MAJOR, minor->index); + if (ddr->memory.max == PAGE_COUNTER_MAX) + seq_printf(sf, "max\n"); + else + seq_printf(sf, "%ld\n", ddr->memory.max * PAGE_SIZE); + break; default: - seq_puts(sf, "\n"); + seq_printf(sf, "%d:%d\n", DRM_MAJOR, minor->index); break; } @@ -268,6 +296,17 @@ static int drmcg_seq_show(struct seq_file *sf, void *v) return drm_minor_for_each(&drmcg_seq_show_fn, sf); } +static int drmcg_parse_input(const char *buf, enum drmcg_res_type type, + int *minor, char *sattr) +{ + if (sscanf(buf, + __stringify(DRM_MAJOR)":%u %255[^\t\n]", + minor, sattr) != 2) + return -EINVAL; + + return 0; +} + static ssize_t drmcg_write(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -284,9 +323,7 @@ static ssize_t drmcg_write(struct kernfs_open_file *of, char *buf, while (!ret && limits != NULL) { line = strsep(&limits, "\n"); - if (sscanf(line, - __stringify(DRM_MAJOR)":%u %255[^\t\n]", - &minor, sattr) != 2) { + if (drmcg_parse_input(line, type, &minor, sattr)) { pr_err("drmcg: error parsing %s ", cft_name); pr_cont_cgroup_name(drmcg->css.cgroup); pr_cont("\n"); @@ -325,6 +362,18 @@ static ssize_t drmcg_write(struct kernfs_open_file *of, char *buf, } struct cftype files[] = { + { + .name = "memory.current", + .seq_show = drmcg_seq_show, + .private = DRMCG_TYPE_MEM_CURRENT, + }, + { + .name = "memory.max", + .seq_show = drmcg_seq_show, + .write = drmcg_write, + .private = DRMCG_TYPE_MEM_MAX, + .flags = CFTYPE_NOT_ON_ROOT + }, { } /* terminate */ }; @@ -366,3 +415,89 @@ void drmcg_device_early_init(struct drm_device *dev) rcu_read_unlock(); } EXPORT_SYMBOL(drmcg_device_early_init); + +/** + * drm_cgroup_try_charge - try charging against drmcg resource + * @drmcg: DRM cgroup to charge + * @dev: associated DRM device + * @type: which resource type to charge + * @usage: usage to be charged + * + * For @type of DRMCG_TYPE_MEM_CURRENT: + * Try to charge @usage bytes to specified DRM cgroup. This will fail if + * a successful charge would cause the current device memory usage to go + * above the maximum limit. On failure, the caller (DRM device driver) may + * choose to enact some form of memory reclaim, but the exact behavior is left + * to the DRM device driver to define. + * + * Returns 0 on success. Otherwise, an error code is returned. + */ +int drm_cgroup_try_charge(struct drmcg *drmcg, struct drm_device *dev, + enum drmcg_res_type type, u64 usage) +{ + struct drmcg_device_resource *res; + struct page_counter *counter; + int err = -ENOMEM; + u64 nr_pages; + + if (!drmcg) + return 0; + + res = drmcg->dev_resources[dev->primary->index]; + if (!res) + return -EINVAL; + + switch (type) { + case DRMCG_TYPE_MEM_CURRENT: + nr_pages = usage >> PAGE_SHIFT; + if (page_counter_try_charge(&res->memory, nr_pages, + &counter)) { + css_get_many(&drmcg->css, nr_pages); + err = 0; + } + break; + default: + err = -EINVAL; + break; + } + + return err; +} +EXPORT_SYMBOL(drm_cgroup_try_charge); + +/** + * drm_cgroup_uncharge - uncharge resource usage from drmcg + * @drmcg: DRM cgroup to uncharge + * @dev: associated DRM device + * @type: which resource type to uncharge + * @usage: usage to be uncharged + * + * Action for each @type: + * DRMCG_TYPE_MEM_CURRENT: Uncharge @usage bytes from specified DRM cgroup. + * + * Returns 0 on success. Otherwise, an error code is returned. + */ +void drm_cgroup_uncharge(struct drmcg *drmcg, struct drm_device *dev, + enum drmcg_res_type type, u64 usage) +{ + struct drmcg_device_resource *res; + u64 nr_pages; + + if (!drmcg) + return; + + res = drmcg->dev_resources[dev->primary->index]; + if (!res) + return; + + switch (type) { + case DRMCG_TYPE_MEM_CURRENT: + nr_pages = usage >> PAGE_SHIFT; + page_counter_uncharge(&res->memory, nr_pages); + css_put_many(&drmcg->css, nr_pages); + break; + default: + break; + } +} +EXPORT_SYMBOL(drm_cgroup_uncharge); From patchwork Tue Jan 26 21:46:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048407 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35CDFC433DB for ; Tue, 26 Jan 2021 21:45:13 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D00FF20656 for ; Tue, 26 Jan 2021 21:45:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D00FF20656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 073236E4D0; Tue, 26 Jan 2021 21:44:43 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id D99966E441; Tue, 26 Jan 2021 21:44:38 +0000 (UTC) IronPort-SDR: dliIqAcnv56CarRt8oqIDhNWRF4ukNMhxT+z5LCYAFxyTUQeTfaxhehGGD5YT3sH7mq1gbUhg1 lfPzJG3AdSxw== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770832" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770832" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: pdeKR/xjdpNl2KwR8XT6CRTsjZqfBTuYkjMrDL/Jrs5DbJUnwWYjD7mizYUvmzpwEqsIk3YlZL tKEP+ihW4vJw== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139899" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:23 -0800 Message-Id: <20210126214626.16260-7-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 6/9] drmcg: Add memory.total file X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Following control is introduced in order to display total memory that exists for the DRM device. DRM drivers can advertise this value by writing to drm_device.drmcg_props. This is needed in order to effectively use the other memory controls. Normally for system memory this is available to the user using procfs. memory.total Read-only value, displays total memory for a device, shown only in root cgroup. Signed-off-by: Brian Welty --- Documentation/admin-guide/cgroup-v2.rst | 4 ++++ include/drm/drm_cgroup.h | 2 ++ kernel/cgroup/drm.c | 10 ++++++++++ 3 files changed, 16 insertions(+) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index 405912710b3a..ccc25f03a898 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -2189,6 +2189,10 @@ MEM controller. All memory amounts are in bytes. DRM device memory. If memory usage reaches this limit, subsequent device memory allocations will fail. + memory.total + Read-only value, displays total memory for a device, shown only in + root cgroup. + While some DRM devices may be capable to present multiple memory segments to the user, the intent with above controls is to aggregate all user allocatable backing store. Any support for multiple memory segments is diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h index 8b4c4e798b11..9ba0e372eeee 100644 --- a/include/drm/drm_cgroup.h +++ b/include/drm/drm_cgroup.h @@ -15,11 +15,13 @@ struct drmcg; * of storing per device defaults */ struct drmcg_props { + u64 memory_total; }; enum drmcg_res_type { DRMCG_TYPE_MEM_CURRENT, DRMCG_TYPE_MEM_MAX, + DRMCG_TYPE_MEM_TOTAL, __DRMCG_TYPE_LAST, }; diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index bec41f343208..08e75eb67593 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -283,6 +283,10 @@ static int drmcg_seq_show_fn(int id, void *ptr, void *data) else seq_printf(sf, "%ld\n", ddr->memory.max * PAGE_SIZE); break; + case DRMCG_TYPE_MEM_TOTAL: + seq_printf(sf, "%d:%d %llu\n", DRM_MAJOR, minor->index, + minor->dev->drmcg_props.memory_total); + break; default: seq_printf(sf, "%d:%d\n", DRM_MAJOR, minor->index); break; @@ -374,6 +378,12 @@ struct cftype files[] = { .private = DRMCG_TYPE_MEM_MAX, .flags = CFTYPE_NOT_ON_ROOT }, + { + .name = "memory.total", + .seq_show = drmcg_seq_show, + .private = DRMCG_TYPE_MEM_TOTAL, + .flags = CFTYPE_ONLY_ON_ROOT, + }, { } /* terminate */ }; From patchwork Tue Jan 26 21:46:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048409 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BBEDCC433E9 for ; Tue, 26 Jan 2021 21:45:13 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 84F8F20656 for ; Tue, 26 Jan 2021 21:45:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 84F8F20656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 03FD16E4C1; Tue, 26 Jan 2021 21:44:42 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id DBFB66E455; Tue, 26 Jan 2021 21:44:38 +0000 (UTC) IronPort-SDR: C5eR9fq5lAHjmNH4Hhk0/VNlefwZB6fD3Yd83bdZVt6dElo/q4lbe+VHyaJjeh9OJdgc08utPw d6Hnzd38byZA== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770833" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770833" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: 5gXBtpv/bdceklTZYWdFrkeFvdqPkHTvqOWtCrbOr1mtMjc+Wz1YWJEHoMl1+Kit9uYn5G06dz ksz3Gj04BC5g== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139902" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:24 -0800 Message-Id: <20210126214626.16260-8-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 7/9] drmcg: Add initial support for tracking gpu time usage X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Single control below is added to DRM cgroup controller in order to track user execution time for GPU devices. It is up to device drivers to charge execution time to the cgroup via drm_cgroup_try_charge(). sched.runtime Read-only value, displays current user execution time for each DRM device. The expectation is that this is incremented by DRM device driver's scheduler upon user context completion or context switch. Units of time are in microseconds for consistency with cpu.stats. Signed-off-by: Brian Welty --- Documentation/admin-guide/cgroup-v2.rst | 9 +++++++++ include/drm/drm_cgroup.h | 2 ++ include/linux/cgroup_drm.h | 2 ++ kernel/cgroup/drm.c | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index ccc25f03a898..f1d0f333a49e 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -2205,6 +2205,15 @@ thresholds are hit, this would then allow the DRM device driver to invoke some equivalent to OOM-killer or forced memory eviction for the device backed memory in order to attempt to free additional space. +The below set of control files are for time accounting of DRM devices. Units +of time are in microseconds. + + sched.runtime + Read-only value, displays current user execution time for each DRM + device. The expectation is that this is incremented by DRM device + driver's scheduler upon user context completion or context switch. + + Misc ---- diff --git a/include/drm/drm_cgroup.h b/include/drm/drm_cgroup.h index 9ba0e372eeee..315dab8a93b8 100644 --- a/include/drm/drm_cgroup.h +++ b/include/drm/drm_cgroup.h @@ -22,6 +22,7 @@ enum drmcg_res_type { DRMCG_TYPE_MEM_CURRENT, DRMCG_TYPE_MEM_MAX, DRMCG_TYPE_MEM_TOTAL, + DRMCG_TYPE_SCHED_RUNTIME, __DRMCG_TYPE_LAST, }; @@ -79,5 +80,6 @@ void drm_cgroup_uncharge(struct drmcg *drmcg,struct drm_device *dev, enum drmcg_res_type type, u64 usage) { } + #endif /* CONFIG_CGROUP_DRM */ #endif /* __DRM_CGROUP_H__ */ diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h index 3570636473cf..0fafa663321e 100644 --- a/include/linux/cgroup_drm.h +++ b/include/linux/cgroup_drm.h @@ -19,6 +19,8 @@ */ struct drmcg_device_resource { struct page_counter memory; + seqlock_t sched_lock; + u64 exec_runtime; }; /** diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index 08e75eb67593..64e9d0dbe8c8 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -81,6 +81,7 @@ static inline int init_drmcg_single(struct drmcg *drmcg, struct drm_device *dev) /* set defaults here */ page_counter_init(&ddr->memory, parent_ddr ? &parent_ddr->memory : NULL); + seqlock_init(&ddr->sched_lock); drmcg->dev_resources[minor] = ddr; return 0; @@ -287,6 +288,10 @@ static int drmcg_seq_show_fn(int id, void *ptr, void *data) seq_printf(sf, "%d:%d %llu\n", DRM_MAJOR, minor->index, minor->dev->drmcg_props.memory_total); break; + case DRMCG_TYPE_SCHED_RUNTIME: + seq_printf(sf, "%d:%d %llu\n", DRM_MAJOR, minor->index, + ktime_to_us(ddr->exec_runtime)); + break; default: seq_printf(sf, "%d:%d\n", DRM_MAJOR, minor->index); break; @@ -384,6 +389,12 @@ struct cftype files[] = { .private = DRMCG_TYPE_MEM_TOTAL, .flags = CFTYPE_ONLY_ON_ROOT, }, + { + .name = "sched.runtime", + .seq_show = drmcg_seq_show, + .private = DRMCG_TYPE_SCHED_RUNTIME, + .flags = CFTYPE_NOT_ON_ROOT, + }, { } /* terminate */ }; @@ -440,6 +451,10 @@ EXPORT_SYMBOL(drmcg_device_early_init); * choose to enact some form of memory reclaim, but the exact behavior is left * to the DRM device driver to define. * + * For @res type of DRMCG_TYPE_SCHED_RUNTIME: + * For GPU time accounting, add @usage amount of GPU time to @drmcg for + * the given device. + * * Returns 0 on success. Otherwise, an error code is returned. */ int drm_cgroup_try_charge(struct drmcg *drmcg, struct drm_device *dev, @@ -466,6 +481,11 @@ int drm_cgroup_try_charge(struct drmcg *drmcg, struct drm_device *dev, err = 0; } break; + case DRMCG_TYPE_SCHED_RUNTIME: + write_seqlock(&res->sched_lock); + res->exec_runtime = ktime_add(res->exec_runtime, usage); + write_sequnlock(&res->sched_lock); + break; default: err = -EINVAL; break; From patchwork Tue Jan 26 21:46:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048411 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C69F3C433DB for ; Tue, 26 Jan 2021 21:45:17 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 97A5920656 for ; Tue, 26 Jan 2021 21:45:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 97A5920656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8F0D36E4CB; Tue, 26 Jan 2021 21:44:42 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0FA4A6E171; Tue, 26 Jan 2021 21:44:39 +0000 (UTC) IronPort-SDR: i6iOgqrfjh06BCyVnkGE6fMAyuKsG3RXDWwORUvdlRWH3xmnoKHRphCnHSRkbRhpz7Fzi+3CGd Opold4RlhU6g== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770834" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770834" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:37 -0800 IronPort-SDR: mYnmEKpeuO6WzUZ+VqUfEZoCLGgLnNVRdsnqkI9kHOqYXasjUVc8ONVGKSZVdtN0WcB9l6Bhut EMTwDuPgUGOQ== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139905" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:25 -0800 Message-Id: <20210126214626.16260-9-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 8/9] drm/gem: Associate GEM objects with drm cgroup X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" This patch adds tracking of which cgroup to make charges against for a given GEM object. We associate the current task's cgroup with GEM objects as they are created. First user of this is for charging DRM cgroup for device memory allocations. The intended behavior is for device drivers to make the cgroup charging calls at the time that backing store is allocated or deallocated for the object. Exported functions are provided for charging memory allocations for a GEM object to DRM cgroup. To aid in debugging, we store how many bytes have been charged inside the GEM object. Add helpers for setting and clearing the object's associated cgroup which will check that charges are not being leaked. For shared objects, this may make the charge against a cgroup that is potentially not the same cgroup as the process using the memory. Based on the memory cgroup's discussion of "memory ownership", this seems acceptable [1]. [1] https://www.kernel.org/doc/Documentation/cgroup-v2.txt, "Memory Ownership" Signed-off-by: Brian Welty --- drivers/gpu/drm/drm_gem.c | 89 +++++++++++++++++++++++++++++++++++++++ include/drm/drm_gem.h | 17 ++++++++ 2 files changed, 106 insertions(+) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index c2ce78c4edc3..a12da41eaafe 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -112,6 +113,89 @@ drm_gem_init(struct drm_device *dev) return drmm_add_action(dev, drm_gem_init_release, NULL); } +/** + * drm_gem_object_set_cgroup - associate GEM object with a cgroup + * @obj: GEM object which is being associated with a cgroup + * @task: task associated with process control group to use + * + * This will acquire a reference on cgroup and use for charging GEM + * memory allocations. + * This helper could be extended in future to migrate charges to another + * cgroup, print warning if this usage occurs. + */ +void drm_gem_object_set_cgroup(struct drm_gem_object *obj, + struct task_struct *task) +{ + /* if object has existing cgroup, we migrate the charge... */ + if (obj->drmcg) { + pr_warn("DRM: need to migrate cgroup charge of %lld\n", + atomic64_read(&obj->drmcg_bytes_charged)); + } + obj->drmcg = drmcg_get(task); +} +EXPORT_SYMBOL(drm_gem_object_set_cgroup); + +/** + * drm_gem_object_unset_cgroup - clear GEM object's associated cgroup + * @obj: GEM object + * + * This will release a reference on cgroup. + */ +void drm_gem_object_unset_cgroup(struct drm_gem_object *obj) +{ + WARN_ON(atomic64_read(&obj->drmcg_bytes_charged)); + drmcg_put(obj->drmcg); +} +EXPORT_SYMBOL(drm_gem_object_unset_cgroup); + +/** + * drm_gem_object_charge_mem - try charging size bytes to DRM cgroup + * @obj: GEM object which is being charged + * @size: number of bytes to charge + * + * Try to charge @size bytes to GEM object's associated DRM cgroup. This + * will fail if a successful charge would cause the current device memory + * usage to go above the cgroup's GPU memory maximum limit. + * + * Returns 0 on success. Otherwise, an error code is returned. + */ +int drm_gem_object_charge_mem(struct drm_gem_object *obj, u64 size) +{ + int ret; + + ret = drm_cgroup_try_charge(obj->drmcg, obj->dev, + DRMCG_TYPE_MEM_CURRENT, size); + if (!ret) + atomic64_add(size, &obj->drmcg_bytes_charged); + return ret; +} +EXPORT_SYMBOL(drm_gem_object_charge_mem); + +/** + * drm_gem_object_uncharge_mem - uncharge size bytes from DRM cgroup + * @obj: GEM object which is being uncharged + * @size: number of bytes to uncharge + * + * Uncharge @size bytes from the DRM cgroup associated with specified + * GEM object. + * + * Returns 0 on success. Otherwise, an error code is returned. + */ +void drm_gem_object_uncharge_mem(struct drm_gem_object *obj, u64 size) +{ + u64 charged = atomic64_read(&obj->drmcg_bytes_charged); + + if (WARN_ON(!charged)) + return; + if (WARN_ON(size > charged)) + size = charged; + + atomic64_sub(size, &obj->drmcg_bytes_charged); + drm_cgroup_uncharge(obj->drmcg, obj->dev, DRMCG_TYPE_MEM_CURRENT, + size); +} +EXPORT_SYMBOL(drm_gem_object_uncharge_mem); + /** * drm_gem_object_init - initialize an allocated shmem-backed GEM object * @dev: drm_device the object should be initialized for @@ -156,6 +240,8 @@ void drm_gem_private_object_init(struct drm_device *dev, obj->dev = dev; obj->filp = NULL; + drm_gem_object_set_cgroup(obj, current); + kref_init(&obj->refcount); obj->handle_count = 0; obj->size = size; @@ -950,6 +1036,9 @@ drm_gem_object_release(struct drm_gem_object *obj) dma_resv_fini(&obj->_resv); drm_gem_free_mmap_offset(obj); + + /* Release reference on cgroup used with GEM object charging */ + drm_gem_object_unset_cgroup(obj); } EXPORT_SYMBOL(drm_gem_object_release); diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 240049566592..06ea10fc17bc 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -37,6 +37,7 @@ #include #include +#include #include struct dma_buf_map; @@ -222,6 +223,17 @@ struct drm_gem_object { */ struct file *filp; + /** + * @drmcg: + * + * cgroup used for charging GEM object page allocations against. This + * is set to the current cgroup during GEM object creation. + * Charging policy is up to the DRM driver to implement and should be + * charged when allocating backing store from device memory. + */ + struct drmcg *drmcg; + atomic64_t drmcg_bytes_charged; + /** * @vma_node: * @@ -417,4 +429,9 @@ int drm_gem_fence_array_add_implicit(struct xarray *fence_array, int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, u32 handle, u64 *offset); +void drm_gem_object_set_cgroup(struct drm_gem_object *obj, + struct task_struct *task); +void drm_gem_object_unset_cgroup(struct drm_gem_object *obj); +int drm_gem_object_charge_mem(struct drm_gem_object *obj, u64 size); +void drm_gem_object_uncharge_mem(struct drm_gem_object *obj, u64 size); #endif /* __DRM_GEM_H__ */ From patchwork Tue Jan 26 21:46:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Welty, Brian" X-Patchwork-Id: 12048413 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D965C433E0 for ; Tue, 26 Jan 2021 21:45:18 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1C5D520656 for ; Tue, 26 Jan 2021 21:45:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1C5D520656 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8DDB16E4CA; Tue, 26 Jan 2021 21:44:42 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 14CE46E466; Tue, 26 Jan 2021 21:44:39 +0000 (UTC) IronPort-SDR: kRyTBmGzx4AWPKJyjIR+6tuiXjgXmJkWLMiTV+xyW2gNawMBHaGP3xdNcxgaYk4RsjKI4IEGhI w5VTmpF73WVg== X-IronPort-AV: E=McAfee;i="6000,8403,9876"; a="198770835" X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="198770835" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2021 13:44:38 -0800 IronPort-SDR: zc66kQ1JtSLeYK+wt641PVVb/HET+nEaDxne1KFIOAlpQAAsXthG14gnFUqzJrerD6iJkLIOGH +M/naXge3Lrw== X-IronPort-AV: E=Sophos;i="5.79,377,1602572400"; d="scan'208";a="362139908" Received: from nvishwa1-desk.sc.intel.com ([172.25.29.76]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-SHA; 26 Jan 2021 13:44:37 -0800 From: Brian Welty To: Brian Welty , cgroups@vger.kernel.org, Tejun Heo , dri-devel@lists.freedesktop.org, David Airlie , Daniel Vetter , =?utf-8?q?Christian_K=C3=B6nig?= , Kenny Ho , amd-gfx@lists.freedesktop.org, Chris Wilson , Tvrtko Ursulin , intel-gfx@lists.freedesktop.org, Joonas Lahtinen , Eero Tamminen Date: Tue, 26 Jan 2021 13:46:26 -0800 Message-Id: <20210126214626.16260-10-brian.welty@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210126214626.16260-1-brian.welty@intel.com> References: <20210126214626.16260-1-brian.welty@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [RFC PATCH 9/9] drm/i915: Use memory cgroup for enforcing device memory limit X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To charge device memory allocations, we need to (1) identify appropriate cgroup to charge (currently decided at object creation time), and (2) make the charging call at the time that memory pages are being allocated. For (1), see prior DRM patch which associates current task's cgroup with GEM objects as they are created. That cgroup will be charged/uncharged for all paging activity against the GEM object. For (2), we call drm_get_object_charge_mem() in .get_pages callback for the GEM object type. Uncharging is done in .put_pages when the memory is marked such that it can be evicted. The try_charge() call will fail with -ENOMEM if the current memory allocation will exceed the cgroup device memory maximum, and allow for driver to perform memory reclaim. We also set the total device memory reported by DRM cgroup by storing in drm_device.drmcg_props after initializing LMEM memory regions. FIXME: to release drm cgroup reference requires this additional patch: https://patchwork.freedesktop.org/patch/349029 Signed-off-by: Brian Welty --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_region.c | 23 ++++++++++++++++++---- drivers/gpu/drm/i915/intel_memory_region.c | 13 ++++++++++-- drivers/gpu/drm/i915/intel_memory_region.h | 2 +- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index ec28a6cde49b..9fbe91d4d2f1 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -16,6 +16,7 @@ #include "i915_gem_gtt.h" #include "i915_gem_ioctls.h" #include "i915_gem_object.h" +#include "i915_gem_lmem.h" #include "i915_gem_mman.h" #include "i915_trace.h" #include "i915_user_extensions.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c index 3e3dad22a683..690b36b25984 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c @@ -12,11 +12,14 @@ void i915_gem_object_put_pages_buddy(struct drm_i915_gem_object *obj, struct sg_table *pages) { - __intel_memory_region_put_pages_buddy(obj->mm.region, &obj->mm.blocks); + u64 freed; + freed = __intel_memory_region_put_pages_buddy(obj->mm.region, + &obj->mm.blocks); obj->mm.dirty = false; sg_free_table(pages); kfree(pages); + drm_gem_object_uncharge_mem(&obj->base, freed); } int @@ -25,7 +28,7 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj) const u64 max_segment = i915_sg_segment_size(); struct intel_memory_region *mem = obj->mm.region; struct list_head *blocks = &obj->mm.blocks; - resource_size_t size = obj->base.size; + resource_size_t charged, size = obj->base.size; resource_size_t prev_end; struct i915_buddy_block *block; unsigned int flags; @@ -44,12 +47,22 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj) } flags = I915_ALLOC_MIN_PAGE_SIZE; - if (obj->flags & I915_BO_ALLOC_CONTIGUOUS) + if (obj->flags & I915_BO_ALLOC_CONTIGUOUS) { flags |= I915_ALLOC_CONTIGUOUS; + charged = roundup_pow_of_two(size); + } else { + charged = size; + } + + ret = drm_gem_object_charge_mem(&obj->base, charged); + if (ret) { + DRM_DEBUG("DRMCG: charge_mem failed for %lld\n", charged); + goto err_free_sg; + } ret = __intel_memory_region_get_pages_buddy(mem, size, flags, blocks); if (ret) - goto err_free_sg; + goto err_uncharge; GEM_BUG_ON(list_empty(blocks)); @@ -99,6 +112,8 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj) return 0; +err_uncharge: + drm_gem_object_uncharge_mem(&obj->base, charged); err_free_sg: sg_free_table(st); kfree(st); diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index 1bfcdd89b241..9b1edbf4361c 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -46,13 +46,18 @@ intel_memory_region_free_pages(struct intel_memory_region *mem, return size; } -void +u64 __intel_memory_region_put_pages_buddy(struct intel_memory_region *mem, struct list_head *blocks) { + u64 freed; + mutex_lock(&mem->mm_lock); - mem->avail += intel_memory_region_free_pages(mem, blocks); + freed = intel_memory_region_free_pages(mem, blocks); + mem->avail += freed; mutex_unlock(&mem->mm_lock); + + return freed; } void @@ -241,6 +246,7 @@ void intel_memory_region_put(struct intel_memory_region *mem) int intel_memory_regions_hw_probe(struct drm_i915_private *i915) { + u64 lmem_total = 0; int err, i; for (i = 0; i < ARRAY_SIZE(i915->mm.regions); i++) { @@ -260,6 +266,7 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915) break; case INTEL_MEMORY_LOCAL: mem = intel_setup_fake_lmem(i915); + lmem_total += mem->total; break; } @@ -278,6 +285,8 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915) i915->mm.regions[i] = mem; } + i915->drm.drmcg_props.memory_total = lmem_total; + return 0; out_cleanup: diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index 6ffc0673f005..c9fca951a372 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -109,7 +109,7 @@ struct i915_buddy_block * __intel_memory_region_get_block_buddy(struct intel_memory_region *mem, resource_size_t size, unsigned int flags); -void __intel_memory_region_put_pages_buddy(struct intel_memory_region *mem, +u64 __intel_memory_region_put_pages_buddy(struct intel_memory_region *mem, struct list_head *blocks); void __intel_memory_region_put_block_buddy(struct i915_buddy_block *block);