diff options
Diffstat (limited to 'include/drm/gpu_scheduler.h')
-rw-r--r-- | include/drm/gpu_scheduler.h | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h new file mode 100644 index 000000000000..dfd54fb94e10 --- /dev/null +++ b/include/drm/gpu_scheduler.h | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Advanced Micro Devices, Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef _DRM_GPU_SCHEDULER_H_ | ||
25 | #define _DRM_GPU_SCHEDULER_H_ | ||
26 | |||
27 | #include <drm/spsc_queue.h> | ||
28 | #include <linux/dma-fence.h> | ||
29 | |||
30 | struct drm_gpu_scheduler; | ||
31 | struct drm_sched_rq; | ||
32 | |||
33 | enum drm_sched_priority { | ||
34 | DRM_SCHED_PRIORITY_MIN, | ||
35 | DRM_SCHED_PRIORITY_LOW = DRM_SCHED_PRIORITY_MIN, | ||
36 | DRM_SCHED_PRIORITY_NORMAL, | ||
37 | DRM_SCHED_PRIORITY_HIGH_SW, | ||
38 | DRM_SCHED_PRIORITY_HIGH_HW, | ||
39 | DRM_SCHED_PRIORITY_KERNEL, | ||
40 | DRM_SCHED_PRIORITY_MAX, | ||
41 | DRM_SCHED_PRIORITY_INVALID = -1, | ||
42 | DRM_SCHED_PRIORITY_UNSET = -2 | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * A scheduler entity is a wrapper around a job queue or a group | ||
47 | * of other entities. Entities take turns emitting jobs from their | ||
48 | * job queues to corresponding hardware ring based on scheduling | ||
49 | * policy. | ||
50 | */ | ||
51 | struct drm_sched_entity { | ||
52 | struct list_head list; | ||
53 | struct drm_sched_rq *rq; | ||
54 | spinlock_t rq_lock; | ||
55 | struct drm_gpu_scheduler *sched; | ||
56 | |||
57 | spinlock_t queue_lock; | ||
58 | struct spsc_queue job_queue; | ||
59 | |||
60 | atomic_t fence_seq; | ||
61 | uint64_t fence_context; | ||
62 | |||
63 | struct dma_fence *dependency; | ||
64 | struct dma_fence_cb cb; | ||
65 | atomic_t *guilty; /* points to ctx's guilty */ | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * Run queue is a set of entities scheduling command submissions for | ||
70 | * one specific ring. It implements the scheduling policy that selects | ||
71 | * the next entity to emit commands from. | ||
72 | */ | ||
73 | struct drm_sched_rq { | ||
74 | spinlock_t lock; | ||
75 | struct list_head entities; | ||
76 | struct drm_sched_entity *current_entity; | ||
77 | }; | ||
78 | |||
79 | struct drm_sched_fence { | ||
80 | struct dma_fence scheduled; | ||
81 | struct dma_fence finished; | ||
82 | struct dma_fence_cb cb; | ||
83 | struct dma_fence *parent; | ||
84 | struct drm_gpu_scheduler *sched; | ||
85 | spinlock_t lock; | ||
86 | void *owner; | ||
87 | }; | ||
88 | |||
89 | struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f); | ||
90 | |||
91 | struct drm_sched_job { | ||
92 | struct spsc_node queue_node; | ||
93 | struct drm_gpu_scheduler *sched; | ||
94 | struct drm_sched_fence *s_fence; | ||
95 | struct dma_fence_cb finish_cb; | ||
96 | struct work_struct finish_work; | ||
97 | struct list_head node; | ||
98 | struct delayed_work work_tdr; | ||
99 | uint64_t id; | ||
100 | atomic_t karma; | ||
101 | enum drm_sched_priority s_priority; | ||
102 | }; | ||
103 | |||
104 | static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job, | ||
105 | int threshold) | ||
106 | { | ||
107 | return (s_job && atomic_inc_return(&s_job->karma) > threshold); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Define the backend operations called by the scheduler, | ||
112 | * these functions should be implemented in driver side | ||
113 | */ | ||
114 | struct drm_sched_backend_ops { | ||
115 | struct dma_fence *(*dependency)(struct drm_sched_job *sched_job, | ||
116 | struct drm_sched_entity *s_entity); | ||
117 | struct dma_fence *(*run_job)(struct drm_sched_job *sched_job); | ||
118 | void (*timedout_job)(struct drm_sched_job *sched_job); | ||
119 | void (*free_job)(struct drm_sched_job *sched_job); | ||
120 | }; | ||
121 | |||
122 | /** | ||
123 | * One scheduler is implemented for each hardware ring | ||
124 | */ | ||
125 | struct drm_gpu_scheduler { | ||
126 | const struct drm_sched_backend_ops *ops; | ||
127 | uint32_t hw_submission_limit; | ||
128 | long timeout; | ||
129 | const char *name; | ||
130 | struct drm_sched_rq sched_rq[DRM_SCHED_PRIORITY_MAX]; | ||
131 | wait_queue_head_t wake_up_worker; | ||
132 | wait_queue_head_t job_scheduled; | ||
133 | atomic_t hw_rq_count; | ||
134 | atomic64_t job_id_count; | ||
135 | struct task_struct *thread; | ||
136 | struct list_head ring_mirror_list; | ||
137 | spinlock_t job_list_lock; | ||
138 | int hang_limit; | ||
139 | }; | ||
140 | |||
141 | int drm_sched_init(struct drm_gpu_scheduler *sched, | ||
142 | const struct drm_sched_backend_ops *ops, | ||
143 | uint32_t hw_submission, unsigned hang_limit, long timeout, | ||
144 | const char *name); | ||
145 | void drm_sched_fini(struct drm_gpu_scheduler *sched); | ||
146 | |||
147 | int drm_sched_entity_init(struct drm_gpu_scheduler *sched, | ||
148 | struct drm_sched_entity *entity, | ||
149 | struct drm_sched_rq *rq, | ||
150 | uint32_t jobs, atomic_t *guilty); | ||
151 | void drm_sched_entity_fini(struct drm_gpu_scheduler *sched, | ||
152 | struct drm_sched_entity *entity); | ||
153 | void drm_sched_entity_push_job(struct drm_sched_job *sched_job, | ||
154 | struct drm_sched_entity *entity); | ||
155 | void drm_sched_entity_set_rq(struct drm_sched_entity *entity, | ||
156 | struct drm_sched_rq *rq); | ||
157 | |||
158 | struct drm_sched_fence *drm_sched_fence_create( | ||
159 | struct drm_sched_entity *s_entity, void *owner); | ||
160 | void drm_sched_fence_scheduled(struct drm_sched_fence *fence); | ||
161 | void drm_sched_fence_finished(struct drm_sched_fence *fence); | ||
162 | int drm_sched_job_init(struct drm_sched_job *job, | ||
163 | struct drm_gpu_scheduler *sched, | ||
164 | struct drm_sched_entity *entity, | ||
165 | void *owner); | ||
166 | void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, | ||
167 | struct drm_sched_job *job); | ||
168 | void drm_sched_job_recovery(struct drm_gpu_scheduler *sched); | ||
169 | bool drm_sched_dependency_optimized(struct dma_fence* fence, | ||
170 | struct drm_sched_entity *entity); | ||
171 | void drm_sched_job_kickout(struct drm_sched_job *s_job); | ||
172 | |||
173 | #endif | ||