blob: 86acac010bb8c747d7aeee49aac489dccf348d5b [file] [log] [blame]
Chris Wilson688e6c72016-07-01 17:23:15 +01001/*
2 * Copyright © 2015 Intel Corporation
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 (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
Chris Wilsonc81d4612016-07-01 17:23:25 +010025#include <linux/kthread.h>
Ingo Molnarae7e81c2017-02-01 18:07:51 +010026#include <uapi/linux/sched/types.h>
Chris Wilsonc81d4612016-07-01 17:23:25 +010027
Chris Wilson688e6c72016-07-01 17:23:15 +010028#include "i915_drv.h"
29
Chris Wilsonb92326a2017-12-09 12:47:10 +000030#ifdef CONFIG_SMP
31#define task_asleep(tsk) ((tsk)->state & TASK_NORMAL && !(tsk)->on_cpu)
32#else
33#define task_asleep(tsk) ((tsk)->state & TASK_NORMAL)
34#endif
35
Chris Wilson67b807a82017-02-27 20:58:50 +000036static unsigned int __intel_breadcrumbs_wakeup(struct intel_breadcrumbs *b)
Chris Wilson8d769ea2017-02-27 20:58:47 +000037{
Chris Wilson56299fb2017-02-27 20:58:48 +000038 struct intel_wait *wait;
Chris Wilson8d769ea2017-02-27 20:58:47 +000039 unsigned int result = 0;
40
Chris Wilson61d3dc72017-03-03 19:08:24 +000041 lockdep_assert_held(&b->irq_lock);
42
43 wait = b->irq_wait;
Chris Wilson56299fb2017-02-27 20:58:48 +000044 if (wait) {
Chris Wilsonb92326a2017-12-09 12:47:10 +000045 /*
46 * N.B. Since task_asleep() and ttwu are not atomic, the
47 * waiter may actually go to sleep after the check, causing
48 * us to suppress a valid wakeup. We prefer to reduce the
49 * number of false positive missed_breadcrumb() warnings
50 * at the expense of a few false negatives, as it it easy
51 * to trigger a false positive under heavy load. Enough
52 * signal should remain from genuine missed_breadcrumb()
53 * for us to detect in CI.
54 */
55 bool was_asleep = task_asleep(wait->tsk);
56
Chris Wilson8d769ea2017-02-27 20:58:47 +000057 result = ENGINE_WAKEUP_WAITER;
Chris Wilsonb92326a2017-12-09 12:47:10 +000058 if (wake_up_process(wait->tsk) && was_asleep)
Chris Wilson67b807a82017-02-27 20:58:50 +000059 result |= ENGINE_WAKEUP_ASLEEP;
Chris Wilson8d769ea2017-02-27 20:58:47 +000060 }
Chris Wilson67b807a82017-02-27 20:58:50 +000061
62 return result;
63}
64
65unsigned int intel_engine_wakeup(struct intel_engine_cs *engine)
66{
67 struct intel_breadcrumbs *b = &engine->breadcrumbs;
Chris Wilson467221b2017-03-20 14:31:33 +000068 unsigned long flags;
Chris Wilson67b807a82017-02-27 20:58:50 +000069 unsigned int result;
70
Chris Wilson467221b2017-03-20 14:31:33 +000071 spin_lock_irqsave(&b->irq_lock, flags);
Chris Wilson67b807a82017-02-27 20:58:50 +000072 result = __intel_breadcrumbs_wakeup(b);
Chris Wilson467221b2017-03-20 14:31:33 +000073 spin_unlock_irqrestore(&b->irq_lock, flags);
Chris Wilson8d769ea2017-02-27 20:58:47 +000074
75 return result;
76}
77
Chris Wilson2246bea2017-02-17 15:13:00 +000078static unsigned long wait_timeout(void)
79{
80 return round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES);
81}
82
Chris Wilson80166e402017-02-28 08:50:18 +000083static noinline void missed_breadcrumb(struct intel_engine_cs *engine)
84{
Chris Wilson832265d2017-12-08 01:23:01 +000085 if (drm_debug & DRM_UT_DRIVER) {
86 struct drm_printer p = drm_debug_printer(__func__);
87
88 intel_engine_dump(engine, &p,
89 "%s missed breadcrumb at %pS\n",
90 engine->name, __builtin_return_address(0));
91 }
Chris Wilson80166e402017-02-28 08:50:18 +000092
93 set_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings);
94}
95
Kees Cook39cbf2a2017-10-17 09:53:04 +030096static void intel_breadcrumbs_hangcheck(struct timer_list *t)
Chris Wilson83348ba2016-08-09 17:47:51 +010097{
Chris Wilsonb92326a2017-12-09 12:47:10 +000098 struct intel_engine_cs *engine =
99 from_timer(engine, t, breadcrumbs.hangcheck);
Chris Wilson83348ba2016-08-09 17:47:51 +0100100 struct intel_breadcrumbs *b = &engine->breadcrumbs;
101
Chris Wilson67b807a82017-02-27 20:58:50 +0000102 if (!b->irq_armed)
Chris Wilson83348ba2016-08-09 17:47:51 +0100103 return;
104
Chris Wilson2246bea2017-02-17 15:13:00 +0000105 if (b->hangcheck_interrupts != atomic_read(&engine->irq_count)) {
106 b->hangcheck_interrupts = atomic_read(&engine->irq_count);
107 mod_timer(&b->hangcheck, wait_timeout());
Chris Wilson83348ba2016-08-09 17:47:51 +0100108 return;
109 }
110
Chris Wilsona6b0a1412017-03-15 22:22:59 +0000111 /* We keep the hangcheck timer alive until we disarm the irq, even
Chris Wilson67b807a82017-02-27 20:58:50 +0000112 * if there are no waiters at present.
113 *
114 * If the waiter was currently running, assume it hasn't had a chance
Chris Wilson89985672017-02-17 15:13:02 +0000115 * to process the pending interrupt (e.g, low priority task on a loaded
116 * system) and wait until it sleeps before declaring a missed interrupt.
Chris Wilson67b807a82017-02-27 20:58:50 +0000117 *
118 * If the waiter was asleep (and not even pending a wakeup), then we
119 * must have missed an interrupt as the GPU has stopped advancing
120 * but we still have a waiter. Assuming all batches complete within
121 * DRM_I915_HANGCHECK_JIFFIES [1.5s]!
Chris Wilson89985672017-02-17 15:13:02 +0000122 */
Chris Wilson67b807a82017-02-27 20:58:50 +0000123 if (intel_engine_wakeup(engine) & ENGINE_WAKEUP_ASLEEP) {
Chris Wilson80166e402017-02-28 08:50:18 +0000124 missed_breadcrumb(engine);
Chris Wilsonb92326a2017-12-09 12:47:10 +0000125 mod_timer(&b->fake_irq, jiffies + 1);
Chris Wilson67b807a82017-02-27 20:58:50 +0000126 } else {
Chris Wilson89985672017-02-17 15:13:02 +0000127 mod_timer(&b->hangcheck, wait_timeout());
Chris Wilson89985672017-02-17 15:13:02 +0000128 }
Chris Wilson83348ba2016-08-09 17:47:51 +0100129}
130
Kees Cook39cbf2a2017-10-17 09:53:04 +0300131static void intel_breadcrumbs_fake_irq(struct timer_list *t)
Chris Wilson688e6c72016-07-01 17:23:15 +0100132{
Kees Cook39cbf2a2017-10-17 09:53:04 +0300133 struct intel_engine_cs *engine = from_timer(engine, t,
134 breadcrumbs.fake_irq);
Chris Wilson67b807a82017-02-27 20:58:50 +0000135 struct intel_breadcrumbs *b = &engine->breadcrumbs;
Chris Wilson688e6c72016-07-01 17:23:15 +0100136
Chris Wilsona6b0a1412017-03-15 22:22:59 +0000137 /* The timer persists in case we cannot enable interrupts,
Chris Wilson688e6c72016-07-01 17:23:15 +0100138 * or if we have previously seen seqno/interrupt incoherency
Chris Wilsona6b0a1412017-03-15 22:22:59 +0000139 * ("missed interrupt" syndrome, better known as a "missed breadcrumb").
140 * Here the worker will wake up every jiffie in order to kick the
141 * oldest waiter to do the coherent seqno check.
Chris Wilson688e6c72016-07-01 17:23:15 +0100142 */
Chris Wilson67b807a82017-02-27 20:58:50 +0000143
Tvrtko Ursulina9e64932017-03-06 15:03:20 +0000144 spin_lock_irq(&b->irq_lock);
Chris Wilsonbcbd5c32017-10-25 15:39:42 +0100145 if (b->irq_armed && !__intel_breadcrumbs_wakeup(b))
Chris Wilson67b807a82017-02-27 20:58:50 +0000146 __intel_engine_disarm_breadcrumbs(engine);
Tvrtko Ursulina9e64932017-03-06 15:03:20 +0000147 spin_unlock_irq(&b->irq_lock);
Chris Wilson67b807a82017-02-27 20:58:50 +0000148 if (!b->irq_armed)
Chris Wilson19d0a572017-02-27 20:58:49 +0000149 return;
150
Chris Wilson67b807a82017-02-27 20:58:50 +0000151 mod_timer(&b->fake_irq, jiffies + 1);
Chris Wilson19d0a572017-02-27 20:58:49 +0000152
153 /* Ensure that even if the GPU hangs, we get woken up.
154 *
155 * However, note that if no one is waiting, we never notice
156 * a gpu hang. Eventually, we will have to wait for a resource
157 * held by the GPU and so trigger a hangcheck. In the most
158 * pathological case, this will be upon memory starvation! To
159 * prevent this, we also queue the hangcheck from the retire
160 * worker.
161 */
162 i915_queue_hangcheck(engine->i915);
Chris Wilson688e6c72016-07-01 17:23:15 +0100163}
164
165static void irq_enable(struct intel_engine_cs *engine)
166{
Chris Wilsonc16c4ba2017-11-07 10:20:03 +0000167 /*
168 * FIXME: Ideally we want this on the API boundary, but for the
169 * sake of testing with mock breadcrumbs (no HW so unable to
170 * enable irqs) we place it deep within the bowels, at the point
171 * of no return.
172 */
173 GEM_BUG_ON(!intel_irqs_enabled(engine->i915));
174
Chris Wilson3d5564e2016-07-01 17:23:23 +0100175 /* Enabling the IRQ may miss the generation of the interrupt, but
176 * we still need to force the barrier before reading the seqno,
177 * just in case.
178 */
Chris Wilson538b2572017-01-24 15:18:05 +0000179 set_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
Chris Wilson31bb59c2016-07-01 17:23:27 +0100180
Chris Wilsonf6168e32016-10-28 13:58:55 +0100181 /* Caller disables interrupts */
182 spin_lock(&engine->i915->irq_lock);
Chris Wilson31bb59c2016-07-01 17:23:27 +0100183 engine->irq_enable(engine);
Chris Wilsonf6168e32016-10-28 13:58:55 +0100184 spin_unlock(&engine->i915->irq_lock);
Chris Wilson688e6c72016-07-01 17:23:15 +0100185}
186
187static void irq_disable(struct intel_engine_cs *engine)
188{
Chris Wilsonf6168e32016-10-28 13:58:55 +0100189 /* Caller disables interrupts */
190 spin_lock(&engine->i915->irq_lock);
Chris Wilson31bb59c2016-07-01 17:23:27 +0100191 engine->irq_disable(engine);
Chris Wilsonf6168e32016-10-28 13:58:55 +0100192 spin_unlock(&engine->i915->irq_lock);
Chris Wilson688e6c72016-07-01 17:23:15 +0100193}
194
Chris Wilson67b807a82017-02-27 20:58:50 +0000195void __intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
196{
197 struct intel_breadcrumbs *b = &engine->breadcrumbs;
198
Chris Wilson61d3dc72017-03-03 19:08:24 +0000199 lockdep_assert_held(&b->irq_lock);
Chris Wilsone1c0c912017-03-06 09:29:15 +0000200 GEM_BUG_ON(b->irq_wait);
Chris Wilsonbcbd5c32017-10-25 15:39:42 +0100201 GEM_BUG_ON(!b->irq_armed);
Chris Wilson67b807a82017-02-27 20:58:50 +0000202
Chris Wilsonbcbd5c32017-10-25 15:39:42 +0100203 GEM_BUG_ON(!b->irq_enabled);
204 if (!--b->irq_enabled)
Chris Wilson67b807a82017-02-27 20:58:50 +0000205 irq_disable(engine);
Chris Wilson67b807a82017-02-27 20:58:50 +0000206
207 b->irq_armed = false;
208}
209
Chris Wilsonbcbd5c32017-10-25 15:39:42 +0100210void intel_engine_pin_breadcrumbs_irq(struct intel_engine_cs *engine)
211{
212 struct intel_breadcrumbs *b = &engine->breadcrumbs;
213
214 spin_lock_irq(&b->irq_lock);
215 if (!b->irq_enabled++)
216 irq_enable(engine);
217 GEM_BUG_ON(!b->irq_enabled); /* no overflow! */
218 spin_unlock_irq(&b->irq_lock);
219}
220
221void intel_engine_unpin_breadcrumbs_irq(struct intel_engine_cs *engine)
222{
223 struct intel_breadcrumbs *b = &engine->breadcrumbs;
224
225 spin_lock_irq(&b->irq_lock);
226 GEM_BUG_ON(!b->irq_enabled); /* no underflow! */
227 if (!--b->irq_enabled)
228 irq_disable(engine);
229 spin_unlock_irq(&b->irq_lock);
230}
231
Chris Wilson67b807a82017-02-27 20:58:50 +0000232void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine)
233{
234 struct intel_breadcrumbs *b = &engine->breadcrumbs;
Chris Wilson832265d2017-12-08 01:23:01 +0000235 struct intel_wait *wait, *n;
Chris Wilson67b807a82017-02-27 20:58:50 +0000236
237 if (!b->irq_armed)
Chris Wilson776bc272017-12-08 12:10:33 +0000238 goto wakeup_signaler;
Chris Wilson67b807a82017-02-27 20:58:50 +0000239
Chris Wilson832265d2017-12-08 01:23:01 +0000240 /*
241 * We only disarm the irq when we are idle (all requests completed),
Chris Wilsone1c0c912017-03-06 09:29:15 +0000242 * so if the bottom-half remains asleep, it missed the request
Chris Wilson67b807a82017-02-27 20:58:50 +0000243 * completion.
244 */
Chris Wilson832265d2017-12-08 01:23:01 +0000245 if (intel_engine_wakeup(engine) & ENGINE_WAKEUP_ASLEEP)
246 missed_breadcrumb(engine);
Chris Wilson67b807a82017-02-27 20:58:50 +0000247
Chris Wilsone1c0c912017-03-06 09:29:15 +0000248 spin_lock_irq(&b->rb_lock);
Chris Wilsona5cae7b2017-03-15 21:07:24 +0000249
250 spin_lock(&b->irq_lock);
Chris Wilson832265d2017-12-08 01:23:01 +0000251 b->irq_wait = NULL;
Chris Wilsone5330ac2017-10-31 12:22:35 +0000252 if (b->irq_armed)
253 __intel_engine_disarm_breadcrumbs(engine);
Chris Wilsona5cae7b2017-03-15 21:07:24 +0000254 spin_unlock(&b->irq_lock);
255
Chris Wilsone1c0c912017-03-06 09:29:15 +0000256 rbtree_postorder_for_each_entry_safe(wait, n, &b->waiters, node) {
257 RB_CLEAR_NODE(&wait->node);
Chris Wilson832265d2017-12-08 01:23:01 +0000258 wake_up_process(wait->tsk);
Chris Wilsone1c0c912017-03-06 09:29:15 +0000259 }
260 b->waiters = RB_ROOT;
261
Chris Wilsone1c0c912017-03-06 09:29:15 +0000262 spin_unlock_irq(&b->rb_lock);
Chris Wilson776bc272017-12-08 12:10:33 +0000263
264 /*
265 * The signaling thread may be asleep holding a reference to a request,
266 * that had its signaling cancelled prior to being preempted. We need
267 * to kick the signaler, just in case, to release any such reference.
268 */
269wakeup_signaler:
270 wake_up_process(b->signaler);
Chris Wilson67b807a82017-02-27 20:58:50 +0000271}
272
Chris Wilson6ef98ea2017-02-17 15:13:03 +0000273static bool use_fake_irq(const struct intel_breadcrumbs *b)
274{
275 const struct intel_engine_cs *engine =
276 container_of(b, struct intel_engine_cs, breadcrumbs);
277
278 if (!test_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings))
279 return false;
280
281 /* Only start with the heavy weight fake irq timer if we have not
282 * seen any interrupts since enabling it the first time. If the
283 * interrupts are still arriving, it means we made a mistake in our
284 * engine->seqno_barrier(), a timing error that should be transient
285 * and unlikely to reoccur.
286 */
287 return atomic_read(&engine->irq_count) == b->hangcheck_interrupts;
288}
289
Chris Wilson67b807a82017-02-27 20:58:50 +0000290static void enable_fake_irq(struct intel_breadcrumbs *b)
291{
292 /* Ensure we never sleep indefinitely */
293 if (!b->irq_enabled || use_fake_irq(b))
294 mod_timer(&b->fake_irq, jiffies + 1);
295 else
296 mod_timer(&b->hangcheck, wait_timeout());
297}
298
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100299static bool __intel_breadcrumbs_enable_irq(struct intel_breadcrumbs *b)
Chris Wilson688e6c72016-07-01 17:23:15 +0100300{
301 struct intel_engine_cs *engine =
302 container_of(b, struct intel_engine_cs, breadcrumbs);
303 struct drm_i915_private *i915 = engine->i915;
Chris Wilsonbcbd5c32017-10-25 15:39:42 +0100304 bool enabled;
305
Chris Wilson61d3dc72017-03-03 19:08:24 +0000306 lockdep_assert_held(&b->irq_lock);
Chris Wilson67b807a82017-02-27 20:58:50 +0000307 if (b->irq_armed)
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100308 return false;
Chris Wilson688e6c72016-07-01 17:23:15 +0100309
Chris Wilson67b807a82017-02-27 20:58:50 +0000310 /* The breadcrumb irq will be disarmed on the interrupt after the
311 * waiters are signaled. This gives us a single interrupt window in
312 * which we can add a new waiter and avoid the cost of re-enabling
313 * the irq.
314 */
315 b->irq_armed = true;
Chris Wilson67b807a82017-02-27 20:58:50 +0000316
Chris Wilsonf97fbf92017-02-13 17:15:14 +0000317 if (I915_SELFTEST_ONLY(b->mock)) {
318 /* For our mock objects we want to avoid interaction
319 * with the real hardware (which is not set up). So
320 * we simply pretend we have enabled the powerwell
321 * and the irq, and leave it up to the mock
322 * implementation to call intel_engine_wakeup()
323 * itself when it wants to simulate a user interrupt,
324 */
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100325 return true;
Chris Wilsonf97fbf92017-02-13 17:15:14 +0000326 }
327
Chris Wilson688e6c72016-07-01 17:23:15 +0100328 /* Since we are waiting on a request, the GPU should be busy
Chris Wilson67b807a82017-02-27 20:58:50 +0000329 * and should have its own rpm reference. This is tracked
330 * by i915->gt.awake, we can forgo holding our own wakref
331 * for the interrupt as before i915->gt.awake is released (when
332 * the driver is idle) we disarm the breadcrumbs.
Chris Wilson688e6c72016-07-01 17:23:15 +0100333 */
Chris Wilson688e6c72016-07-01 17:23:15 +0100334
335 /* No interrupts? Kick the waiter every jiffie! */
Chris Wilsonbcbd5c32017-10-25 15:39:42 +0100336 enabled = false;
337 if (!b->irq_enabled++ &&
338 !test_bit(engine->id, &i915->gpu_error.test_irq_rings)) {
339 irq_enable(engine);
340 enabled = true;
Chris Wilson688e6c72016-07-01 17:23:15 +0100341 }
342
Chris Wilson67b807a82017-02-27 20:58:50 +0000343 enable_fake_irq(b);
Chris Wilsonbcbd5c32017-10-25 15:39:42 +0100344 return enabled;
Chris Wilson688e6c72016-07-01 17:23:15 +0100345}
346
347static inline struct intel_wait *to_wait(struct rb_node *node)
348{
Chris Wilsond8567862016-12-20 10:40:03 +0000349 return rb_entry(node, struct intel_wait, node);
Chris Wilson688e6c72016-07-01 17:23:15 +0100350}
351
352static inline void __intel_breadcrumbs_finish(struct intel_breadcrumbs *b,
353 struct intel_wait *wait)
354{
Chris Wilson61d3dc72017-03-03 19:08:24 +0000355 lockdep_assert_held(&b->rb_lock);
Chris Wilson908a6cb2017-03-15 21:07:25 +0000356 GEM_BUG_ON(b->irq_wait == wait);
Chris Wilson688e6c72016-07-01 17:23:15 +0100357
358 /* This request is completed, so remove it from the tree, mark it as
Chris Wilsona6b0a1412017-03-15 22:22:59 +0000359 * complete, and *then* wake up the associated task. N.B. when the
360 * task wakes up, it will find the empty rb_node, discern that it
361 * has already been removed from the tree and skip the serialisation
362 * of the b->rb_lock and b->irq_lock. This means that the destruction
363 * of the intel_wait is not serialised with the interrupt handler
364 * by the waiter - it must instead be serialised by the caller.
Chris Wilson688e6c72016-07-01 17:23:15 +0100365 */
366 rb_erase(&wait->node, &b->waiters);
367 RB_CLEAR_NODE(&wait->node);
368
369 wake_up_process(wait->tsk); /* implicit smp_wmb() */
370}
371
Chris Wilsonb66255f2017-03-03 17:14:22 +0000372static inline void __intel_breadcrumbs_next(struct intel_engine_cs *engine,
373 struct rb_node *next)
374{
375 struct intel_breadcrumbs *b = &engine->breadcrumbs;
376
Chris Wilson61d3dc72017-03-03 19:08:24 +0000377 spin_lock(&b->irq_lock);
Chris Wilsonb66255f2017-03-03 17:14:22 +0000378 GEM_BUG_ON(!b->irq_armed);
Chris Wilson429732e2017-03-15 21:07:23 +0000379 GEM_BUG_ON(!b->irq_wait);
Chris Wilson61d3dc72017-03-03 19:08:24 +0000380 b->irq_wait = to_wait(next);
381 spin_unlock(&b->irq_lock);
Chris Wilsonb66255f2017-03-03 17:14:22 +0000382
383 /* We always wake up the next waiter that takes over as the bottom-half
384 * as we may delegate not only the irq-seqno barrier to the next waiter
385 * but also the task of waking up concurrent waiters.
386 */
387 if (next)
388 wake_up_process(to_wait(next)->tsk);
389}
390
Chris Wilson688e6c72016-07-01 17:23:15 +0100391static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
392 struct intel_wait *wait)
393{
394 struct intel_breadcrumbs *b = &engine->breadcrumbs;
395 struct rb_node **p, *parent, *completed;
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100396 bool first, armed;
Chris Wilson688e6c72016-07-01 17:23:15 +0100397 u32 seqno;
398
Chris Wilsonc68ce692018-01-02 19:25:00 +0000399 GEM_BUG_ON(!wait->seqno);
400
Chris Wilson688e6c72016-07-01 17:23:15 +0100401 /* Insert the request into the retirement ordered list
402 * of waiters by walking the rbtree. If we are the oldest
403 * seqno in the tree (the first to be retired), then
404 * set ourselves as the bottom-half.
405 *
406 * As we descend the tree, prune completed branches since we hold the
407 * spinlock we know that the first_waiter must be delayed and can
408 * reduce some of the sequential wake up latency if we take action
409 * ourselves and wake up the completed tasks in parallel. Also, by
410 * removing stale elements in the tree, we may be able to reduce the
411 * ping-pong between the old bottom-half and ourselves as first-waiter.
412 */
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100413 armed = false;
Chris Wilson688e6c72016-07-01 17:23:15 +0100414 first = true;
415 parent = NULL;
416 completed = NULL;
Chris Wilson1b7744e2016-07-01 17:23:17 +0100417 seqno = intel_engine_get_seqno(engine);
Chris Wilson688e6c72016-07-01 17:23:15 +0100418
419 /* If the request completed before we managed to grab the spinlock,
420 * return now before adding ourselves to the rbtree. We let the
421 * current bottom-half handle any pending wakeups and instead
422 * try and get out of the way quickly.
423 */
424 if (i915_seqno_passed(seqno, wait->seqno)) {
425 RB_CLEAR_NODE(&wait->node);
426 return first;
427 }
428
429 p = &b->waiters.rb_node;
430 while (*p) {
431 parent = *p;
432 if (wait->seqno == to_wait(parent)->seqno) {
433 /* We have multiple waiters on the same seqno, select
434 * the highest priority task (that with the smallest
435 * task->prio) to serve as the bottom-half for this
436 * group.
437 */
438 if (wait->tsk->prio > to_wait(parent)->tsk->prio) {
439 p = &parent->rb_right;
440 first = false;
441 } else {
442 p = &parent->rb_left;
443 }
444 } else if (i915_seqno_passed(wait->seqno,
445 to_wait(parent)->seqno)) {
446 p = &parent->rb_right;
447 if (i915_seqno_passed(seqno, to_wait(parent)->seqno))
448 completed = parent;
449 else
450 first = false;
451 } else {
452 p = &parent->rb_left;
453 }
454 }
455 rb_link_node(&wait->node, parent, p);
456 rb_insert_color(&wait->node, &b->waiters);
Chris Wilson688e6c72016-07-01 17:23:15 +0100457
Chris Wilson688e6c72016-07-01 17:23:15 +0100458 if (first) {
Chris Wilson61d3dc72017-03-03 19:08:24 +0000459 spin_lock(&b->irq_lock);
Chris Wilson61d3dc72017-03-03 19:08:24 +0000460 b->irq_wait = wait;
Chris Wilson04171312016-07-06 12:39:00 +0100461 /* After assigning ourselves as the new bottom-half, we must
462 * perform a cursory check to prevent a missed interrupt.
463 * Either we miss the interrupt whilst programming the hardware,
464 * or if there was a previous waiter (for a later seqno) they
465 * may be woken instead of us (due to the inherent race
Chris Wilsonaca34b62016-07-06 12:39:02 +0100466 * in the unlocked read of b->irq_seqno_bh in the irq handler)
467 * and so we miss the wake up.
Chris Wilson04171312016-07-06 12:39:00 +0100468 */
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100469 armed = __intel_breadcrumbs_enable_irq(b);
Chris Wilson61d3dc72017-03-03 19:08:24 +0000470 spin_unlock(&b->irq_lock);
Chris Wilson688e6c72016-07-01 17:23:15 +0100471 }
Chris Wilson429732e2017-03-15 21:07:23 +0000472
473 if (completed) {
Chris Wilsona6b0a1412017-03-15 22:22:59 +0000474 /* Advance the bottom-half (b->irq_wait) before we wake up
475 * the waiters who may scribble over their intel_wait
476 * just as the interrupt handler is dereferencing it via
477 * b->irq_wait.
478 */
Chris Wilson429732e2017-03-15 21:07:23 +0000479 if (!first) {
480 struct rb_node *next = rb_next(completed);
481 GEM_BUG_ON(next == &wait->node);
482 __intel_breadcrumbs_next(engine, next);
483 }
484
485 do {
486 struct intel_wait *crumb = to_wait(completed);
487 completed = rb_prev(completed);
488 __intel_breadcrumbs_finish(b, crumb);
489 } while (completed);
490 }
491
Chris Wilson61d3dc72017-03-03 19:08:24 +0000492 GEM_BUG_ON(!b->irq_wait);
Chris Wilson429732e2017-03-15 21:07:23 +0000493 GEM_BUG_ON(!b->irq_armed);
Chris Wilson61d3dc72017-03-03 19:08:24 +0000494 GEM_BUG_ON(rb_first(&b->waiters) != &b->irq_wait->node);
Chris Wilson688e6c72016-07-01 17:23:15 +0100495
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100496 return armed;
Chris Wilson688e6c72016-07-01 17:23:15 +0100497}
498
499bool intel_engine_add_wait(struct intel_engine_cs *engine,
500 struct intel_wait *wait)
501{
502 struct intel_breadcrumbs *b = &engine->breadcrumbs;
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100503 bool armed;
Chris Wilson688e6c72016-07-01 17:23:15 +0100504
Chris Wilson61d3dc72017-03-03 19:08:24 +0000505 spin_lock_irq(&b->rb_lock);
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100506 armed = __intel_engine_add_wait(engine, wait);
Chris Wilson61d3dc72017-03-03 19:08:24 +0000507 spin_unlock_irq(&b->rb_lock);
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100508 if (armed)
509 return armed;
Chris Wilson688e6c72016-07-01 17:23:15 +0100510
Chris Wilsonbac2ef42017-06-08 12:14:03 +0100511 /* Make the caller recheck if its request has already started. */
512 return i915_seqno_passed(intel_engine_get_seqno(engine),
513 wait->seqno - 1);
Chris Wilson688e6c72016-07-01 17:23:15 +0100514}
515
Chris Wilson688e6c72016-07-01 17:23:15 +0100516static inline bool chain_wakeup(struct rb_node *rb, int priority)
517{
518 return rb && to_wait(rb)->tsk->prio <= priority;
519}
520
Chris Wilsonc81d4612016-07-01 17:23:25 +0100521static inline int wakeup_priority(struct intel_breadcrumbs *b,
522 struct task_struct *tsk)
523{
524 if (tsk == b->signaler)
525 return INT_MIN;
526 else
527 return tsk->prio;
528}
529
Chris Wilson9eb143b2017-02-23 07:44:16 +0000530static void __intel_engine_remove_wait(struct intel_engine_cs *engine,
531 struct intel_wait *wait)
Chris Wilson688e6c72016-07-01 17:23:15 +0100532{
533 struct intel_breadcrumbs *b = &engine->breadcrumbs;
534
Chris Wilson61d3dc72017-03-03 19:08:24 +0000535 lockdep_assert_held(&b->rb_lock);
Chris Wilson688e6c72016-07-01 17:23:15 +0100536
537 if (RB_EMPTY_NODE(&wait->node))
Chris Wilson9eb143b2017-02-23 07:44:16 +0000538 goto out;
Chris Wilson688e6c72016-07-01 17:23:15 +0100539
Chris Wilson61d3dc72017-03-03 19:08:24 +0000540 if (b->irq_wait == wait) {
Chris Wilsonc81d4612016-07-01 17:23:25 +0100541 const int priority = wakeup_priority(b, wait->tsk);
Chris Wilson688e6c72016-07-01 17:23:15 +0100542 struct rb_node *next;
Chris Wilson688e6c72016-07-01 17:23:15 +0100543
Chris Wilson688e6c72016-07-01 17:23:15 +0100544 /* We are the current bottom-half. Find the next candidate,
545 * the first waiter in the queue on the remaining oldest
546 * request. As multiple seqnos may complete in the time it
547 * takes us to wake up and find the next waiter, we have to
548 * wake up that waiter for it to perform its own coherent
549 * completion check.
550 */
551 next = rb_next(&wait->node);
552 if (chain_wakeup(next, priority)) {
553 /* If the next waiter is already complete,
554 * wake it up and continue onto the next waiter. So
555 * if have a small herd, they will wake up in parallel
556 * rather than sequentially, which should reduce
557 * the overall latency in waking all the completed
558 * clients.
559 *
560 * However, waking up a chain adds extra latency to
561 * the first_waiter. This is undesirable if that
562 * waiter is a high priority task.
563 */
Chris Wilson1b7744e2016-07-01 17:23:17 +0100564 u32 seqno = intel_engine_get_seqno(engine);
Chris Wilson688e6c72016-07-01 17:23:15 +0100565
566 while (i915_seqno_passed(seqno, to_wait(next)->seqno)) {
567 struct rb_node *n = rb_next(next);
568
569 __intel_breadcrumbs_finish(b, to_wait(next));
570 next = n;
571 if (!chain_wakeup(next, priority))
572 break;
573 }
574 }
575
Chris Wilsonb66255f2017-03-03 17:14:22 +0000576 __intel_breadcrumbs_next(engine, next);
Chris Wilson688e6c72016-07-01 17:23:15 +0100577 } else {
578 GEM_BUG_ON(rb_first(&b->waiters) == &wait->node);
579 }
580
581 GEM_BUG_ON(RB_EMPTY_NODE(&wait->node));
582 rb_erase(&wait->node, &b->waiters);
Chris Wilsonc5346122017-11-15 12:14:58 +0000583 RB_CLEAR_NODE(&wait->node);
Chris Wilson688e6c72016-07-01 17:23:15 +0100584
Chris Wilson9eb143b2017-02-23 07:44:16 +0000585out:
Chris Wilson61d3dc72017-03-03 19:08:24 +0000586 GEM_BUG_ON(b->irq_wait == wait);
Chris Wilson688e6c72016-07-01 17:23:15 +0100587 GEM_BUG_ON(rb_first(&b->waiters) !=
Chris Wilson61d3dc72017-03-03 19:08:24 +0000588 (b->irq_wait ? &b->irq_wait->node : NULL));
Chris Wilson9eb143b2017-02-23 07:44:16 +0000589}
590
591void intel_engine_remove_wait(struct intel_engine_cs *engine,
592 struct intel_wait *wait)
593{
594 struct intel_breadcrumbs *b = &engine->breadcrumbs;
595
596 /* Quick check to see if this waiter was already decoupled from
597 * the tree by the bottom-half to avoid contention on the spinlock
598 * by the herd.
599 */
Chris Wilson908a6cb2017-03-15 21:07:25 +0000600 if (RB_EMPTY_NODE(&wait->node)) {
601 GEM_BUG_ON(READ_ONCE(b->irq_wait) == wait);
Chris Wilson9eb143b2017-02-23 07:44:16 +0000602 return;
Chris Wilson908a6cb2017-03-15 21:07:25 +0000603 }
Chris Wilson9eb143b2017-02-23 07:44:16 +0000604
Chris Wilson61d3dc72017-03-03 19:08:24 +0000605 spin_lock_irq(&b->rb_lock);
Chris Wilson9eb143b2017-02-23 07:44:16 +0000606 __intel_engine_remove_wait(engine, wait);
Chris Wilson61d3dc72017-03-03 19:08:24 +0000607 spin_unlock_irq(&b->rb_lock);
Chris Wilson688e6c72016-07-01 17:23:15 +0100608}
609
Chris Wilsond6a22892017-02-23 07:44:17 +0000610static bool signal_valid(const struct drm_i915_gem_request *request)
611{
612 return intel_wait_check_request(&request->signaling.wait, request);
613}
614
615static bool signal_complete(const struct drm_i915_gem_request *request)
Chris Wilsonc81d4612016-07-01 17:23:25 +0100616{
Chris Wilsonb3850852016-07-01 17:23:26 +0100617 if (!request)
Chris Wilsonc81d4612016-07-01 17:23:25 +0100618 return false;
619
620 /* If another process served as the bottom-half it may have already
621 * signalled that this wait is already completed.
622 */
Chris Wilsonb3850852016-07-01 17:23:26 +0100623 if (intel_wait_complete(&request->signaling.wait))
Chris Wilsond6a22892017-02-23 07:44:17 +0000624 return signal_valid(request);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100625
626 /* Carefully check if the request is complete, giving time for the
627 * seqno to be visible or if the GPU hung.
628 */
Chris Wilsonb3850852016-07-01 17:23:26 +0100629 if (__i915_request_irq_complete(request))
Chris Wilsonc81d4612016-07-01 17:23:25 +0100630 return true;
631
632 return false;
633}
634
Chris Wilsonb3850852016-07-01 17:23:26 +0100635static struct drm_i915_gem_request *to_signaler(struct rb_node *rb)
Chris Wilsonc81d4612016-07-01 17:23:25 +0100636{
Chris Wilsond8567862016-12-20 10:40:03 +0000637 return rb_entry(rb, struct drm_i915_gem_request, signaling.node);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100638}
639
640static void signaler_set_rtpriority(void)
641{
642 struct sched_param param = { .sched_priority = 1 };
643
644 sched_setscheduler_nocheck(current, SCHED_FIFO, &param);
645}
646
647static int intel_breadcrumbs_signaler(void *arg)
648{
649 struct intel_engine_cs *engine = arg;
650 struct intel_breadcrumbs *b = &engine->breadcrumbs;
Chris Wilsonb3850852016-07-01 17:23:26 +0100651 struct drm_i915_gem_request *request;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100652
653 /* Install ourselves with high priority to reduce signalling latency */
654 signaler_set_rtpriority();
655
656 do {
Chris Wilsona7980a62017-04-04 13:05:31 +0100657 bool do_schedule = true;
658
Chris Wilsonc81d4612016-07-01 17:23:25 +0100659 set_current_state(TASK_INTERRUPTIBLE);
660
661 /* We are either woken up by the interrupt bottom-half,
662 * or by a client adding a new signaller. In both cases,
663 * the GPU seqno may have advanced beyond our oldest signal.
664 * If it has, propagate the signal, remove the waiter and
665 * check again with the next oldest signal. Otherwise we
666 * need to wait for a new interrupt from the GPU or for
667 * a new client.
668 */
Chris Wilsoncced5e22017-02-23 07:44:15 +0000669 rcu_read_lock();
670 request = rcu_dereference(b->first_signal);
671 if (request)
672 request = i915_gem_request_get_rcu(request);
673 rcu_read_unlock();
Chris Wilsonb3850852016-07-01 17:23:26 +0100674 if (signal_complete(request)) {
Chris Wilson7c9e9342017-01-24 11:00:09 +0000675 local_bh_disable();
676 dma_fence_signal(&request->fence);
677 local_bh_enable(); /* kick start the tasklets */
678
Chris Wilson61d3dc72017-03-03 19:08:24 +0000679 spin_lock_irq(&b->rb_lock);
Chris Wilson9eb143b2017-02-23 07:44:16 +0000680
Chris Wilsonc81d4612016-07-01 17:23:25 +0100681 /* Wake up all other completed waiters and select the
682 * next bottom-half for the next user interrupt.
683 */
Chris Wilson9eb143b2017-02-23 07:44:16 +0000684 __intel_engine_remove_wait(engine,
685 &request->signaling.wait);
Chris Wilson5590af32016-09-09 14:11:54 +0100686
Chris Wilsonc81d4612016-07-01 17:23:25 +0100687 /* Find the next oldest signal. Note that as we have
688 * not been holding the lock, another client may
689 * have installed an even older signal than the one
690 * we just completed - so double check we are still
691 * the oldest before picking the next one.
692 */
Chris Wilsoncced5e22017-02-23 07:44:15 +0000693 if (request == rcu_access_pointer(b->first_signal)) {
Chris Wilsonb3850852016-07-01 17:23:26 +0100694 struct rb_node *rb =
695 rb_next(&request->signaling.node);
Chris Wilsoncced5e22017-02-23 07:44:15 +0000696 rcu_assign_pointer(b->first_signal,
697 rb ? to_signaler(rb) : NULL);
Chris Wilsonb3850852016-07-01 17:23:26 +0100698 }
699 rb_erase(&request->signaling.node, &b->signals);
Chris Wilson9eb143b2017-02-23 07:44:16 +0000700 RB_CLEAR_NODE(&request->signaling.node);
701
Chris Wilson61d3dc72017-03-03 19:08:24 +0000702 spin_unlock_irq(&b->rb_lock);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100703
Chris Wilsone8a261e2016-07-20 13:31:49 +0100704 i915_gem_request_put(request);
Chris Wilsona7980a62017-04-04 13:05:31 +0100705
706 /* If the engine is saturated we may be continually
707 * processing completed requests. This angers the
708 * NMI watchdog if we never let anything else
709 * have access to the CPU. Let's pretend to be nice
710 * and relinquish the CPU if we burn through the
711 * entire RT timeslice!
712 */
713 do_schedule = need_resched();
714 }
715
716 if (unlikely(do_schedule)) {
Chris Wilsonb1becb82017-04-03 11:51:24 +0100717 if (kthread_should_park())
718 kthread_parkme();
719
Chris Wilson776bc272017-12-08 12:10:33 +0000720 if (unlikely(kthread_should_stop())) {
721 i915_gem_request_put(request);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100722 break;
Chris Wilsoncced5e22017-02-23 07:44:15 +0000723 }
Chris Wilsonc81d4612016-07-01 17:23:25 +0100724
725 schedule();
726 }
Chris Wilsoncced5e22017-02-23 07:44:15 +0000727 i915_gem_request_put(request);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100728 } while (1);
729 __set_current_state(TASK_RUNNING);
730
731 return 0;
732}
733
Chris Wilsonf7b02a52017-04-26 09:06:59 +0100734void intel_engine_enable_signaling(struct drm_i915_gem_request *request,
735 bool wakeup)
Chris Wilsonc81d4612016-07-01 17:23:25 +0100736{
737 struct intel_engine_cs *engine = request->engine;
738 struct intel_breadcrumbs *b = &engine->breadcrumbs;
Chris Wilson754c9fd2017-02-23 07:44:14 +0000739 u32 seqno;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100740
Chris Wilsonf6168e32016-10-28 13:58:55 +0100741 /* Note that we may be called from an interrupt handler on another
742 * device (e.g. nouveau signaling a fence completion causing us
743 * to submit a request, and so enable signaling). As such,
Chris Wilsona6b0a1412017-03-15 22:22:59 +0000744 * we need to make sure that all other users of b->rb_lock protect
Chris Wilsonf6168e32016-10-28 13:58:55 +0100745 * against interrupts, i.e. use spin_lock_irqsave.
746 */
747
748 /* locked by dma_fence_enable_sw_signaling() (irqsafe fence->lock) */
Chris Wilsone60a8702017-03-02 11:51:30 +0000749 GEM_BUG_ON(!irqs_disabled());
Chris Wilson67520412017-03-02 13:28:01 +0000750 lockdep_assert_held(&request->lock);
Chris Wilson754c9fd2017-02-23 07:44:14 +0000751
752 seqno = i915_gem_request_global_seqno(request);
753 if (!seqno)
Chris Wilson65e47602016-10-28 13:58:49 +0100754 return;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100755
Chris Wilsonb3850852016-07-01 17:23:26 +0100756 request->signaling.wait.tsk = b->signaler;
Chris Wilson56299fb2017-02-27 20:58:48 +0000757 request->signaling.wait.request = request;
Chris Wilson754c9fd2017-02-23 07:44:14 +0000758 request->signaling.wait.seqno = seqno;
Chris Wilsone8a261e2016-07-20 13:31:49 +0100759 i915_gem_request_get(request);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100760
Chris Wilson61d3dc72017-03-03 19:08:24 +0000761 spin_lock(&b->rb_lock);
Chris Wilson4a50d202016-07-26 12:01:50 +0100762
Chris Wilsonc81d4612016-07-01 17:23:25 +0100763 /* First add ourselves into the list of waiters, but register our
764 * bottom-half as the signaller thread. As per usual, only the oldest
765 * waiter (not just signaller) is tasked as the bottom-half waking
766 * up all completed waiters after the user interrupt.
767 *
768 * If we are the oldest waiter, enable the irq (after which we
769 * must double check that the seqno did not complete).
770 */
Chris Wilsonf7b02a52017-04-26 09:06:59 +0100771 wakeup &= __intel_engine_add_wait(engine, &request->signaling.wait);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100772
Chris Wilson735e0eb2017-06-08 12:14:04 +0100773 if (!__i915_gem_request_completed(request, seqno)) {
774 struct rb_node *parent, **p;
775 bool first;
776
777 /* Now insert ourselves into the retirement ordered list of
778 * signals on this engine. We track the oldest seqno as that
779 * will be the first signal to complete.
780 */
781 parent = NULL;
782 first = true;
783 p = &b->signals.rb_node;
784 while (*p) {
785 parent = *p;
786 if (i915_seqno_passed(seqno,
787 to_signaler(parent)->signaling.wait.seqno)) {
788 p = &parent->rb_right;
789 first = false;
790 } else {
791 p = &parent->rb_left;
792 }
Chris Wilsonc81d4612016-07-01 17:23:25 +0100793 }
Chris Wilson735e0eb2017-06-08 12:14:04 +0100794 rb_link_node(&request->signaling.node, parent, p);
795 rb_insert_color(&request->signaling.node, &b->signals);
796 if (first)
797 rcu_assign_pointer(b->first_signal, request);
798 } else {
799 __intel_engine_remove_wait(engine, &request->signaling.wait);
800 i915_gem_request_put(request);
801 wakeup = false;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100802 }
Chris Wilsonb3850852016-07-01 17:23:26 +0100803
Chris Wilson61d3dc72017-03-03 19:08:24 +0000804 spin_unlock(&b->rb_lock);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100805
806 if (wakeup)
807 wake_up_process(b->signaler);
Chris Wilsonc81d4612016-07-01 17:23:25 +0100808}
809
Chris Wilson9eb143b2017-02-23 07:44:16 +0000810void intel_engine_cancel_signaling(struct drm_i915_gem_request *request)
811{
812 struct intel_engine_cs *engine = request->engine;
813 struct intel_breadcrumbs *b = &engine->breadcrumbs;
814
Chris Wilsone60a8702017-03-02 11:51:30 +0000815 GEM_BUG_ON(!irqs_disabled());
Chris Wilson67520412017-03-02 13:28:01 +0000816 lockdep_assert_held(&request->lock);
Chris Wilson9eb143b2017-02-23 07:44:16 +0000817 GEM_BUG_ON(!request->signaling.wait.seqno);
818
Chris Wilson61d3dc72017-03-03 19:08:24 +0000819 spin_lock(&b->rb_lock);
Chris Wilson9eb143b2017-02-23 07:44:16 +0000820
821 if (!RB_EMPTY_NODE(&request->signaling.node)) {
822 if (request == rcu_access_pointer(b->first_signal)) {
823 struct rb_node *rb =
824 rb_next(&request->signaling.node);
825 rcu_assign_pointer(b->first_signal,
826 rb ? to_signaler(rb) : NULL);
827 }
828 rb_erase(&request->signaling.node, &b->signals);
829 RB_CLEAR_NODE(&request->signaling.node);
830 i915_gem_request_put(request);
831 }
832
833 __intel_engine_remove_wait(engine, &request->signaling.wait);
834
Chris Wilson61d3dc72017-03-03 19:08:24 +0000835 spin_unlock(&b->rb_lock);
Chris Wilson9eb143b2017-02-23 07:44:16 +0000836
837 request->signaling.wait.seqno = 0;
838}
839
Chris Wilson688e6c72016-07-01 17:23:15 +0100840int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine)
841{
842 struct intel_breadcrumbs *b = &engine->breadcrumbs;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100843 struct task_struct *tsk;
Chris Wilson688e6c72016-07-01 17:23:15 +0100844
Chris Wilson61d3dc72017-03-03 19:08:24 +0000845 spin_lock_init(&b->rb_lock);
846 spin_lock_init(&b->irq_lock);
847
Kees Cook39cbf2a2017-10-17 09:53:04 +0300848 timer_setup(&b->fake_irq, intel_breadcrumbs_fake_irq, 0);
849 timer_setup(&b->hangcheck, intel_breadcrumbs_hangcheck, 0);
Chris Wilson688e6c72016-07-01 17:23:15 +0100850
Chris Wilsonc81d4612016-07-01 17:23:25 +0100851 /* Spawn a thread to provide a common bottom-half for all signals.
852 * As this is an asynchronous interface we cannot steal the current
853 * task for handling the bottom-half to the user interrupt, therefore
854 * we create a thread to do the coherent seqno dance after the
855 * interrupt and then signal the waitqueue (via the dma-buf/fence).
856 */
857 tsk = kthread_run(intel_breadcrumbs_signaler, engine,
858 "i915/signal:%d", engine->id);
859 if (IS_ERR(tsk))
860 return PTR_ERR(tsk);
861
862 b->signaler = tsk;
863
Chris Wilson688e6c72016-07-01 17:23:15 +0100864 return 0;
865}
866
Chris Wilsonad07dfc2016-10-07 07:53:26 +0100867static void cancel_fake_irq(struct intel_engine_cs *engine)
868{
869 struct intel_breadcrumbs *b = &engine->breadcrumbs;
870
871 del_timer_sync(&b->hangcheck);
872 del_timer_sync(&b->fake_irq);
873 clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings);
874}
875
876void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine)
877{
878 struct intel_breadcrumbs *b = &engine->breadcrumbs;
879
880 cancel_fake_irq(engine);
Chris Wilson61d3dc72017-03-03 19:08:24 +0000881 spin_lock_irq(&b->irq_lock);
Chris Wilsonad07dfc2016-10-07 07:53:26 +0100882
Chris Wilson67b807a82017-02-27 20:58:50 +0000883 if (b->irq_enabled)
884 irq_enable(engine);
885 else
Chris Wilsonad07dfc2016-10-07 07:53:26 +0100886 irq_disable(engine);
Chris Wilson67b807a82017-02-27 20:58:50 +0000887
888 /* We set the IRQ_BREADCRUMB bit when we enable the irq presuming the
889 * GPU is active and may have already executed the MI_USER_INTERRUPT
890 * before the CPU is ready to receive. However, the engine is currently
891 * idle (we haven't started it yet), there is no possibility for a
892 * missed interrupt as we enabled the irq and so we can clear the
893 * immediate wakeup (until a real interrupt arrives for the waiter).
894 */
895 clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
896
897 if (b->irq_armed)
898 enable_fake_irq(b);
Chris Wilsonad07dfc2016-10-07 07:53:26 +0100899
Chris Wilson61d3dc72017-03-03 19:08:24 +0000900 spin_unlock_irq(&b->irq_lock);
Chris Wilsonad07dfc2016-10-07 07:53:26 +0100901}
902
Chris Wilson688e6c72016-07-01 17:23:15 +0100903void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
904{
905 struct intel_breadcrumbs *b = &engine->breadcrumbs;
906
Chris Wilson381744f2016-11-21 11:07:59 +0000907 /* The engines should be idle and all requests accounted for! */
Chris Wilson61d3dc72017-03-03 19:08:24 +0000908 WARN_ON(READ_ONCE(b->irq_wait));
Chris Wilson381744f2016-11-21 11:07:59 +0000909 WARN_ON(!RB_EMPTY_ROOT(&b->waiters));
Chris Wilsoncced5e22017-02-23 07:44:15 +0000910 WARN_ON(rcu_access_pointer(b->first_signal));
Chris Wilson381744f2016-11-21 11:07:59 +0000911 WARN_ON(!RB_EMPTY_ROOT(&b->signals));
912
Chris Wilsonc81d4612016-07-01 17:23:25 +0100913 if (!IS_ERR_OR_NULL(b->signaler))
914 kthread_stop(b->signaler);
915
Chris Wilsonad07dfc2016-10-07 07:53:26 +0100916 cancel_fake_irq(engine);
Chris Wilson688e6c72016-07-01 17:23:15 +0100917}
918
Chris Wilson9b6586a2017-02-23 07:44:08 +0000919bool intel_breadcrumbs_busy(struct intel_engine_cs *engine)
Chris Wilsonc81d4612016-07-01 17:23:25 +0100920{
Chris Wilson9b6586a2017-02-23 07:44:08 +0000921 struct intel_breadcrumbs *b = &engine->breadcrumbs;
922 bool busy = false;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100923
Chris Wilson61d3dc72017-03-03 19:08:24 +0000924 spin_lock_irq(&b->rb_lock);
Chris Wilson6a5d1db2016-11-08 14:37:19 +0000925
Chris Wilson61d3dc72017-03-03 19:08:24 +0000926 if (b->irq_wait) {
927 wake_up_process(b->irq_wait->tsk);
Chris Wilson4bd66392017-03-15 21:07:22 +0000928 busy = true;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100929 }
930
Chris Wilsoncced5e22017-02-23 07:44:15 +0000931 if (rcu_access_pointer(b->first_signal)) {
Chris Wilson9b6586a2017-02-23 07:44:08 +0000932 wake_up_process(b->signaler);
Chris Wilson4bd66392017-03-15 21:07:22 +0000933 busy = true;
Chris Wilson9b6586a2017-02-23 07:44:08 +0000934 }
935
Chris Wilson61d3dc72017-03-03 19:08:24 +0000936 spin_unlock_irq(&b->rb_lock);
Chris Wilson9b6586a2017-02-23 07:44:08 +0000937
938 return busy;
Chris Wilsonc81d4612016-07-01 17:23:25 +0100939}
Chris Wilsonf97fbf92017-02-13 17:15:14 +0000940
941#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
942#include "selftests/intel_breadcrumbs.c"
943#endif