All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Intel-gfx@lists.freedesktop.org
Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Tejun Heo" <tj@kernel.org>,
	"Johannes Weiner" <hannes@cmpxchg.org>,
	"Zefan Li" <lizefan.x@bytedance.com>,
	"Dave Airlie" <airlied@redhat.com>,
	"Daniel Vetter" <daniel.vetter@ffwll.ch>,
	"Rob Clark" <robdclark@chromium.org>,
	"Stéphane Marchesin" <marcheu@chromium.org>,
	"T . J . Mercier" <tjmercier@google.com>,
	Kenny.Ho@amd.com, "Christian König" <christian.koenig@amd.com>,
	"Brian Welty" <brian.welty@intel.com>,
	"Tvrtko Ursulin" <tvrtko.ursulin@intel.com>
Subject: [RFC 03/17] cgroup/drm: Support cgroup priority control
Date: Wed, 19 Oct 2022 18:32:40 +0100	[thread overview]
Message-ID: <20221019173254.3361334-4-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20221019173254.3361334-1-tvrtko.ursulin@linux.intel.com>

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

A lot of the drm drivers support a concept of a scheduling priority. Add
support for controlling it via the drm cgroup controller.

Abstract priority control range of [DRM_CGROUP_PRIORITY_MIN,
DRM_CGROUP_PRIORITY_MAX] is used and each group hierarchy adjusts it's
base level based on a priority of its parent. In terms of an example that
looks like this:

       P=-1000
          /\
         /  \
        /    \
      A=0   B=100

This results in the effective priority of a group A of -1000 and B of
-900. In other words the fact B is configured for elevated priority is
relative to the parent being a low priority and hence is only elevated in
the context of its siblings.

Implementation does not impose any further policy and leaves sensible
configuration to the system administrator.

Individual drm drivers are expected to transparently convert the drm
cgroup priority into values suitable for their capabilities.

No guarantees on effectiveness or granularity are provided by the
controller, apart the available range being chosen to be an integer and
hence allowing a generic concept of normal (zero), lower (negative values)
and higher (positive values).

Every cgroup starts with a default priority of zero.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 Documentation/admin-guide/cgroup-v2.rst |  58 +++++++++++++
 include/linux/cgroup_drm.h              |   4 +
 kernel/cgroup/drm.c                     | 110 ++++++++++++++++++++++++
 3 files changed, 172 insertions(+)

diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index dc254a3cb956..0a6d97c83ea4 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -2398,6 +2398,64 @@ HugeTLB Interface Files
         hugetlb pages of <hugepagesize> in this cgroup.  Only active in
         use hugetlb pages are included.  The per-node values are in bytes.
 
+DRM
+---
+
+The DRM controller allows configuring static hierarchical scheduling priority.
+
+DRM static priority control
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Static priority control exposes a hierarchical control interface for the
+scheduling priority support present in many DRM device drivers.
+
+Hierarchical meaning that the child group priorities are relative to their
+parent. As an example:
+
+	A=-1000
+	   /\
+	  /  \
+	 /    \
+	B=0   C=100
+
+This results in the effective priority of a group B of -1000 and C of -900. In
+other words the fact C is configured for elevated priority is relative to its
+parent being a low priority and hence is only elevated in the context of its
+siblings.
+
+The scope of individual DRM scheduling priority may be per device or per device
+driver, or a combination of both, depending on the implementation. The
+controller does not ensure any priority ordering across multiple DRM drivers nor
+does it impose any further policy and leaves desired configuration to the system
+administrator.
+
+Individual DRM drivers are required to transparently convert the cgroup priority
+into values suitable for their capabilities.
+
+No guarantees on effectiveness or granularity are provided by the controller,
+apart the available range being chosen to be an integer and hence allowing a
+generic concept of normal (zero), lower (negative values) and higher (positive
+values) priority.
+
+DRM static priority interface files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  drm.priority_levels
+	One of:
+	 1) And integer representing the minimum number of discrete priority
+	    levels for the whole group.
+	 2) '0'- indicating one or more DRM clients in the group has no support
+	    for static priority control.
+	 3) 'n/a' - when there are no DRM clients in the configured group.
+
+  drm.priority
+	A read-write integer between -10000 and 10000 (inclusive) representing
+	an abstract static priority level.
+
+  drm.effective_priority
+	Read only integer showing the current effective priority level for the
+	group. Effective meaning taking into account the chain of inherited
+
 Misc
 ----
 
diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h
index bf8abc6b8ebf..a59792ccb550 100644
--- a/include/linux/cgroup_drm.h
+++ b/include/linux/cgroup_drm.h
@@ -6,4 +6,8 @@
 #ifndef _CGROUP_DRM_H
 #define _CGROUP_DRM_H
 
+#define DRM_CGROUP_PRIORITY_MIN	(-10000)
+#define DRM_CGROUP_PRIORITY_DEF	(0)
+#define DRM_CGROUP_PRIORITY_MAX	(10000)
+
 #endif	/* _CGROUP_DRM_H */
diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c
index b88c93661df3..2350e1f8a48a 100644
--- a/kernel/cgroup/drm.c
+++ b/kernel/cgroup/drm.c
@@ -6,24 +6,117 @@
 #include <linux/slab.h>
 #include <linux/cgroup.h>
 #include <linux/cgroup_drm.h>
+#include <linux/minmax.h>
+#include <linux/mutex.h>
 #include <linux/sched.h>
 
 struct drm_cgroup_state {
 	struct cgroup_subsys_state css;
+
+	int priority;
+	int effective_priority;
 };
 
+static DEFINE_MUTEX(drmcg_mutex);
+
 static inline struct drm_cgroup_state *
 css_to_drmcs(struct cgroup_subsys_state *css)
 {
 	return container_of(css, struct drm_cgroup_state, css);
 }
 
+static int drmcs_show_priority_levels(struct seq_file *sf, void *v)
+{
+	seq_printf(sf, "%u\n", 0);
+
+	return 0;
+}
+
+static s64
+drmcs_read_effective_priority(struct cgroup_subsys_state *css,
+			      struct cftype *cft)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	return drmcs->effective_priority;
+}
+
+static s64
+drmcs_read_priority(struct cgroup_subsys_state *css, struct cftype *cft)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	return drmcs->priority;
+}
+
+static void update_priority(struct drm_cgroup_state *drmcs, int priority)
+{
+	struct cgroup_subsys_state *node;
+
+	lockdep_assert_held(&drmcg_mutex);
+
+	if (priority == drmcs->priority)
+		return;
+
+	drmcs->priority = priority;
+
+	rcu_read_lock();
+	css_for_each_descendant_pre(node, &drmcs->css) {
+		struct drm_cgroup_state *dnode = css_to_drmcs(node);
+		int pprio;
+
+		if (!node->parent)
+			pprio = DRM_CGROUP_PRIORITY_DEF;
+		else
+			pprio = css_to_drmcs(node->parent)->effective_priority;
+
+		dnode->effective_priority =
+			clamp(pprio + dnode->priority,
+			      DRM_CGROUP_PRIORITY_MIN,
+			      DRM_CGROUP_PRIORITY_MAX);
+	}
+	rcu_read_unlock();
+}
+
+static int
+drmcs_write_priority(struct cgroup_subsys_state *css, struct cftype *cftype,
+		     s64 priority)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+	int ret;
+
+	if (priority < (s64)DRM_CGROUP_PRIORITY_MIN ||
+	    priority > (s64)DRM_CGROUP_PRIORITY_MAX)
+		return -ERANGE;
+
+	ret = mutex_lock_interruptible(&drmcg_mutex);
+	if (ret)
+		return ret;
+	update_priority(drmcs, (int)priority);
+	mutex_unlock(&drmcg_mutex);
+
+	return 0;
+}
+
+static int drmcs_online(struct cgroup_subsys_state *css)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	mutex_lock(&drmcg_mutex);
+	update_priority(drmcs, DRM_CGROUP_PRIORITY_DEF);
+	mutex_unlock(&drmcg_mutex);
+
+	return 0;
+}
+
 static void drmcs_free(struct cgroup_subsys_state *css)
 {
 	kfree(css_to_drmcs(css));
 }
 
 static struct drm_cgroup_state root_drmcs = {
+	.priority = DRM_CGROUP_PRIORITY_DEF,
+	.effective_priority = DRM_CGROUP_PRIORITY_DEF,
 };
 
 static struct cgroup_subsys_state *
