lkml.org 
[lkml]   [2022]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC 14/17] cgroup/drm: Show group budget signaling capability in sysfs
    Date
    From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

    Show overall status of a task group - whether all DRM clients in a group
    support over budget signaling, or some do not, or if there are no DRM
    clients in the group to start with.

    Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
    ---
    Documentation/admin-guide/cgroup-v2.rst | 7 ++++
    drivers/gpu/drm/drm_cgroup.c | 33 ++++++++++++++++
    include/drm/drm_clients.h | 7 ++++
    include/drm/drm_drv.h | 11 +++++-
    kernel/cgroup/drm.c | 52 +++++++++++++++++++++++++
    5 files changed, 109 insertions(+), 1 deletion(-)

    diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
    index 318f463a1316..6ee94ee109f0 100644
    --- a/Documentation/admin-guide/cgroup-v2.rst
    +++ b/Documentation/admin-guide/cgroup-v2.rst
    @@ -2491,6 +2491,13 @@ DRM scheduling soft limits interface files
    signal.
    Value of zero (defaul) disables the soft limit checking.

    + drm.budget_supported
    + One of:
    + 1) 'yes' - when all DRM clients in the group support the functionality.
    + 2) 'no' - when at least one of the DRM clients does not support the
    + functionality.
    + 3) 'n/a' - when there are no DRM clients in the group.
    +
    Misc
    ----

    diff --git a/drivers/gpu/drm/drm_cgroup.c b/drivers/gpu/drm/drm_cgroup.c
    index ff99d1f4f1d4..d2d8b2cb4ab3 100644
    --- a/drivers/gpu/drm/drm_cgroup.c
    +++ b/drivers/gpu/drm/drm_cgroup.c
    @@ -259,3 +259,36 @@ void drm_pid_signal_budget(struct pid *pid, u64 usage, u64 budget)
    rcu_read_unlock();
    }
    EXPORT_SYMBOL_GPL(drm_pid_signal_budget);
    +
    +enum drm_cg_supported drm_pid_signal_budget_supported(struct pid *pid)
    +{
    + enum drm_cg_supported supported = DRM_CG_NOT_APPLICABLE;
    + struct drm_pid_clients *clients;
    +
    + rcu_read_lock();
    + clients = xa_load(&drm_pid_clients, (unsigned long)pid);
    + if (clients) {
    + struct drm_file *fpriv;
    +
    + list_for_each_entry_rcu(fpriv, &clients->file_list, clink) {
    + const struct drm_cgroup_ops *cg_ops =
    + fpriv->minor->dev->driver->cg_ops;
    +
    + if (!cg_ops ||
    + !cg_ops->active_time_us ||
    + !cg_ops->signal_budget ||
    + cg_ops->signal_budget(fpriv, 0, 0) < 0) {
    + supported = DRM_CG_NOT_SUPPORTED;
    + break;
    + }
    +
    + if (supported == DRM_CG_NOT_APPLICABLE)
    + supported = DRM_CG_SUPPORTED;
    +
    + }
    + }
    + rcu_read_unlock();
    +
    + return supported;
    +}
    +EXPORT_SYMBOL_GPL(drm_pid_signal_budget_supported);
    diff --git a/include/drm/drm_clients.h b/include/drm/drm_clients.h
    index 7ad09fd0a404..5d14ae26ece6 100644
    --- a/include/drm/drm_clients.h
    +++ b/include/drm/drm_clients.h
    @@ -14,6 +14,12 @@ struct drm_pid_clients {
    struct rcu_head rcu;
    };

    +enum drm_cg_supported {
    + DRM_CG_NOT_APPLICABLE = -1,
    + DRM_CG_NOT_SUPPORTED = 0,
    + DRM_CG_SUPPORTED
    +};
    +
    #if IS_ENABLED(CONFIG_CGROUP_DRM)
    void drm_clients_close(struct drm_file *file_priv);
    int drm_clients_open(struct drm_file *file_priv);
    @@ -39,5 +45,6 @@ unsigned int drm_pid_priority_levels(struct pid *pid, bool *non_uniform);
    void drm_pid_update_priority(struct pid *pid, int priority);
    u64 drm_pid_get_active_time_us(struct pid *pid);
    void drm_pid_signal_budget(struct pid *pid, u64 usage, u64 budget);
    +enum drm_cg_supported drm_pid_signal_budget_supported(struct pid *pid);

    #endif
    diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
    index 07dec956ebfb..7a1a20d1b8de 100644
    --- a/include/drm/drm_drv.h
    +++ b/include/drm/drm_drv.h
    @@ -198,8 +198,17 @@ struct drm_cgroup_ops {
    *
    * Optional callback used by the DRM core to forward over/under GPU time
    * messages sent by the DRM cgroup controller.
    + *
    + * Zero used with zero budget is a special budgeting support status
    + * query which needs to return either zero or -EINVAL if client does not
    + * support budget control.
    + *
    + * Returns:
    + * * 1 when client has been throttled.
    + * * 0 when no action has been taken.
    + * * -EINVAL when not supported by the client.
    */
    - void (*signal_budget) (struct drm_file *, u64 used, u64 budget);
    + int (*signal_budget) (struct drm_file *, u64 used, u64 budget);
    };

    /**
    diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c
    index af50ead1564a..dd7db70c2831 100644
    --- a/kernel/cgroup/drm.c
    +++ b/kernel/cgroup/drm.c
    @@ -239,6 +239,53 @@ drmcs_write_weight(struct cgroup_subsys_state *css, struct cftype *cftype,
    return 0;
    }

    +static int drmcs_show_budget_supported(struct seq_file *sf, void *v)
    +{
    + struct drm_cgroup_state *drmcs = css_to_drmcs(seq_css(sf));
    + enum drm_cg_supported overall = DRM_CG_NOT_APPLICABLE;
    + struct cgroup *cgrp = drmcs->css.cgroup;
    + struct task_struct *task;
    + struct css_task_iter it;
    +
    + css_task_iter_start(&cgrp->self,
    + CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED,
    + &it);
    + while ((task = css_task_iter_next(&it))) {
    + enum drm_cg_supported supported;
    +
    + /* Ignore kernel threads here. */
    + if (task->flags & PF_KTHREAD)
    + continue;
    +
    + supported = drm_pid_signal_budget_supported(task_pid(task));
    + if (supported == DRM_CG_SUPPORTED &&
    + overall == DRM_CG_NOT_APPLICABLE) {
    + overall = DRM_CG_SUPPORTED;
    + } else if (supported == DRM_CG_NOT_SUPPORTED) {
    + overall = DRM_CG_NOT_SUPPORTED;
    + break;
    + }
    + }
    + css_task_iter_end(&it);
    +
    + switch (overall) {
    + case DRM_CG_NOT_APPLICABLE:
    + seq_puts(sf, "n/a\n");
    + break;
    + case DRM_CG_NOT_SUPPORTED:
    + seq_puts(sf, "no\n");
    + break;
    + case DRM_CG_SUPPORTED:
    + seq_puts(sf, "yes\n");
    + break;
    + default:
    + seq_printf(sf, "%u\n", overall);
    + break;
    + }
    +
    + return 0;
    +}
    +
    static int drmcs_online(struct cgroup_subsys_state *css)
    {
    struct drm_cgroup_state *drmcs = css_to_drmcs(css);
    @@ -690,6 +737,11 @@ struct cftype files[] = {
    .read_u64 = drmcs_read_weight,
    .write_u64 = drmcs_write_weight,
    },
    + {
    + .name = "budget_supported",
    + .flags = CFTYPE_NOT_ON_ROOT,
    + .seq_show = drmcs_show_budget_supported,
    + },
    {
    .name = "period_us",
    .flags = CFTYPE_NOT_ON_ROOT,
    --
    2.34.1
    \
     
     \ /
      Last update: 2022-10-19 19:36    [W:4.220 / U:0.424 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site