1 /* $NetBSD: intel_context.h,v 1.2 2021/12/18 23:45:30 riastradh Exp $ */
2
3 /*
4 * SPDX-License-Identifier: MIT
5 *
6 * Copyright © 2019 Intel Corporation
7 */
8
9 #ifndef __INTEL_CONTEXT_H__
10 #define __INTEL_CONTEXT_H__
11
12 #include <linux/bitops.h>
13 #include <linux/lockdep.h>
14 #include <linux/types.h>
15
16 #include "i915_active.h"
17 #include "intel_context_types.h"
18 #include "intel_engine_types.h"
19 #include "intel_ring_types.h"
20 #include "intel_timeline_types.h"
21
22 #define CE_TRACE(ce, fmt, ...) do { \
23 const struct intel_context *ce__ = (ce); \
24 ENGINE_TRACE(ce__->engine, "context:%llx " fmt, \
25 ce__->timeline->fence_context, \
26 ##__VA_ARGS__); \
27 } while (0)
28
29 void intel_context_init(struct intel_context *ce,
30 struct intel_engine_cs *engine);
31 void intel_context_fini(struct intel_context *ce);
32
33 struct intel_context *
34 intel_context_create(struct intel_engine_cs *engine);
35
36 int intel_context_alloc_state(struct intel_context *ce);
37
38 void intel_context_free(struct intel_context *ce);
39
40 /**
41 * intel_context_lock_pinned - Stablises the 'pinned' status of the HW context
42 * @ce - the context
43 *
44 * Acquire a lock on the pinned status of the HW context, such that the context
45 * can neither be bound to the GPU or unbound whilst the lock is held, i.e.
46 * intel_context_is_pinned() remains stable.
47 */
intel_context_lock_pinned(struct intel_context * ce)48 static inline int intel_context_lock_pinned(struct intel_context *ce)
49 __acquires(ce->pin_mutex)
50 {
51 return mutex_lock_interruptible(&ce->pin_mutex);
52 }
53
54 /**
55 * intel_context_is_pinned - Reports the 'pinned' status
56 * @ce - the context
57 *
58 * While in use by the GPU, the context, along with its ring and page
59 * tables is pinned into memory and the GTT.
60 *
61 * Returns: true if the context is currently pinned for use by the GPU.
62 */
63 static inline bool
intel_context_is_pinned(struct intel_context * ce)64 intel_context_is_pinned(struct intel_context *ce)
65 {
66 return atomic_read(&ce->pin_count);
67 }
68
69 /**
70 * intel_context_unlock_pinned - Releases the earlier locking of 'pinned' status
71 * @ce - the context
72 *
73 * Releases the lock earlier acquired by intel_context_unlock_pinned().
74 */
intel_context_unlock_pinned(struct intel_context * ce)75 static inline void intel_context_unlock_pinned(struct intel_context *ce)
76 __releases(ce->pin_mutex)
77 {
78 mutex_unlock(&ce->pin_mutex);
79 }
80
81 int __intel_context_do_pin(struct intel_context *ce);
82
intel_context_pin_if_active(struct intel_context * ce)83 static inline bool intel_context_pin_if_active(struct intel_context *ce)
84 {
85 return atomic_inc_not_zero(&ce->pin_count);
86 }
87
intel_context_pin(struct intel_context * ce)88 static inline int intel_context_pin(struct intel_context *ce)
89 {
90 if (likely(intel_context_pin_if_active(ce)))
91 return 0;
92
93 return __intel_context_do_pin(ce);
94 }
95
__intel_context_pin(struct intel_context * ce)96 static inline void __intel_context_pin(struct intel_context *ce)
97 {
98 GEM_BUG_ON(!intel_context_is_pinned(ce));
99 atomic_inc(&ce->pin_count);
100 }
101
102 void intel_context_unpin(struct intel_context *ce);
103
104 void intel_context_enter_engine(struct intel_context *ce);
105 void intel_context_exit_engine(struct intel_context *ce);
106
intel_context_enter(struct intel_context * ce)107 static inline void intel_context_enter(struct intel_context *ce)
108 {
109 lockdep_assert_held(&ce->timeline->mutex);
110 if (!ce->active_count++)
111 ce->ops->enter(ce);
112 }
113
intel_context_mark_active(struct intel_context * ce)114 static inline void intel_context_mark_active(struct intel_context *ce)
115 {
116 lockdep_assert_held(&ce->timeline->mutex);
117 ++ce->active_count;
118 }
119
intel_context_exit(struct intel_context * ce)120 static inline void intel_context_exit(struct intel_context *ce)
121 {
122 lockdep_assert_held(&ce->timeline->mutex);
123 GEM_BUG_ON(!ce->active_count);
124 if (!--ce->active_count)
125 ce->ops->exit(ce);
126 }
127
intel_context_get(struct intel_context * ce)128 static inline struct intel_context *intel_context_get(struct intel_context *ce)
129 {
130 kref_get(&ce->ref);
131 return ce;
132 }
133
intel_context_put(struct intel_context * ce)134 static inline void intel_context_put(struct intel_context *ce)
135 {
136 kref_put(&ce->ref, ce->ops->destroy);
137 }
138
139 static inline struct intel_timeline *__must_check
intel_context_timeline_lock(struct intel_context * ce)140 intel_context_timeline_lock(struct intel_context *ce)
141 __acquires(&ce->timeline->mutex)
142 {
143 struct intel_timeline *tl = ce->timeline;
144 int err;
145
146 err = mutex_lock_interruptible(&tl->mutex);
147 if (err)
148 return ERR_PTR(err);
149
150 return tl;
151 }
152
intel_context_timeline_unlock(struct intel_timeline * tl)153 static inline void intel_context_timeline_unlock(struct intel_timeline *tl)
154 __releases(&tl->mutex)
155 {
156 mutex_unlock(&tl->mutex);
157 }
158
159 int intel_context_prepare_remote_request(struct intel_context *ce,
160 struct i915_request *rq);
161
162 struct i915_request *intel_context_create_request(struct intel_context *ce);
163
__intel_context_ring_size(u64 sz)164 static inline struct intel_ring *__intel_context_ring_size(u64 sz)
165 {
166 return u64_to_ptr(struct intel_ring, sz);
167 }
168
intel_context_is_barrier(const struct intel_context * ce)169 static inline bool intel_context_is_barrier(const struct intel_context *ce)
170 {
171 return test_bit(CONTEXT_BARRIER_BIT, &ce->flags);
172 }
173
intel_context_use_semaphores(const struct intel_context * ce)174 static inline bool intel_context_use_semaphores(const struct intel_context *ce)
175 {
176 return test_bit(CONTEXT_USE_SEMAPHORES, &ce->flags);
177 }
178
intel_context_set_use_semaphores(struct intel_context * ce)179 static inline void intel_context_set_use_semaphores(struct intel_context *ce)
180 {
181 set_bit(CONTEXT_USE_SEMAPHORES, &ce->flags);
182 }
183
intel_context_clear_use_semaphores(struct intel_context * ce)184 static inline void intel_context_clear_use_semaphores(struct intel_context *ce)
185 {
186 clear_bit(CONTEXT_USE_SEMAPHORES, &ce->flags);
187 }
188
intel_context_is_banned(const struct intel_context * ce)189 static inline bool intel_context_is_banned(const struct intel_context *ce)
190 {
191 return test_bit(CONTEXT_BANNED, &ce->flags);
192 }
193
intel_context_set_banned(struct intel_context * ce)194 static inline bool intel_context_set_banned(struct intel_context *ce)
195 {
196 return test_and_set_bit(CONTEXT_BANNED, &ce->flags);
197 }
198
199 static inline bool
intel_context_force_single_submission(const struct intel_context * ce)200 intel_context_force_single_submission(const struct intel_context *ce)
201 {
202 return test_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ce->flags);
203 }
204
205 static inline void
intel_context_set_single_submission(struct intel_context * ce)206 intel_context_set_single_submission(struct intel_context *ce)
207 {
208 __set_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ce->flags);
209 }
210
211 static inline bool
intel_context_nopreempt(const struct intel_context * ce)212 intel_context_nopreempt(const struct intel_context *ce)
213 {
214 return test_bit(CONTEXT_NOPREEMPT, &ce->flags);
215 }
216
217 static inline void
intel_context_set_nopreempt(struct intel_context * ce)218 intel_context_set_nopreempt(struct intel_context *ce)
219 {
220 set_bit(CONTEXT_NOPREEMPT, &ce->flags);
221 }
222
223 static inline void
intel_context_clear_nopreempt(struct intel_context * ce)224 intel_context_clear_nopreempt(struct intel_context *ce)
225 {
226 clear_bit(CONTEXT_NOPREEMPT, &ce->flags);
227 }
228
229 #endif /* __INTEL_CONTEXT_H__ */
230