@@ -42,12 +135,29 @@ drmcs_alloc(struct cgroup_subsys_state *parent_css)
 }
 
 struct cftype files[] = {
+	{
+		.name = "priority_levels",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.seq_show = drmcs_show_priority_levels,
+	},
+	{
+		.name = "priority",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_s64 = drmcs_read_priority,
+		.write_s64 = drmcs_write_priority,
+	},
+	{
+		.name = "effective_priority",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_s64 = drmcs_read_effective_priority,
+	},
 	{ } /* Zero entry terminates. */
 };
 
 struct cgroup_subsys drm_cgrp_subsys = {
 	.css_alloc	= drmcs_alloc,
 	.css_free	= drmcs_free,
+	.css_online	= drmcs_online,
 	.early_init	= false,
 	.legacy_cftypes	= files,
 	.dfl_cftypes	= files,
-- 
2.34.1


WARNING: multiple messages have this Message-ID (diff)
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Intel-gfx@lists.freedesktop.org
Cc: "Rob Clark" <robdclark@chromium.org>,
	Kenny.Ho@amd.com, "Daniel Vetter" <daniel.vetter@ffwll.ch>,
	"Johannes Weiner" <hannes@cmpxchg.org>,
	linux-kernel@vger.kernel.org,
	"Stéphane Marchesin" <marcheu@chromium.org>,
	"Christian König" <christian.koenig@amd.com>,
	"Zefan Li" <lizefan.x@bytedance.com>,
	"Dave Airlie" <airlied@redhat.com>, "Tejun Heo" <tj@kernel.org>,
	cgroups@vger.kernel.org, "T . J . Mercier" <tjmercier@google.com>
Subject: [Intel-gfx] [RFC 03/17] cgroup/drm: Support cgroup priority control
Date: Wed, 19 Oct 2022 18:32:40 +0100	[thread overview]
Message-ID: <20221019173254.3361334-4-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20221019173254.3361334-1-tvrtko.ursulin@linux.intel.com>

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

A lot of the drm drivers support a concept of a scheduling priority. Add
support for controlling it via the drm cgroup controller.

Abstract priority control range of [DRM_CGROUP_PRIORITY_MIN,
DRM_CGROUP_PRIORITY_MAX] is used and each group hierarchy adjusts it's
base level based on a priority of its parent. In terms of an example that
looks like this:

       P=-1000
          /\
         /  \
        /    \
      A=0   B=100

This results in the effective priority of a group A of -1000 and B of
-900. In other words the fact B is configured for elevated priority is
relative to the parent being a low priority and hence is only elevated in
the context of its siblings.

Implementation does not impose any further policy and leaves sensible
configuration to the system administrator.

Individual drm drivers are expected to transparently convert the drm
cgroup priority into values suitable for their capabilities.

No guarantees on effectiveness or granularity are provided by the
controller, apart the available range being chosen to be an integer and
hence allowing a generic concept of normal (zero), lower (negative values)
and higher (positive values).

Every cgroup starts with a default priority of zero.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 Documentation/admin-guide/cgroup-v2.rst |  58 +++++++++++++
 include/linux/cgroup_drm.h              |   4 +
 kernel/cgroup/drm.c                     | 110 ++++++++++++++++++++++++
 3 files changed, 172 insertions(+)

diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index dc254a3cb956..0a6d97c83ea4 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -2398,6 +2398,64 @@ HugeTLB Interface Files
         hugetlb pages of <hugepagesize> in this cgroup.  Only active in
         use hugetlb pages are included.  The per-node values are in bytes.
 
+DRM
+---
+
+The DRM controller allows configuring static hierarchical scheduling priority.
+
+DRM static priority control
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Static priority control exposes a hierarchical control interface for the
+scheduling priority support present in many DRM device drivers.
+
+Hierarchical meaning that the child group priorities are relative to their
+parent. As an example:
+
+	A=-1000
+	   /\
+	  /  \
+	 /    \
+	B=0   C=100
+
+This results in the effective priority of a group B of -1000 and C of -900. In
+other words the fact C is configured for elevated priority is relative to its
+parent being a low priority and hence is only elevated in the context of its
+siblings.
+
+The scope of individual DRM scheduling priority may be per device or per device
+driver, or a combination of both, depending on the implementation. The
+controller does not ensure any priority ordering across multiple DRM drivers nor
+does it impose any further policy and leaves desired configuration to the system
+administrator.
+
+Individual DRM drivers are required to transparently convert the cgroup priority
+into values suitable for their capabilities.
+
+No guarantees on effectiveness or granularity are provided by the controller,
+apart the available range being chosen to be an integer and hence allowing a
+generic concept of normal (zero), lower (negative values) and higher (positive
+values) priority.
+
+DRM static priority interface files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  drm.priority_levels
+	One of:
+	 1) And integer representing the minimum number of discrete priority
+	    levels for the whole group.
+	 2) '0'- indicating one or more DRM clients in the group has no support
+	    for static priority control.
+	 3) 'n/a' - when there are no DRM clients in the configured group.
+
+  drm.priority
+	A read-write integer between -10000 and 10000 (inclusive) representing
+	an abstract static priority level.
+
+  drm.effective_priority
+	Read only integer showing the current effective priority level for the
+	group. Effective meaning taking into account the chain of inherited
+
 Misc
 ----
 
diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h
index bf8abc6b8ebf..a59792ccb550 100644
--- a/include/linux/cgroup_drm.h
+++ b/include/linux/cgroup_drm.h
@@ -6,4 +6,8 @@
 #ifndef _CGROUP_DRM_H
 #define _CGROUP_DRM_H
 
+#define DRM_CGROUP_PRIORITY_MIN	(-10000)
+#define DRM_CGROUP_PRIORITY_DEF	(0)
+#define DRM_CGROUP_PRIORITY_MAX	(10000)
+
 #endif	/* _CGROUP_DRM_H */
diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c
index b88c93661df3..2350e1f8a48a 100644
--- a/kernel/cgroup/drm.c
+++ b/kernel/cgroup/drm.c
@@ -6,24 +6,117 @@
 #include <linux/slab.h>
 #include <linux/cgroup.h>
 #include <linux/cgroup_drm.h>
+#include <linux/minmax.h>
+#include <linux/mutex.h>
 #include <linux/sched.h>
 
 struct drm_cgroup_state {
 	struct cgroup_subsys_state css;
+
+	int priority;
+	int effective_priority;
 };
 
+static DEFINE_MUTEX(drmcg_mutex);
+
 static inline struct drm_cgroup_state *
 css_to_drmcs(struct cgroup_subsys_state *css)
 {
 	return container_of(css, struct drm_cgroup_state, css);
 }
 
