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