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