+static int drmcs_show_priority_levels(struct seq_file *sf, void *v)
+{
+	seq_printf(sf, "%u\n", 0);
+
+	return 0;
+}
+
+static s64
+drmcs_read_effective_priority(struct cgroup_subsys_state *css,
+			      struct cftype *cft)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	return drmcs->effective_priority;
+}
+
+static s64
+drmcs_read_priority(struct cgroup_subsys_state *css, struct cftype *cft)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	return drmcs->priority;
+}
+
+static void update_priority(struct drm_cgroup_state *drmcs, int priority)
+{
+	struct cgroup_subsys_state *node;
+
+	lockdep_assert_held(&drmcg_mutex);
+
+	if (priority == drmcs->priority)
+		return;
+
+	drmcs->priority = priority;
+
+	rcu_read_lock();
+	css_for_each_descendant_pre(node, &drmcs->css) {
+		struct drm_cgroup_state *dnode = css_to_drmcs(node);
+		int pprio;
+
+		if (!node->parent)
+			pprio = DRM_CGROUP_PRIORITY_DEF;
+		else
+			pprio = css_to_drmcs(node->parent)->effective_priority;
+
+		dnode->effective_priority =
+			clamp(pprio + dnode->priority,
+			      DRM_CGROUP_PRIORITY_MIN,
+			      DRM_CGROUP_PRIORITY_MAX);
+	}
+	rcu_read_unlock();
+}
+
+static int
+drmcs_write_priority(struct cgroup_subsys_state *css, struct cftype *cftype,
+		     s64 priority)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+	int ret;
+
+	if (priority < (s64)DRM_CGROUP_PRIORITY_MIN ||
+	    priority > (s64)DRM_CGROUP_PRIORITY_MAX)
+		return -ERANGE;
+
+	ret = mutex_lock_interruptible(&drmcg_mutex);
+	if (ret)
+		return ret;
+	update_priority(drmcs, (int)priority);
+	mutex_unlock(&drmcg_mutex);
+
+	return 0;
+}
+
+static int drmcs_online(struct cgroup_subsys_state *css)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	mutex_lock(&drmcg_mutex);
+	update_priority(drmcs, DRM_CGROUP_PRIORITY_DEF);
+	mutex_unlock(&drmcg_mutex);
+
+	return 0;
+}
+
 static void drmcs_free(struct cgroup_subsys_state *css)
 {
 	kfree(css_to_drmcs(css));
 }
 
 static struct drm_cgroup_state root_drmcs = {
+	.priority = DRM_CGROUP_PRIORITY_DEF,
+	.effective_priority = DRM_CGROUP_PRIORITY_DEF,
 };
 
 static struct cgroup_subsys_state *
