To enable adding DRM cgroup support to the DRM scheduler we need a way for updating the relative scheduling weights per entity at the point the controller invokes a call-back notifying the driver of a new relative scheduling weight for a client.
We add two helpers which will allow drivers to opt-in into the tracking and they are responsible to call them at the correct times respective to the entity lifetime. Signed-off-by: Tvrtko Ursulin <tvrtko.ursu...@igalia.com> --- drivers/gpu/drm/drm_file.c | 3 ++ drivers/gpu/drm/scheduler/sched_entity.c | 25 ++++++++++++++++ include/drm/drm_file.h | 5 ++++ include/drm/gpu_scheduler.h | 38 ++++++++++++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 1520436c5491..c584d97e5f6c 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -48,6 +48,7 @@ #include <drm/drm_gem.h> #include <drm/drm_print.h> #include <drm/drm_debugfs.h> +#include <drm/gpu_scheduler.h> #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -162,6 +163,8 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor) mutex_init(&file->event_read_lock); mutex_init(&file->client_name_lock); + drm_sched_cgroup_init_drm_file(file); + if (drm_core_check_feature(dev, DRIVER_GEM)) drm_gem_open(dev, file); diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index ba290143c95d..e0c748c4c10f 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -25,6 +25,7 @@ #include <linux/slab.h> #include <linux/completion.h> +#include <drm/drm_file.h> #include <drm/drm_print.h> #include <drm/gpu_scheduler.h> @@ -131,6 +132,10 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, atomic_set(&entity->fence_seq, 0); entity->fence_context = dma_fence_context_alloc(2); +#if IS_ENABLED(CONFIG_CGROUP_DRM) + INIT_LIST_HEAD(&entity->drm_file_link); +#endif + return 0; } EXPORT_SYMBOL(drm_sched_entity_init); @@ -606,3 +611,23 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job) } } EXPORT_SYMBOL(drm_sched_entity_push_job); + +#if IS_ENABLED(CONFIG_CGROUP_DRM) +void drm_sched_cgroup_track_sched_entity(struct drm_file *file_priv, + struct drm_sched_entity *entity) +{ + spin_lock(&file_priv->sched_entities.lock); + list_add_tail(&entity->drm_file_link, &file_priv->sched_entities.list); + spin_unlock(&file_priv->sched_entities.lock); +} +EXPORT_SYMBOL(drm_sched_cgroup_track_sched_entity); + +void drm_sched_cgroup_untrack_sched_entity(struct drm_file *file_priv, + struct drm_sched_entity *entity) +{ + spin_lock(&file_priv->sched_entities.lock); + list_del(&entity->drm_file_link); + spin_unlock(&file_priv->sched_entities.lock); +} +EXPORT_SYMBOL(drm_sched_cgroup_untrack_sched_entity); +#endif diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 3326246a2f06..04cad0c61513 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -299,6 +299,11 @@ struct drm_file { #if IS_ENABLED(CONFIG_CGROUP_DRM) struct cgroup_subsys_state *__css; struct list_head clink; + + struct { + spinlock_t lock; + struct list_head list; + } sched_entities; #endif /** diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 7fbcd121a6d3..003b5904927f 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -240,6 +240,9 @@ struct drm_sched_entity { */ struct rb_node rb_tree_node; +#if IS_ENABLED(CONFIG_CGROUP_DRM) + struct list_head drm_file_link; +#endif }; /** @@ -700,4 +703,39 @@ void drm_sched_entity_modify_sched(struct drm_sched_entity *entity, struct drm_gpu_scheduler **sched_list, unsigned int num_sched_list); +#if IS_ENABLED(CONFIG_CGROUP_DRM) +#include <linux/list.h> +#include <linux/spinlock.h> + +#include <drm/drm_file.h> + +/* Static inline to allow drm.ko and gpu-sched.ko as modules. */ +static inline void drm_sched_cgroup_init_drm_file(struct drm_file *file_priv) +{ + spin_lock_init(&file_priv->sched_entities.lock); + INIT_LIST_HEAD(&file_priv->sched_entities.list); +} + +void drm_sched_cgroup_track_sched_entity(struct drm_file *file_priv, + struct drm_sched_entity *entity); +void drm_sched_cgroup_untrack_sched_entity(struct drm_file *file_priv, + struct drm_sched_entity *entity); +#else +static inline void drm_sched_cgroup_init_drm_file(struct drm_file *file_priv) +{ +} + +static inline void +drm_sched_cgroup_track_sched_entity(struct drm_file *file_priv, + struct drm_sched_entity *entity) +{ +} + +static inline void +drm_sched_cgroup_untrack_sched_entity(struct drm_file *file_priv, + struct drm_sched_entity *entity) +{ +} +#endif + #endif -- 2.48.0