Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2025 Intel Corporation
4 */
5
6#include <linux/slab.h>
7
8#include <drm/gpu_scheduler.h>
9
10#include "xe_dep_job_types.h"
11#include "xe_dep_scheduler.h"
12#include "xe_device_types.h"
13
14/**
15 * DOC: Xe Dependency Scheduler
16 *
17 * The Xe dependency scheduler is a simple wrapper built around the DRM
18 * scheduler to execute jobs once their dependencies are resolved (i.e., all
19 * input fences specified as dependencies are signaled). The jobs that are
20 * executed contain virtual functions to run (execute) and free the job,
21 * allowing a single dependency scheduler to handle jobs performing different
22 * operations.
23 *
24 * Example use cases include deferred resource freeing, TLB invalidations after
25 * bind jobs, etc.
26 */
27
28/** struct xe_dep_scheduler - Generic Xe dependency scheduler */
29struct xe_dep_scheduler {
30 /** @sched: DRM GPU scheduler */
31 struct drm_gpu_scheduler sched;
32 /** @entity: DRM scheduler entity */
33 struct drm_sched_entity entity;
34 /** @rcu: For safe freeing of exported dma fences */
35 struct rcu_head rcu;
36};
37
38static struct dma_fence *xe_dep_scheduler_run_job(struct drm_sched_job *drm_job)
39{
40 struct xe_dep_job *dep_job =
41 container_of(drm_job, typeof(*dep_job), drm);
42
43 return dep_job->ops->run_job(dep_job);
44}
45
46static void xe_dep_scheduler_free_job(struct drm_sched_job *drm_job)
47{
48 struct xe_dep_job *dep_job =
49 container_of(drm_job, typeof(*dep_job), drm);
50
51 dep_job->ops->free_job(dep_job);
52}
53
54static const struct drm_sched_backend_ops sched_ops = {
55 .run_job = xe_dep_scheduler_run_job,
56 .free_job = xe_dep_scheduler_free_job,
57};
58
59/**
60 * xe_dep_scheduler_create() - Generic Xe dependency scheduler create
61 * @xe: Xe device
62 * @submit_wq: Submit workqueue struct (can be NULL)
63 * @name: Name of dependency scheduler
64 * @job_limit: Max dependency jobs that can be scheduled
65 *
66 * Create a generic Xe dependency scheduler and initialize internal DRM
67 * scheduler objects.
68 *
69 * Return: Generic Xe dependency scheduler object on success, ERR_PTR failure
70 */
71struct xe_dep_scheduler *
72xe_dep_scheduler_create(struct xe_device *xe,
73 struct workqueue_struct *submit_wq,
74 const char *name, u32 job_limit)
75{
76 struct xe_dep_scheduler *dep_scheduler;
77 struct drm_gpu_scheduler *sched;
78 const struct drm_sched_init_args args = {
79 .ops = &sched_ops,
80 .submit_wq = submit_wq,
81 .num_rqs = 1,
82 .credit_limit = job_limit,
83 .timeout = MAX_SCHEDULE_TIMEOUT,
84 .name = name,
85 .dev = xe->drm.dev,
86 };
87 int err;
88
89 dep_scheduler = kzalloc(sizeof(*dep_scheduler), GFP_KERNEL);
90 if (!dep_scheduler)
91 return ERR_PTR(-ENOMEM);
92
93 err = drm_sched_init(&dep_scheduler->sched, &args);
94 if (err)
95 goto err_free;
96
97 sched = &dep_scheduler->sched;
98 err = drm_sched_entity_init(&dep_scheduler->entity, 0, &sched, 1, NULL);
99 if (err)
100 goto err_sched;
101
102 init_rcu_head(&dep_scheduler->rcu);
103
104 return dep_scheduler;
105
106err_sched:
107 drm_sched_fini(&dep_scheduler->sched);
108err_free:
109 kfree(dep_scheduler);
110
111 return ERR_PTR(err);
112}
113
114/**
115 * xe_dep_scheduler_fini() - Generic Xe dependency scheduler finalize
116 * @dep_scheduler: Generic Xe dependency scheduler object
117 *
118 * Finalize internal DRM scheduler objects and free generic Xe dependency
119 * scheduler object
120 */
121void xe_dep_scheduler_fini(struct xe_dep_scheduler *dep_scheduler)
122{
123 drm_sched_entity_fini(&dep_scheduler->entity);
124 drm_sched_fini(&dep_scheduler->sched);
125 /*
126 * RCU free due sched being exported via DRM scheduler fences
127 * (timeline name).
128 */
129 kfree_rcu(dep_scheduler, rcu);
130}
131
132/**
133 * xe_dep_scheduler_entity() - Retrieve a generic Xe dependency scheduler
134 * DRM scheduler entity
135 * @dep_scheduler: Generic Xe dependency scheduler object
136 *
137 * Return: The generic Xe dependency scheduler's DRM scheduler entity
138 */
139struct drm_sched_entity *
140xe_dep_scheduler_entity(struct xe_dep_scheduler *dep_scheduler)
141{
142 return &dep_scheduler->entity;
143}