@@ -42,12 +135,29 @@ drmcs_alloc(struct cgroup_subsys_state *parent_css)
 }
 
 struct cftype files[] = {
+	{
+		.name = "priority_levels",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.seq_show = drmcs_show_priority_levels,
+	},
+	{
+		.name = "priority",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_s64 = drmcs_read_priority,
+		.write_s64 = drmcs_write_priority,
+	},
+	{
+		.name = "effective_priority",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_s64 = drmcs_read_effective_priority,
+	},
 	{ } /* Zero entry terminates. */
 };
 
 struct cgroup_subsys drm_cgrp_subsys = {
 	.css_alloc	= drmcs_alloc,
 	.css_free	= drmcs_free,
+	.css_online	= drmcs_online,
 	.early_init	= false,
 	.legacy_cftypes	= files,
 	.dfl_cftypes	= files,
-- 
2.34.1


WARNING: multiple messages have this Message-ID (diff)
From: Tvrtko Ursulin <tvrtko.ursulin-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
To: Intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	"Tejun Heo" <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	"Johannes Weiner"
	<hannes-druUgvl0LCNAfugRpC6u6w@public.gmane.org>,
	"Zefan Li" <lizefan.x-EC8Uxl6Npydl57MIdRCFDg@public.gmane.org>,
	"Dave Airlie" <airlied-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
	"Daniel Vetter" <daniel.vetter-/w4YWyX8dFk@public.gmane.org>,
	"Rob Clark" <robdclark-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
	"Stéphane Marchesin"
	<marcheu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>,
	"T . J . Mercier"
	<tjmercier-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>,
	Kenny.Ho-5C7GfCeVMHo@public.gmane.org,
	"Christian König" <christian.koenig-5C7GfCeVMHo@public.gmane.org>,
	"Brian Welty"
	<brian.welty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	"Tvrtko Ursulin"
	<tvrtko.ursulin-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Subject: [RFC 03/17] cgroup/drm: Support cgroup priority control
Date: Wed, 19 Oct 2022 18:32:40 +0100	[thread overview]
Message-ID: <20221019173254.3361334-4-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20221019173254.3361334-1-tvrtko.ursulin-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

From: Tvrtko Ursulin <tvrtko.ursulin-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

A lot of the drm drivers support a concept of a scheduling priority. Add
support for controlling it via the drm cgroup controller.

Abstract priority control range of [DRM_CGROUP_PRIORITY_MIN,
DRM_CGROUP_PRIORITY_MAX] is used and each group hierarchy adjusts it's
base level based on a priority of its parent. In terms of an example that
looks like this:

       P=-1000
          /\
         /  \
        /    \
      A=0   B=100

This results in the effective priority of a group A of -1000 and B of
-900. In other words the fact B is configured for elevated priority is
relative to the parent being a low priority and hence is only elevated in
the context of its siblings.

Implementation does not impose any further policy and leaves sensible
configuration to the system administrator.

Individual drm drivers are expected to transparently convert the drm
cgroup priority into values suitable for their capabilities.

No guarantees on effectiveness or granularity are provided by the
controller, apart the available range being chosen to be an integer and
hence allowing a generic concept of normal (zero), lower (negative values)
and higher (positive values).

Every cgroup starts with a default priority of zero.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 Documentation/admin-guide/cgroup-v2.rst |  58 +++++++++++++
 include/linux/cgroup_drm.h              |   4 +
 kernel/cgroup/drm.c                     | 110 ++++++++++++++++++++++++
 3 files changed, 172 insertions(+)

diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index dc254a3cb956..0a6d97c83ea4 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -2398,6 +2398,64 @@ HugeTLB Interface Files
         hugetlb pages of <hugepagesize> in this cgroup.  Only active in
         use hugetlb pages are included.  The per-node values are in bytes.
 
+DRM
+---
+
+The DRM controller allows configuring static hierarchical scheduling priority.
+
+DRM static priority control
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Static priority control exposes a hierarchical control interface for the
+scheduling priority support present in many DRM device drivers.
+
+Hierarchical meaning that the child group priorities are relative to their
+parent. As an example:
+
+	A=-1000
+	   /\
+	  /  \
+	 /    \
+	B=0   C=100
+
+This results in the effective priority of a group B of -1000 and C of -900. In
+other words the fact C is configured for elevated priority is relative to its
+parent being a low priority and hence is only elevated in the context of its
+siblings.
+
+The scope of individual DRM scheduling priority may be per device or per device
+driver, or a combination of both, depending on the implementation. The
+controller does not ensure any priority ordering across multiple DRM drivers nor
+does it impose any further policy and leaves desired configuration to the system
+administrator.
+
+Individual DRM drivers are required to transparently convert the cgroup priority
+into values suitable for their capabilities.
+
+No guarantees on effectiveness or granularity are provided by the controller,
+apart the available range being chosen to be an integer and hence allowing a
+generic concept of normal (zero), lower (negative values) and higher (positive
+values) priority.
+
+DRM static priority interface files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  drm.priority_levels
+	One of:
+	 1) And integer representing the minimum number of discrete priority
+	    levels for the whole group.
+	 2) '0'- indicating one or more DRM clients in the group has no support
+	    for static priority control.
+	 3) 'n/a' - when there are no DRM clients in the configured group.
+
+  drm.priority
+	A read-write integer between -10000 and 10000 (inclusive) representing
+	an abstract static priority level.
+
+  drm.effective_priority
+	Read only integer showing the current effective priority level for the
+	group. Effective meaning taking into account the chain of inherited
+
 Misc
 ----
 
diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h
index bf8abc6b8ebf..a59792ccb550 100644
--- a/include/linux/cgroup_drm.h
+++ b/include/linux/cgroup_drm.h
@@ -6,4 +6,8 @@
 #ifndef _CGROUP_DRM_H
 #define _CGROUP_DRM_H
 
+#define DRM_CGROUP_PRIORITY_MIN	(-10000)
+#define DRM_CGROUP_PRIORITY_DEF	(0)
+#define DRM_CGROUP_PRIORITY_MAX	(10000)
+
 #endif	/* _CGROUP_DRM_H */
diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c
index b88c93661df3..2350e1f8a48a 100644
--- a/kernel/cgroup/drm.c
+++ b/kernel/cgroup/drm.c
@@ -6,24 +6,117 @@
 #include <linux/slab.h>
 #include <linux/cgroup.h>
 #include <linux/cgroup_drm.h>
+#include <linux/minmax.h>
+#include <linux/mutex.h>
 #include <linux/sched.h>
 
 struct drm_cgroup_state {
 	struct cgroup_subsys_state css;
+
+	int priority;
+	int effective_priority;
 };
 
+static DEFINE_MUTEX(drmcg_mutex);
+
 static inline struct drm_cgroup_state *
 css_to_drmcs(struct cgroup_subsys_state *css)
 {
 	return container_of(css, struct drm_cgroup_state, css);
 }
 
+static int drmcs_show_priority_levels(struct seq_file *sf, void *v)
+{
+	seq_printf(sf, "%u\n", 0);
+
+	return 0;
+}
+
+static s64
+drmcs_read_effective_priority(struct cgroup_subsys_state *css,
+			      struct cftype *cft)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	return drmcs->effective_priority;
+}
+
+static s64
+drmcs_read_priority(struct cgroup_subsys_state *css, struct cftype *cft)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	return drmcs->priority;
+}
+
+static void update_priority(struct drm_cgroup_state *drmcs, int priority)
+{
+	struct cgroup_subsys_state *node;
+
+	lockdep_assert_held(&drmcg_mutex);
+
+	if (priority == drmcs->priority)
+		return;
+
+	drmcs->priority = priority;
+
+	rcu_read_lock();
+	css_for_each_descendant_pre(node, &drmcs->css) {
+		struct drm_cgroup_state *dnode = css_to_drmcs(node);
+		int pprio;
+
+		if (!node->parent)
+			pprio = DRM_CGROUP_PRIORITY_DEF;
+		else
+			pprio = css_to_drmcs(node->parent)->effective_priority;
+
+		dnode->effective_priority =
+			clamp(pprio + dnode->priority,
+			      DRM_CGROUP_PRIORITY_MIN,
+			      DRM_CGROUP_PRIORITY_MAX);
+	}
+	rcu_read_unlock();
+}
+
+static int
+drmcs_write_priority(struct cgroup_subsys_state *css, struct cftype *cftype,
+		     s64 priority)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+	int ret;
+
+	if (priority < (s64)DRM_CGROUP_PRIORITY_MIN ||
+	    priority > (s64)DRM_CGROUP_PRIORITY_MAX)
+		return -ERANGE;
+
+	ret = mutex_lock_interruptible(&drmcg_mutex);
+	if (ret)
+		return ret;
+	update_priority(drmcs, (int)priority);
+	mutex_unlock(&drmcg_mutex);
+
+	return 0;
+}
+
+static int drmcs_online(struct cgroup_subsys_state *css)
+{
+	struct drm_cgroup_state *drmcs = css_to_drmcs(css);
+
+	mutex_lock(&drmcg_mutex);
+	update_priority(drmcs, DRM_CGROUP_PRIORITY_DEF);
+	mutex_unlock(&drmcg_mutex);
+
+	return 0;
+}
+
 static void drmcs_free(struct cgroup_subsys_state *css)
 {
 	kfree(css_to_drmcs(css));
 }
 
 static struct drm_cgroup_state root_drmcs = {
+	.priority = DRM_CGROUP_PRIORITY_DEF,
+	.effective_priority = DRM_CGROUP_PRIORITY_DEF,
 };
 
 static struct cgroup_subsys_state *
@@ -42,12 +135,29 @@ drmcs_alloc(struct cgroup_subsys_state *parent_css)
 }
 
 struct cftype files[] = {
+	{
+		.name = "priority_levels",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.seq_show = drmcs_show_priority_levels,
+	},
+	{
+		.name = "priority",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_s64 = drmcs_read_priority,
+		.write_s64 = drmcs_write_priority,
+	},
+	{
+		.name = "effective_priority",
+		.flags = CFTYPE_NOT_ON_ROOT,
+		.read_s64 = drmcs_read_effective_priority,
+	},
 	{ } /* Zero entry terminates. */
 };
 
 struct cgroup_subsys drm_cgrp_subsys = {
 	.css_alloc	= drmcs_alloc,
 	.css_free	= drmcs_free,
+	.css_online	= drmcs_online,
 	.early_init	= false,
 	.legacy_cftypes	= files,
 	.dfl_cftypes	= files,
-- 
2.34.1


  parent reply	other threads:[~2022-10-19 17:33 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-19 17:32 [RFC 00/17] DRM scheduling cgroup controller Tvrtko Ursulin
2022-10-19 17:32 ` Tvrtko Ursulin
2022-10-19 17:32 ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 01/17] cgroup: Add the DRM " Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 02/17] drm: Track clients per owning process Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-20  6:40   ` Christian König
2022-10-20  6:40     ` Christian König
2022-10-20  6:40     ` [Intel-gfx] " Christian König
2022-10-20  7:34     ` Tvrtko Ursulin
2022-10-20  7:34       ` Tvrtko Ursulin
2022-10-20  7:34       ` [Intel-gfx] " Tvrtko Ursulin
2022-10-20 11:33       ` Christian König
2022-10-20 11:33         ` Christian König
2022-10-20 11:33         ` [Intel-gfx] " Christian König
2022-10-27 14:35         ` Tvrtko Ursulin
2022-10-27 14:35           ` Tvrtko Ursulin
2022-10-27 14:35           ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` Tvrtko Ursulin [this message]
2022-10-19 17:32   ` [RFC 03/17] cgroup/drm: Support cgroup priority control Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 04/17] drm/cgroup: Allow safe external access to file_priv Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 05/17] drm: Connect priority updates to drm core Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-20  9:50   ` kernel test robot
2022-10-19 17:32 ` [RFC 06/17] drm: Only track clients which are providing drm_cgroup_ops Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [Intel-gfx] [RFC 07/17] drm/i915: i915 priority Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 08/17] drm: Allow for migration of clients Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 09/17] cgroup/drm: Introduce weight based drm cgroup control Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 10/17] drm: Add ability to query drm cgroup GPU time Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 11/17] drm: Add over budget signalling callback Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 12/17] cgroup/drm: Client exit hook Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 13/17] cgroup/drm: Ability to periodically scan cgroups for over budget GPU usage Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-21 22:52   ` T.J. Mercier
2022-10-21 22:52     ` T.J. Mercier
2022-10-21 22:52     ` [Intel-gfx] " T.J. Mercier
2022-10-27 14:45     ` Tvrtko Ursulin
2022-10-27 14:45       ` Tvrtko Ursulin
2022-10-27 14:45       ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [Intel-gfx] [RFC 14/17] cgroup/drm: Show group budget signaling capability in sysfs Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32 ` [RFC 15/17] drm/i915: Migrate client to new owner on context create Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` [Intel-gfx] " Tvrtko Ursulin
2022-10-19 17:32 ` [Intel-gfx] [RFC 16/17] drm/i915: Wire up with drm controller GPU time query Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32 ` [Intel-gfx] [RFC 17/17] drm/i915: Implement cgroup controller over budget throttling Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 17:32   ` Tvrtko Ursulin
2022-10-19 18:45 ` [RFC 00/17] DRM scheduling cgroup controller Tejun Heo
2022-10-19 18:45   ` Tejun Heo
2022-10-19 18:45   ` [Intel-gfx] " Tejun Heo
2022-10-27 14:32   ` Tvrtko Ursulin
2022-10-27 14:32     ` Tvrtko Ursulin
2022-10-27 14:32     ` [Intel-gfx] " Tvrtko Ursulin
2022-10-31 20:20     ` Tejun Heo
2022-10-31 20:20       ` Tejun Heo
2022-10-31 20:20       ` [Intel-gfx] " Tejun Heo
2022-11-09 16:59       ` Tvrtko Ursulin
2022-11-09 16:59         ` Tvrtko Ursulin
2022-11-09 16:59         ` Tvrtko Ursulin
2022-10-19 19:25 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221019173254.3361334-4-tvrtko.ursulin@linux.intel.com \
    --to=tvrtko.ursulin@linux.intel.com \
    --cc=Intel-gfx@lists.freedesktop.org \
    --cc=Kenny.Ho@amd.com \
    --cc=airlied@redhat.com \
    --cc=brian.welty@intel.com \
    --cc=cgroups@vger.kernel.org \
    --cc=christian.koenig@amd.com \
    --cc=daniel.vetter@ffwll.ch \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan.x@bytedance.com \
    --cc=marcheu@chromium.org \
    --cc=robdclark@chromium.org \
    --cc=tj@kernel.org \
    --cc=tjmercier@google.com \
    --cc=tvrtko.ursulin@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.