1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2009 Jerome Glisse.
3254885Sdumbbell * All Rights Reserved.
4254885Sdumbbell *
5254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
6254885Sdumbbell * copy of this software and associated documentation files (the
7254885Sdumbbell * "Software"), to deal in the Software without restriction, including
8254885Sdumbbell * without limitation the rights to use, copy, modify, merge, publish,
9254885Sdumbbell * distribute, sub license, and/or sell copies of the Software, and to
10254885Sdumbbell * permit persons to whom the Software is furnished to do so, subject to
11254885Sdumbbell * the following conditions:
12254885Sdumbbell *
13254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16254885Sdumbbell * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17254885Sdumbbell * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18254885Sdumbbell * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19254885Sdumbbell * USE OR OTHER DEALINGS IN THE SOFTWARE.
20254885Sdumbbell *
21254885Sdumbbell * The above copyright notice and this permission notice (including the
22254885Sdumbbell * next paragraph) shall be included in all copies or substantial portions
23254885Sdumbbell * of the Software.
24254885Sdumbbell *
25254885Sdumbbell */
26254885Sdumbbell/*
27254885Sdumbbell * Authors:
28254885Sdumbbell *    Jerome Glisse <glisse@freedesktop.org>
29254885Sdumbbell *    Dave Airlie
30254885Sdumbbell */
31254885Sdumbbell
32254885Sdumbbell#include <sys/cdefs.h>
33254885Sdumbbell__FBSDID("$FreeBSD$");
34254885Sdumbbell
35254885Sdumbbell#include <dev/drm2/drmP.h>
36254885Sdumbbell#include "radeon_reg.h"
37254885Sdumbbell#include "radeon.h"
38280183Sdumbbell#ifdef FREEBSD_WIP
39254885Sdumbbell#include "radeon_trace.h"
40280183Sdumbbell#endif /* FREEBSD_WIP */
41254885Sdumbbell
42254885Sdumbbell/*
43254885Sdumbbell * Fences
44254885Sdumbbell * Fences mark an event in the GPUs pipeline and are used
45254885Sdumbbell * for GPU/CPU synchronization.  When the fence is written,
46254885Sdumbbell * it is expected that all buffers associated with that fence
47254885Sdumbbell * are no longer in use by the associated ring on the GPU and
48300050Seadler * that the relevant GPU caches have been flushed.  Whether
49254885Sdumbbell * we use a scratch register or memory location depends on the asic
50254885Sdumbbell * and whether writeback is enabled.
51254885Sdumbbell */
52254885Sdumbbell
53254885Sdumbbell/**
54254885Sdumbbell * radeon_fence_write - write a fence value
55254885Sdumbbell *
56254885Sdumbbell * @rdev: radeon_device pointer
57254885Sdumbbell * @seq: sequence number to write
58254885Sdumbbell * @ring: ring index the fence is associated with
59254885Sdumbbell *
60254885Sdumbbell * Writes a fence value to memory or a scratch register (all asics).
61254885Sdumbbell */
62254885Sdumbbellstatic void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring)
63254885Sdumbbell{
64254885Sdumbbell	struct radeon_fence_driver *drv = &rdev->fence_drv[ring];
65254885Sdumbbell	if (likely(rdev->wb.enabled || !drv->scratch_reg)) {
66254885Sdumbbell		*drv->cpu_addr = cpu_to_le32(seq);
67254885Sdumbbell	} else {
68254885Sdumbbell		WREG32(drv->scratch_reg, seq);
69254885Sdumbbell	}
70254885Sdumbbell}
71254885Sdumbbell
72254885Sdumbbell/**
73254885Sdumbbell * radeon_fence_read - read a fence value
74254885Sdumbbell *
75254885Sdumbbell * @rdev: radeon_device pointer
76254885Sdumbbell * @ring: ring index the fence is associated with
77254885Sdumbbell *
78254885Sdumbbell * Reads a fence value from memory or a scratch register (all asics).
79254885Sdumbbell * Returns the value of the fence read from memory or register.
80254885Sdumbbell */
81254885Sdumbbellstatic u32 radeon_fence_read(struct radeon_device *rdev, int ring)
82254885Sdumbbell{
83254885Sdumbbell	struct radeon_fence_driver *drv = &rdev->fence_drv[ring];
84254885Sdumbbell	u32 seq = 0;
85254885Sdumbbell
86254885Sdumbbell	if (likely(rdev->wb.enabled || !drv->scratch_reg)) {
87254885Sdumbbell		seq = le32_to_cpu(*drv->cpu_addr);
88254885Sdumbbell	} else {
89254885Sdumbbell		seq = RREG32(drv->scratch_reg);
90254885Sdumbbell	}
91254885Sdumbbell	return seq;
92254885Sdumbbell}
93254885Sdumbbell
94254885Sdumbbell/**
95254885Sdumbbell * radeon_fence_emit - emit a fence on the requested ring
96254885Sdumbbell *
97254885Sdumbbell * @rdev: radeon_device pointer
98254885Sdumbbell * @fence: radeon fence object
99254885Sdumbbell * @ring: ring index the fence is associated with
100254885Sdumbbell *
101254885Sdumbbell * Emits a fence command on the requested ring (all asics).
102254885Sdumbbell * Returns 0 on success, -ENOMEM on failure.
103254885Sdumbbell */
104254885Sdumbbellint radeon_fence_emit(struct radeon_device *rdev,
105254885Sdumbbell		      struct radeon_fence **fence,
106254885Sdumbbell		      int ring)
107254885Sdumbbell{
108254885Sdumbbell	/* we are protected by the ring emission mutex */
109280183Sdumbbell	*fence = malloc(sizeof(struct radeon_fence), DRM_MEM_DRIVER, M_NOWAIT);
110254885Sdumbbell	if ((*fence) == NULL) {
111254885Sdumbbell		return -ENOMEM;
112254885Sdumbbell	}
113254885Sdumbbell	refcount_init(&((*fence)->kref), 1);
114254885Sdumbbell	(*fence)->rdev = rdev;
115254885Sdumbbell	(*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring];
116254885Sdumbbell	(*fence)->ring = ring;
117254885Sdumbbell	radeon_fence_ring_emit(rdev, ring, *fence);
118254885Sdumbbell	CTR2(KTR_DRM, "radeon fence: emit (ring=%d, seq=%d)", ring, (*fence)->seq);
119254885Sdumbbell	return 0;
120254885Sdumbbell}
121254885Sdumbbell
122254885Sdumbbell/**
123254885Sdumbbell * radeon_fence_process - process a fence
124254885Sdumbbell *
125254885Sdumbbell * @rdev: radeon_device pointer
126254885Sdumbbell * @ring: ring index the fence is associated with
127254885Sdumbbell *
128254885Sdumbbell * Checks the current fence value and wakes the fence queue
129254885Sdumbbell * if the sequence number has increased (all asics).
130254885Sdumbbell */
131254885Sdumbbellvoid radeon_fence_process(struct radeon_device *rdev, int ring)
132254885Sdumbbell{
133254885Sdumbbell	uint64_t seq, last_seq, last_emitted;
134254885Sdumbbell	unsigned count_loop = 0;
135254885Sdumbbell	bool wake = false;
136254885Sdumbbell
137254885Sdumbbell	/* Note there is a scenario here for an infinite loop but it's
138254885Sdumbbell	 * very unlikely to happen. For it to happen, the current polling
139254885Sdumbbell	 * process need to be interrupted by another process and another
140254885Sdumbbell	 * process needs to update the last_seq btw the atomic read and
141254885Sdumbbell	 * xchg of the current process.
142254885Sdumbbell	 *
143254885Sdumbbell	 * More over for this to go in infinite loop there need to be
144254885Sdumbbell	 * continuously new fence signaled ie radeon_fence_read needs
145254885Sdumbbell	 * to return a different value each time for both the currently
146254885Sdumbbell	 * polling process and the other process that xchg the last_seq
147254885Sdumbbell	 * btw atomic read and xchg of the current process. And the
148254885Sdumbbell	 * value the other process set as last seq must be higher than
149254885Sdumbbell	 * the seq value we just read. Which means that current process
150254885Sdumbbell	 * need to be interrupted after radeon_fence_read and before
151254885Sdumbbell	 * atomic xchg.
152254885Sdumbbell	 *
153254885Sdumbbell	 * To be even more safe we count the number of time we loop and
154254885Sdumbbell	 * we bail after 10 loop just accepting the fact that we might
155254885Sdumbbell	 * have temporarly set the last_seq not to the true real last
156254885Sdumbbell	 * seq but to an older one.
157254885Sdumbbell	 */
158280183Sdumbbell	last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
159254885Sdumbbell	do {
160254885Sdumbbell		last_emitted = rdev->fence_drv[ring].sync_seq[ring];
161254885Sdumbbell		seq = radeon_fence_read(rdev, ring);
162254885Sdumbbell		seq |= last_seq & 0xffffffff00000000LL;
163254885Sdumbbell		if (seq < last_seq) {
164254885Sdumbbell			seq &= 0xffffffff;
165254885Sdumbbell			seq |= last_emitted & 0xffffffff00000000LL;
166254885Sdumbbell		}
167254885Sdumbbell
168254885Sdumbbell		if (seq <= last_seq || seq > last_emitted) {
169254885Sdumbbell			break;
170254885Sdumbbell		}
171254885Sdumbbell		/* If we loop over we don't want to return without
172254885Sdumbbell		 * checking if a fence is signaled as it means that the
173254885Sdumbbell		 * seq we just read is different from the previous on.
174254885Sdumbbell		 */
175254885Sdumbbell		wake = true;
176254885Sdumbbell		last_seq = seq;
177254885Sdumbbell		if ((count_loop++) > 10) {
178254885Sdumbbell			/* We looped over too many time leave with the
179254885Sdumbbell			 * fact that we might have set an older fence
180254885Sdumbbell			 * seq then the current real last seq as signaled
181254885Sdumbbell			 * by the hw.
182254885Sdumbbell			 */
183254885Sdumbbell			break;
184254885Sdumbbell		}
185254885Sdumbbell	} while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq);
186254885Sdumbbell
187254885Sdumbbell	if (wake) {
188254885Sdumbbell		rdev->fence_drv[ring].last_activity = jiffies;
189254885Sdumbbell		cv_broadcast(&rdev->fence_queue);
190254885Sdumbbell	}
191254885Sdumbbell}
192254885Sdumbbell
193254885Sdumbbell/**
194254885Sdumbbell * radeon_fence_destroy - destroy a fence
195254885Sdumbbell *
196254885Sdumbbell * @kref: fence kref
197254885Sdumbbell *
198254885Sdumbbell * Frees the fence object (all asics).
199254885Sdumbbell */
200254885Sdumbbellstatic void radeon_fence_destroy(struct radeon_fence *fence)
201254885Sdumbbell{
202254885Sdumbbell
203254885Sdumbbell	free(fence, DRM_MEM_DRIVER);
204254885Sdumbbell}
205254885Sdumbbell
206254885Sdumbbell/**
207254885Sdumbbell * radeon_fence_seq_signaled - check if a fence sequeuce number has signaled
208254885Sdumbbell *
209254885Sdumbbell * @rdev: radeon device pointer
210254885Sdumbbell * @seq: sequence number
211254885Sdumbbell * @ring: ring index the fence is associated with
212254885Sdumbbell *
213254885Sdumbbell * Check if the last singled fence sequnce number is >= the requested
214254885Sdumbbell * sequence number (all asics).
215254885Sdumbbell * Returns true if the fence has signaled (current fence value
216254885Sdumbbell * is >= requested value) or false if it has not (current fence
217254885Sdumbbell * value is < the requested value.  Helper function for
218254885Sdumbbell * radeon_fence_signaled().
219254885Sdumbbell */
220254885Sdumbbellstatic bool radeon_fence_seq_signaled(struct radeon_device *rdev,
221254885Sdumbbell				      u64 seq, unsigned ring)
222254885Sdumbbell{
223280183Sdumbbell	if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) {
224254885Sdumbbell		return true;
225254885Sdumbbell	}
226254885Sdumbbell	/* poll new last sequence at least once */
227254885Sdumbbell	radeon_fence_process(rdev, ring);
228280183Sdumbbell	if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) {
229254885Sdumbbell		return true;
230254885Sdumbbell	}
231254885Sdumbbell	return false;
232254885Sdumbbell}
233254885Sdumbbell
234254885Sdumbbell/**
235254885Sdumbbell * radeon_fence_signaled - check if a fence has signaled
236254885Sdumbbell *
237254885Sdumbbell * @fence: radeon fence object
238254885Sdumbbell *
239254885Sdumbbell * Check if the requested fence has signaled (all asics).
240254885Sdumbbell * Returns true if the fence has signaled or false if it has not.
241254885Sdumbbell */
242254885Sdumbbellbool radeon_fence_signaled(struct radeon_fence *fence)
243254885Sdumbbell{
244254885Sdumbbell	if (!fence) {
245254885Sdumbbell		return true;
246254885Sdumbbell	}
247254885Sdumbbell	if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) {
248254885Sdumbbell		return true;
249254885Sdumbbell	}
250254885Sdumbbell	if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) {
251254885Sdumbbell		fence->seq = RADEON_FENCE_SIGNALED_SEQ;
252254885Sdumbbell		return true;
253254885Sdumbbell	}
254254885Sdumbbell	return false;
255254885Sdumbbell}
256254885Sdumbbell
257254885Sdumbbell/**
258254885Sdumbbell * radeon_fence_wait_seq - wait for a specific sequence number
259254885Sdumbbell *
260254885Sdumbbell * @rdev: radeon device pointer
261254885Sdumbbell * @target_seq: sequence number we want to wait for
262254885Sdumbbell * @ring: ring index the fence is associated with
263254885Sdumbbell * @intr: use interruptable sleep
264254885Sdumbbell * @lock_ring: whether the ring should be locked or not
265254885Sdumbbell *
266254885Sdumbbell * Wait for the requested sequence number to be written (all asics).
267254885Sdumbbell * @intr selects whether to use interruptable (true) or non-interruptable
268254885Sdumbbell * (false) sleep when waiting for the sequence number.  Helper function
269254885Sdumbbell * for radeon_fence_wait(), et al.
270254885Sdumbbell * Returns 0 if the sequence number has passed, error for all other cases.
271254885Sdumbbell * -EDEADLK is returned when a GPU lockup has been detected and the ring is
272254885Sdumbbell * marked as not ready so no further jobs get scheduled until a successful
273254885Sdumbbell * reset.
274254885Sdumbbell */
275254885Sdumbbellstatic int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
276254885Sdumbbell				 unsigned ring, bool intr, bool lock_ring)
277254885Sdumbbell{
278254885Sdumbbell	unsigned long timeout, last_activity;
279254885Sdumbbell	uint64_t seq;
280254885Sdumbbell	unsigned i;
281254885Sdumbbell	bool signaled, fence_queue_locked;
282254885Sdumbbell	int r;
283254885Sdumbbell
284280183Sdumbbell	while (target_seq > atomic64_read(&rdev->fence_drv[ring].last_seq)) {
285254885Sdumbbell		if (!rdev->ring[ring].ready) {
286254885Sdumbbell			return -EBUSY;
287254885Sdumbbell		}
288254885Sdumbbell
289254885Sdumbbell		timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT;
290254885Sdumbbell		if (time_after(rdev->fence_drv[ring].last_activity, timeout)) {
291254885Sdumbbell			/* the normal case, timeout is somewhere before last_activity */
292254885Sdumbbell			timeout = rdev->fence_drv[ring].last_activity - timeout;
293254885Sdumbbell		} else {
294254885Sdumbbell			/* either jiffies wrapped around, or no fence was signaled in the last 500ms
295254885Sdumbbell			 * anyway we will just wait for the minimum amount and then check for a lockup
296254885Sdumbbell			 */
297254885Sdumbbell			timeout = 1;
298254885Sdumbbell		}
299280183Sdumbbell		seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
300254885Sdumbbell		/* Save current last activity valuee, used to check for GPU lockups */
301254885Sdumbbell		last_activity = rdev->fence_drv[ring].last_activity;
302254885Sdumbbell
303254885Sdumbbell		CTR2(KTR_DRM, "radeon fence: wait begin (ring=%d, seq=%d)",
304254885Sdumbbell		    ring, seq);
305254885Sdumbbell
306254885Sdumbbell		radeon_irq_kms_sw_irq_get(rdev, ring);
307254885Sdumbbell		fence_queue_locked = false;
308254885Sdumbbell		r = 0;
309254885Sdumbbell		while (!(signaled = radeon_fence_seq_signaled(rdev,
310254885Sdumbbell		    target_seq, ring))) {
311254885Sdumbbell			if (!fence_queue_locked) {
312254885Sdumbbell				mtx_lock(&rdev->fence_queue_mtx);
313254885Sdumbbell				fence_queue_locked = true;
314254885Sdumbbell			}
315254885Sdumbbell			if (intr) {
316254885Sdumbbell				r = cv_timedwait_sig(&rdev->fence_queue,
317254885Sdumbbell				    &rdev->fence_queue_mtx,
318254885Sdumbbell				    timeout);
319254885Sdumbbell			} else {
320254885Sdumbbell				r = cv_timedwait(&rdev->fence_queue,
321254885Sdumbbell				    &rdev->fence_queue_mtx,
322254885Sdumbbell				    timeout);
323254885Sdumbbell			}
324259684Sdumbbell			if (r == EINTR)
325259684Sdumbbell				r = ERESTARTSYS;
326254885Sdumbbell			if (r != 0) {
327254885Sdumbbell				if (r == EWOULDBLOCK) {
328254885Sdumbbell					signaled =
329254885Sdumbbell					    radeon_fence_seq_signaled(
330254885Sdumbbell						rdev, target_seq, ring);
331254885Sdumbbell				}
332254885Sdumbbell				break;
333254885Sdumbbell			}
334254885Sdumbbell		}
335254885Sdumbbell		if (fence_queue_locked) {
336254885Sdumbbell			mtx_unlock(&rdev->fence_queue_mtx);
337254885Sdumbbell		}
338254885Sdumbbell		radeon_irq_kms_sw_irq_put(rdev, ring);
339259684Sdumbbell		if (unlikely(r == ERESTARTSYS)) {
340254885Sdumbbell			return -r;
341254885Sdumbbell		}
342254885Sdumbbell		CTR2(KTR_DRM, "radeon fence: wait end (ring=%d, seq=%d)",
343254885Sdumbbell		    ring, seq);
344254885Sdumbbell
345254885Sdumbbell		if (unlikely(!signaled)) {
346254885Sdumbbell#ifndef __FreeBSD__
347254885Sdumbbell			/* we were interrupted for some reason and fence
348254885Sdumbbell			 * isn't signaled yet, resume waiting */
349254885Sdumbbell			if (r) {
350254885Sdumbbell				continue;
351254885Sdumbbell			}
352254885Sdumbbell#endif
353254885Sdumbbell
354254885Sdumbbell			/* check if sequence value has changed since last_activity */
355280183Sdumbbell			if (seq != atomic64_read(&rdev->fence_drv[ring].last_seq)) {
356254885Sdumbbell				continue;
357254885Sdumbbell			}
358254885Sdumbbell
359254885Sdumbbell			if (lock_ring) {
360254885Sdumbbell				sx_xlock(&rdev->ring_lock);
361254885Sdumbbell			}
362254885Sdumbbell
363254885Sdumbbell			/* test if somebody else has already decided that this is a lockup */
364254885Sdumbbell			if (last_activity != rdev->fence_drv[ring].last_activity) {
365254885Sdumbbell				if (lock_ring) {
366254885Sdumbbell					sx_xunlock(&rdev->ring_lock);
367254885Sdumbbell				}
368254885Sdumbbell				continue;
369254885Sdumbbell			}
370254885Sdumbbell
371254885Sdumbbell			if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) {
372254885Sdumbbell				/* good news we believe it's a lockup */
373254885Sdumbbell				dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016jx last fence id 0x%016jx)\n",
374254885Sdumbbell					 (uintmax_t)target_seq, (uintmax_t)seq);
375254885Sdumbbell
376254885Sdumbbell				/* change last activity so nobody else think there is a lockup */
377254885Sdumbbell				for (i = 0; i < RADEON_NUM_RINGS; ++i) {
378254885Sdumbbell					rdev->fence_drv[i].last_activity = jiffies;
379254885Sdumbbell				}
380254885Sdumbbell
381254885Sdumbbell				/* mark the ring as not ready any more */
382254885Sdumbbell				rdev->ring[ring].ready = false;
383254885Sdumbbell				if (lock_ring) {
384254885Sdumbbell					sx_xunlock(&rdev->ring_lock);
385254885Sdumbbell				}
386254885Sdumbbell				return -EDEADLK;
387254885Sdumbbell			}
388254885Sdumbbell
389254885Sdumbbell			if (lock_ring) {
390254885Sdumbbell				sx_xunlock(&rdev->ring_lock);
391254885Sdumbbell			}
392254885Sdumbbell		}
393254885Sdumbbell	}
394254885Sdumbbell	return 0;
395254885Sdumbbell}
396254885Sdumbbell
397254885Sdumbbell/**
398254885Sdumbbell * radeon_fence_wait - wait for a fence to signal
399254885Sdumbbell *
400254885Sdumbbell * @fence: radeon fence object
401254885Sdumbbell * @intr: use interruptable sleep
402254885Sdumbbell *
403254885Sdumbbell * Wait for the requested fence to signal (all asics).
404254885Sdumbbell * @intr selects whether to use interruptable (true) or non-interruptable
405254885Sdumbbell * (false) sleep when waiting for the fence.
406254885Sdumbbell * Returns 0 if the fence has passed, error for all other cases.
407254885Sdumbbell */
408254885Sdumbbellint radeon_fence_wait(struct radeon_fence *fence, bool intr)
409254885Sdumbbell{
410254885Sdumbbell	int r;
411254885Sdumbbell
412254885Sdumbbell	if (fence == NULL) {
413254885Sdumbbell		DRM_ERROR("Querying an invalid fence : %p !\n", fence);
414254885Sdumbbell		return -EINVAL;
415254885Sdumbbell	}
416254885Sdumbbell
417254885Sdumbbell	r = radeon_fence_wait_seq(fence->rdev, fence->seq,
418254885Sdumbbell				  fence->ring, intr, true);
419254885Sdumbbell	if (r) {
420254885Sdumbbell		return r;
421254885Sdumbbell	}
422254885Sdumbbell	fence->seq = RADEON_FENCE_SIGNALED_SEQ;
423254885Sdumbbell	return 0;
424254885Sdumbbell}
425254885Sdumbbell
426254885Sdumbbellstatic bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq)
427254885Sdumbbell{
428254885Sdumbbell	unsigned i;
429254885Sdumbbell
430254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
431254885Sdumbbell		if (seq[i] && radeon_fence_seq_signaled(rdev, seq[i], i)) {
432254885Sdumbbell			return true;
433254885Sdumbbell		}
434254885Sdumbbell	}
435254885Sdumbbell	return false;
436254885Sdumbbell}
437254885Sdumbbell
438254885Sdumbbell/**
439254885Sdumbbell * radeon_fence_wait_any_seq - wait for a sequence number on any ring
440254885Sdumbbell *
441254885Sdumbbell * @rdev: radeon device pointer
442254885Sdumbbell * @target_seq: sequence number(s) we want to wait for
443254885Sdumbbell * @intr: use interruptable sleep
444254885Sdumbbell *
445254885Sdumbbell * Wait for the requested sequence number(s) to be written by any ring
446254885Sdumbbell * (all asics).  Sequnce number array is indexed by ring id.
447254885Sdumbbell * @intr selects whether to use interruptable (true) or non-interruptable
448254885Sdumbbell * (false) sleep when waiting for the sequence number.  Helper function
449254885Sdumbbell * for radeon_fence_wait_any(), et al.
450254885Sdumbbell * Returns 0 if the sequence number has passed, error for all other cases.
451254885Sdumbbell */
452254885Sdumbbellstatic int radeon_fence_wait_any_seq(struct radeon_device *rdev,
453254885Sdumbbell				     u64 *target_seq, bool intr)
454254885Sdumbbell{
455254885Sdumbbell	unsigned long timeout, last_activity, tmp;
456254885Sdumbbell	unsigned i, ring = RADEON_NUM_RINGS;
457254885Sdumbbell	bool signaled, fence_queue_locked;
458254885Sdumbbell	int r;
459254885Sdumbbell
460254885Sdumbbell	for (i = 0, last_activity = 0; i < RADEON_NUM_RINGS; ++i) {
461254885Sdumbbell		if (!target_seq[i]) {
462254885Sdumbbell			continue;
463254885Sdumbbell		}
464254885Sdumbbell
465254885Sdumbbell		/* use the most recent one as indicator */
466254885Sdumbbell		if (time_after(rdev->fence_drv[i].last_activity, last_activity)) {
467254885Sdumbbell			last_activity = rdev->fence_drv[i].last_activity;
468254885Sdumbbell		}
469254885Sdumbbell
470254885Sdumbbell		/* For lockup detection just pick the lowest ring we are
471254885Sdumbbell		 * actively waiting for
472254885Sdumbbell		 */
473254885Sdumbbell		if (i < ring) {
474254885Sdumbbell			ring = i;
475254885Sdumbbell		}
476254885Sdumbbell	}
477254885Sdumbbell
478254885Sdumbbell	/* nothing to wait for ? */
479254885Sdumbbell	if (ring == RADEON_NUM_RINGS) {
480254885Sdumbbell		return -ENOENT;
481254885Sdumbbell	}
482254885Sdumbbell
483254885Sdumbbell	while (!radeon_fence_any_seq_signaled(rdev, target_seq)) {
484254885Sdumbbell		timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT;
485254885Sdumbbell		if (time_after(last_activity, timeout)) {
486254885Sdumbbell			/* the normal case, timeout is somewhere before last_activity */
487254885Sdumbbell			timeout = last_activity - timeout;
488254885Sdumbbell		} else {
489254885Sdumbbell			/* either jiffies wrapped around, or no fence was signaled in the last 500ms
490254885Sdumbbell			 * anyway we will just wait for the minimum amount and then check for a lockup
491254885Sdumbbell			 */
492254885Sdumbbell			timeout = 1;
493254885Sdumbbell		}
494254885Sdumbbell
495254885Sdumbbell		CTR2(KTR_DRM, "radeon fence: wait begin (ring=%d, target_seq=%d)",
496254885Sdumbbell		    ring, target_seq[ring]);
497254885Sdumbbell		for (i = 0; i < RADEON_NUM_RINGS; ++i) {
498254885Sdumbbell			if (target_seq[i]) {
499254885Sdumbbell				radeon_irq_kms_sw_irq_get(rdev, i);
500254885Sdumbbell			}
501254885Sdumbbell		}
502254885Sdumbbell		fence_queue_locked = false;
503254885Sdumbbell		r = 0;
504254885Sdumbbell		while (!(signaled = radeon_fence_any_seq_signaled(rdev,
505254885Sdumbbell		    target_seq))) {
506254885Sdumbbell			if (!fence_queue_locked) {
507254885Sdumbbell				mtx_lock(&rdev->fence_queue_mtx);
508254885Sdumbbell				fence_queue_locked = true;
509254885Sdumbbell			}
510254885Sdumbbell			if (intr) {
511254885Sdumbbell				r = cv_timedwait_sig(&rdev->fence_queue,
512254885Sdumbbell				    &rdev->fence_queue_mtx,
513254885Sdumbbell				    timeout);
514254885Sdumbbell			} else {
515254885Sdumbbell				r = cv_timedwait(&rdev->fence_queue,
516254885Sdumbbell				    &rdev->fence_queue_mtx,
517254885Sdumbbell				    timeout);
518254885Sdumbbell			}
519259684Sdumbbell			if (r == EINTR)
520259684Sdumbbell				r = ERESTARTSYS;
521254885Sdumbbell			if (r != 0) {
522254885Sdumbbell				if (r == EWOULDBLOCK) {
523254885Sdumbbell					signaled =
524254885Sdumbbell					    radeon_fence_any_seq_signaled(
525254885Sdumbbell						rdev, target_seq);
526254885Sdumbbell				}
527254885Sdumbbell				break;
528254885Sdumbbell			}
529254885Sdumbbell		}
530254885Sdumbbell		if (fence_queue_locked) {
531254885Sdumbbell			mtx_unlock(&rdev->fence_queue_mtx);
532254885Sdumbbell		}
533254885Sdumbbell		for (i = 0; i < RADEON_NUM_RINGS; ++i) {
534254885Sdumbbell			if (target_seq[i]) {
535254885Sdumbbell				radeon_irq_kms_sw_irq_put(rdev, i);
536254885Sdumbbell			}
537254885Sdumbbell		}
538259684Sdumbbell		if (unlikely(r == ERESTARTSYS)) {
539254885Sdumbbell			return -r;
540254885Sdumbbell		}
541254885Sdumbbell		CTR2(KTR_DRM, "radeon fence: wait end (ring=%d, target_seq=%d)",
542254885Sdumbbell		    ring, target_seq[ring]);
543254885Sdumbbell
544254885Sdumbbell		if (unlikely(!signaled)) {
545254885Sdumbbell#ifndef __FreeBSD__
546254885Sdumbbell			/* we were interrupted for some reason and fence
547254885Sdumbbell			 * isn't signaled yet, resume waiting */
548254885Sdumbbell			if (r) {
549254885Sdumbbell				continue;
550254885Sdumbbell			}
551254885Sdumbbell#endif
552254885Sdumbbell
553254885Sdumbbell			sx_xlock(&rdev->ring_lock);
554254885Sdumbbell			for (i = 0, tmp = 0; i < RADEON_NUM_RINGS; ++i) {
555254885Sdumbbell				if (time_after(rdev->fence_drv[i].last_activity, tmp)) {
556254885Sdumbbell					tmp = rdev->fence_drv[i].last_activity;
557254885Sdumbbell				}
558254885Sdumbbell			}
559254885Sdumbbell			/* test if somebody else has already decided that this is a lockup */
560254885Sdumbbell			if (last_activity != tmp) {
561254885Sdumbbell				last_activity = tmp;
562254885Sdumbbell				sx_xunlock(&rdev->ring_lock);
563254885Sdumbbell				continue;
564254885Sdumbbell			}
565254885Sdumbbell
566254885Sdumbbell			if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) {
567254885Sdumbbell				/* good news we believe it's a lockup */
568254885Sdumbbell				dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016jx)\n",
569254885Sdumbbell					 (uintmax_t)target_seq[ring]);
570254885Sdumbbell
571254885Sdumbbell				/* change last activity so nobody else think there is a lockup */
572254885Sdumbbell				for (i = 0; i < RADEON_NUM_RINGS; ++i) {
573254885Sdumbbell					rdev->fence_drv[i].last_activity = jiffies;
574254885Sdumbbell				}
575254885Sdumbbell
576254885Sdumbbell				/* mark the ring as not ready any more */
577254885Sdumbbell				rdev->ring[ring].ready = false;
578254885Sdumbbell				sx_xunlock(&rdev->ring_lock);
579254885Sdumbbell				return -EDEADLK;
580254885Sdumbbell			}
581254885Sdumbbell			sx_xunlock(&rdev->ring_lock);
582254885Sdumbbell		}
583254885Sdumbbell	}
584254885Sdumbbell	return 0;
585254885Sdumbbell}
586254885Sdumbbell
587254885Sdumbbell/**
588254885Sdumbbell * radeon_fence_wait_any - wait for a fence to signal on any ring
589254885Sdumbbell *
590254885Sdumbbell * @rdev: radeon device pointer
591254885Sdumbbell * @fences: radeon fence object(s)
592254885Sdumbbell * @intr: use interruptable sleep
593254885Sdumbbell *
594254885Sdumbbell * Wait for any requested fence to signal (all asics).  Fence
595254885Sdumbbell * array is indexed by ring id.  @intr selects whether to use
596254885Sdumbbell * interruptable (true) or non-interruptable (false) sleep when
597254885Sdumbbell * waiting for the fences. Used by the suballocator.
598254885Sdumbbell * Returns 0 if any fence has passed, error for all other cases.
599254885Sdumbbell */
600254885Sdumbbellint radeon_fence_wait_any(struct radeon_device *rdev,
601254885Sdumbbell			  struct radeon_fence **fences,
602254885Sdumbbell			  bool intr)
603254885Sdumbbell{
604254885Sdumbbell	uint64_t seq[RADEON_NUM_RINGS];
605254885Sdumbbell	unsigned i;
606254885Sdumbbell	int r;
607254885Sdumbbell
608254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
609254885Sdumbbell		seq[i] = 0;
610254885Sdumbbell
611254885Sdumbbell		if (!fences[i]) {
612254885Sdumbbell			continue;
613254885Sdumbbell		}
614254885Sdumbbell
615254885Sdumbbell		if (fences[i]->seq == RADEON_FENCE_SIGNALED_SEQ) {
616298955Spfg			/* something was already signaled */
617254885Sdumbbell			return 0;
618254885Sdumbbell		}
619254885Sdumbbell
620254885Sdumbbell		seq[i] = fences[i]->seq;
621254885Sdumbbell	}
622254885Sdumbbell
623254885Sdumbbell	r = radeon_fence_wait_any_seq(rdev, seq, intr);
624254885Sdumbbell	if (r) {
625254885Sdumbbell		return r;
626254885Sdumbbell	}
627254885Sdumbbell	return 0;
628254885Sdumbbell}
629254885Sdumbbell
630254885Sdumbbell/**
631254885Sdumbbell * radeon_fence_wait_next_locked - wait for the next fence to signal
632254885Sdumbbell *
633254885Sdumbbell * @rdev: radeon device pointer
634254885Sdumbbell * @ring: ring index the fence is associated with
635254885Sdumbbell *
636254885Sdumbbell * Wait for the next fence on the requested ring to signal (all asics).
637254885Sdumbbell * Returns 0 if the next fence has passed, error for all other cases.
638254885Sdumbbell * Caller must hold ring lock.
639254885Sdumbbell */
640254885Sdumbbellint radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
641254885Sdumbbell{
642254885Sdumbbell	uint64_t seq;
643254885Sdumbbell
644280183Sdumbbell	seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL;
645254885Sdumbbell	if (seq >= rdev->fence_drv[ring].sync_seq[ring]) {
646254885Sdumbbell		/* nothing to wait for, last_seq is
647298955Spfg		   already the last emitted fence */
648254885Sdumbbell		return -ENOENT;
649254885Sdumbbell	}
650254885Sdumbbell	return radeon_fence_wait_seq(rdev, seq, ring, false, false);
651254885Sdumbbell}
652254885Sdumbbell
653254885Sdumbbell/**
654254885Sdumbbell * radeon_fence_wait_empty_locked - wait for all fences to signal
655254885Sdumbbell *
656254885Sdumbbell * @rdev: radeon device pointer
657254885Sdumbbell * @ring: ring index the fence is associated with
658254885Sdumbbell *
659254885Sdumbbell * Wait for all fences on the requested ring to signal (all asics).
660254885Sdumbbell * Returns 0 if the fences have passed, error for all other cases.
661254885Sdumbbell * Caller must hold ring lock.
662254885Sdumbbell */
663254885Sdumbbellint radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
664254885Sdumbbell{
665254885Sdumbbell	uint64_t seq = rdev->fence_drv[ring].sync_seq[ring];
666254885Sdumbbell	int r;
667254885Sdumbbell
668254885Sdumbbell	r = radeon_fence_wait_seq(rdev, seq, ring, false, false);
669254885Sdumbbell	if (r) {
670254885Sdumbbell		if (r == -EDEADLK) {
671254885Sdumbbell			return -EDEADLK;
672254885Sdumbbell		}
673254885Sdumbbell		dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n",
674254885Sdumbbell			ring, r);
675254885Sdumbbell	}
676254885Sdumbbell	return 0;
677254885Sdumbbell}
678254885Sdumbbell
679254885Sdumbbell/**
680254885Sdumbbell * radeon_fence_ref - take a ref on a fence
681254885Sdumbbell *
682254885Sdumbbell * @fence: radeon fence object
683254885Sdumbbell *
684254885Sdumbbell * Take a reference on a fence (all asics).
685254885Sdumbbell * Returns the fence.
686254885Sdumbbell */
687254885Sdumbbellstruct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)
688254885Sdumbbell{
689254885Sdumbbell	refcount_acquire(&fence->kref);
690254885Sdumbbell	return fence;
691254885Sdumbbell}
692254885Sdumbbell
693254885Sdumbbell/**
694254885Sdumbbell * radeon_fence_unref - remove a ref on a fence
695254885Sdumbbell *
696254885Sdumbbell * @fence: radeon fence object
697254885Sdumbbell *
698254885Sdumbbell * Remove a reference on a fence (all asics).
699254885Sdumbbell */
700254885Sdumbbellvoid radeon_fence_unref(struct radeon_fence **fence)
701254885Sdumbbell{
702254885Sdumbbell	struct radeon_fence *tmp = *fence;
703254885Sdumbbell
704254885Sdumbbell	*fence = NULL;
705254885Sdumbbell	if (tmp) {
706254885Sdumbbell		if (refcount_release(&tmp->kref)) {
707254885Sdumbbell			radeon_fence_destroy(tmp);
708254885Sdumbbell		}
709254885Sdumbbell	}
710254885Sdumbbell}
711254885Sdumbbell
712254885Sdumbbell/**
713254885Sdumbbell * radeon_fence_count_emitted - get the count of emitted fences
714254885Sdumbbell *
715254885Sdumbbell * @rdev: radeon device pointer
716254885Sdumbbell * @ring: ring index the fence is associated with
717254885Sdumbbell *
718254885Sdumbbell * Get the number of fences emitted on the requested ring (all asics).
719254885Sdumbbell * Returns the number of emitted fences on the ring.  Used by the
720254885Sdumbbell * dynpm code to ring track activity.
721254885Sdumbbell */
722254885Sdumbbellunsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring)
723254885Sdumbbell{
724254885Sdumbbell	uint64_t emitted;
725254885Sdumbbell
726254885Sdumbbell	/* We are not protected by ring lock when reading the last sequence
727254885Sdumbbell	 * but it's ok to report slightly wrong fence count here.
728254885Sdumbbell	 */
729254885Sdumbbell	radeon_fence_process(rdev, ring);
730254885Sdumbbell	emitted = rdev->fence_drv[ring].sync_seq[ring]
731280183Sdumbbell		- atomic64_read(&rdev->fence_drv[ring].last_seq);
732254885Sdumbbell	/* to avoid 32bits warp around */
733254885Sdumbbell	if (emitted > 0x10000000) {
734254885Sdumbbell		emitted = 0x10000000;
735254885Sdumbbell	}
736254885Sdumbbell	return (unsigned)emitted;
737254885Sdumbbell}
738254885Sdumbbell
739254885Sdumbbell/**
740254885Sdumbbell * radeon_fence_need_sync - do we need a semaphore
741254885Sdumbbell *
742254885Sdumbbell * @fence: radeon fence object
743254885Sdumbbell * @dst_ring: which ring to check against
744254885Sdumbbell *
745254885Sdumbbell * Check if the fence needs to be synced against another ring
746254885Sdumbbell * (all asics).  If so, we need to emit a semaphore.
747254885Sdumbbell * Returns true if we need to sync with another ring, false if
748254885Sdumbbell * not.
749254885Sdumbbell */
750254885Sdumbbellbool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring)
751254885Sdumbbell{
752254885Sdumbbell	struct radeon_fence_driver *fdrv;
753254885Sdumbbell
754254885Sdumbbell	if (!fence) {
755254885Sdumbbell		return false;
756254885Sdumbbell	}
757254885Sdumbbell
758254885Sdumbbell	if (fence->ring == dst_ring) {
759254885Sdumbbell		return false;
760254885Sdumbbell	}
761254885Sdumbbell
762254885Sdumbbell	/* we are protected by the ring mutex */
763254885Sdumbbell	fdrv = &fence->rdev->fence_drv[dst_ring];
764254885Sdumbbell	if (fence->seq <= fdrv->sync_seq[fence->ring]) {
765254885Sdumbbell		return false;
766254885Sdumbbell	}
767254885Sdumbbell
768254885Sdumbbell	return true;
769254885Sdumbbell}
770254885Sdumbbell
771254885Sdumbbell/**
772254885Sdumbbell * radeon_fence_note_sync - record the sync point
773254885Sdumbbell *
774254885Sdumbbell * @fence: radeon fence object
775254885Sdumbbell * @dst_ring: which ring to check against
776254885Sdumbbell *
777254885Sdumbbell * Note the sequence number at which point the fence will
778254885Sdumbbell * be synced with the requested ring (all asics).
779254885Sdumbbell */
780254885Sdumbbellvoid radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring)
781254885Sdumbbell{
782254885Sdumbbell	struct radeon_fence_driver *dst, *src;
783254885Sdumbbell	unsigned i;
784254885Sdumbbell
785254885Sdumbbell	if (!fence) {
786254885Sdumbbell		return;
787254885Sdumbbell	}
788254885Sdumbbell
789254885Sdumbbell	if (fence->ring == dst_ring) {
790254885Sdumbbell		return;
791254885Sdumbbell	}
792254885Sdumbbell
793254885Sdumbbell	/* we are protected by the ring mutex */
794254885Sdumbbell	src = &fence->rdev->fence_drv[fence->ring];
795254885Sdumbbell	dst = &fence->rdev->fence_drv[dst_ring];
796254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
797254885Sdumbbell		if (i == dst_ring) {
798254885Sdumbbell			continue;
799254885Sdumbbell		}
800254885Sdumbbell		dst->sync_seq[i] = max(dst->sync_seq[i], src->sync_seq[i]);
801254885Sdumbbell	}
802254885Sdumbbell}
803254885Sdumbbell
804254885Sdumbbell/**
805254885Sdumbbell * radeon_fence_driver_start_ring - make the fence driver
806254885Sdumbbell * ready for use on the requested ring.
807254885Sdumbbell *
808254885Sdumbbell * @rdev: radeon device pointer
809254885Sdumbbell * @ring: ring index to start the fence driver on
810254885Sdumbbell *
811254885Sdumbbell * Make the fence driver ready for processing (all asics).
812254885Sdumbbell * Not all asics have all rings, so each asic will only
813254885Sdumbbell * start the fence driver on the rings it has.
814254885Sdumbbell * Returns 0 for success, errors for failure.
815254885Sdumbbell */
816254885Sdumbbellint radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
817254885Sdumbbell{
818254885Sdumbbell	uint64_t index;
819254885Sdumbbell	int r;
820254885Sdumbbell
821254885Sdumbbell	radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
822254885Sdumbbell	if (rdev->wb.use_event || !radeon_ring_supports_scratch_reg(rdev, &rdev->ring[ring])) {
823254885Sdumbbell		rdev->fence_drv[ring].scratch_reg = 0;
824254885Sdumbbell		index = R600_WB_EVENT_OFFSET + ring * 4;
825254885Sdumbbell	} else {
826254885Sdumbbell		r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg);
827254885Sdumbbell		if (r) {
828254885Sdumbbell			dev_err(rdev->dev, "fence failed to get scratch register\n");
829254885Sdumbbell			return r;
830254885Sdumbbell		}
831254885Sdumbbell		index = RADEON_WB_SCRATCH_OFFSET +
832254885Sdumbbell			rdev->fence_drv[ring].scratch_reg -
833254885Sdumbbell			rdev->scratch.reg_base;
834254885Sdumbbell	}
835254885Sdumbbell	rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
836254885Sdumbbell	rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index;
837280183Sdumbbell	radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring);
838254885Sdumbbell	rdev->fence_drv[ring].initialized = true;
839254885Sdumbbell	dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016jx and cpu addr 0x%p\n",
840254885Sdumbbell		 ring, (uintmax_t)rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr);
841254885Sdumbbell	return 0;
842254885Sdumbbell}
843254885Sdumbbell
844254885Sdumbbell/**
845254885Sdumbbell * radeon_fence_driver_init_ring - init the fence driver
846254885Sdumbbell * for the requested ring.
847254885Sdumbbell *
848254885Sdumbbell * @rdev: radeon device pointer
849254885Sdumbbell * @ring: ring index to start the fence driver on
850254885Sdumbbell *
851254885Sdumbbell * Init the fence driver for the requested ring (all asics).
852254885Sdumbbell * Helper function for radeon_fence_driver_init().
853254885Sdumbbell */
854254885Sdumbbellstatic void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring)
855254885Sdumbbell{
856254885Sdumbbell	int i;
857254885Sdumbbell
858254885Sdumbbell	rdev->fence_drv[ring].scratch_reg = -1;
859254885Sdumbbell	rdev->fence_drv[ring].cpu_addr = NULL;
860254885Sdumbbell	rdev->fence_drv[ring].gpu_addr = 0;
861254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; ++i)
862254885Sdumbbell		rdev->fence_drv[ring].sync_seq[i] = 0;
863280183Sdumbbell	atomic64_set(&rdev->fence_drv[ring].last_seq, 0);
864254885Sdumbbell	rdev->fence_drv[ring].last_activity = jiffies;
865254885Sdumbbell	rdev->fence_drv[ring].initialized = false;
866254885Sdumbbell}
867254885Sdumbbell
868254885Sdumbbell/**
869254885Sdumbbell * radeon_fence_driver_init - init the fence driver
870254885Sdumbbell * for all possible rings.
871254885Sdumbbell *
872254885Sdumbbell * @rdev: radeon device pointer
873254885Sdumbbell *
874254885Sdumbbell * Init the fence driver for all possible rings (all asics).
875254885Sdumbbell * Not all asics have all rings, so each asic will only
876254885Sdumbbell * start the fence driver on the rings it has using
877254885Sdumbbell * radeon_fence_driver_start_ring().
878254885Sdumbbell * Returns 0 for success.
879254885Sdumbbell */
880254885Sdumbbellint radeon_fence_driver_init(struct radeon_device *rdev)
881254885Sdumbbell{
882254885Sdumbbell	int ring;
883254885Sdumbbell
884254885Sdumbbell	mtx_init(&rdev->fence_queue_mtx,
885254885Sdumbbell	    "drm__radeon_device__fence_queue_mtx", NULL, MTX_DEF);
886254885Sdumbbell	cv_init(&rdev->fence_queue, "drm__radeon_device__fence_queue");
887254885Sdumbbell	for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
888254885Sdumbbell		radeon_fence_driver_init_ring(rdev, ring);
889254885Sdumbbell	}
890254885Sdumbbell	if (radeon_debugfs_fence_init(rdev)) {
891254885Sdumbbell		dev_err(rdev->dev, "fence debugfs file creation failed\n");
892254885Sdumbbell	}
893254885Sdumbbell	return 0;
894254885Sdumbbell}
895254885Sdumbbell
896254885Sdumbbell/**
897254885Sdumbbell * radeon_fence_driver_fini - tear down the fence driver
898254885Sdumbbell * for all possible rings.
899254885Sdumbbell *
900254885Sdumbbell * @rdev: radeon device pointer
901254885Sdumbbell *
902254885Sdumbbell * Tear down the fence driver for all possible rings (all asics).
903254885Sdumbbell */
904254885Sdumbbellvoid radeon_fence_driver_fini(struct radeon_device *rdev)
905254885Sdumbbell{
906254885Sdumbbell	int ring, r;
907254885Sdumbbell
908254885Sdumbbell	sx_xlock(&rdev->ring_lock);
909254885Sdumbbell	for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
910254885Sdumbbell		if (!rdev->fence_drv[ring].initialized)
911254885Sdumbbell			continue;
912254885Sdumbbell		r = radeon_fence_wait_empty_locked(rdev, ring);
913254885Sdumbbell		if (r) {
914254885Sdumbbell			/* no need to trigger GPU reset as we are unloading */
915254885Sdumbbell			radeon_fence_driver_force_completion(rdev);
916254885Sdumbbell		}
917254885Sdumbbell		cv_broadcast(&rdev->fence_queue);
918254885Sdumbbell		radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
919254885Sdumbbell		rdev->fence_drv[ring].initialized = false;
920254885Sdumbbell		cv_destroy(&rdev->fence_queue);
921254885Sdumbbell	}
922254885Sdumbbell	sx_xunlock(&rdev->ring_lock);
923254885Sdumbbell}
924254885Sdumbbell
925254885Sdumbbell/**
926254885Sdumbbell * radeon_fence_driver_force_completion - force all fence waiter to complete
927254885Sdumbbell *
928254885Sdumbbell * @rdev: radeon device pointer
929254885Sdumbbell *
930254885Sdumbbell * In case of GPU reset failure make sure no process keep waiting on fence
931254885Sdumbbell * that will never complete.
932254885Sdumbbell */
933254885Sdumbbellvoid radeon_fence_driver_force_completion(struct radeon_device *rdev)
934254885Sdumbbell{
935254885Sdumbbell	int ring;
936254885Sdumbbell
937254885Sdumbbell	for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
938254885Sdumbbell		if (!rdev->fence_drv[ring].initialized)
939254885Sdumbbell			continue;
940254885Sdumbbell		radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring);
941254885Sdumbbell	}
942254885Sdumbbell}
943254885Sdumbbell
944254885Sdumbbell
945254885Sdumbbell/*
946254885Sdumbbell * Fence debugfs
947254885Sdumbbell */
948254885Sdumbbell#if defined(CONFIG_DEBUG_FS)
949254885Sdumbbellstatic int radeon_debugfs_fence_info(struct seq_file *m, void *data)
950254885Sdumbbell{
951254885Sdumbbell	struct drm_info_node *node = (struct drm_info_node *)m->private;
952254885Sdumbbell	struct drm_device *dev = node->minor->dev;
953254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
954254885Sdumbbell	int i, j;
955254885Sdumbbell
956254885Sdumbbell	for (i = 0; i < RADEON_NUM_RINGS; ++i) {
957254885Sdumbbell		if (!rdev->fence_drv[i].initialized)
958254885Sdumbbell			continue;
959254885Sdumbbell
960254885Sdumbbell		seq_printf(m, "--- ring %d ---\n", i);
961254885Sdumbbell		seq_printf(m, "Last signaled fence 0x%016llx\n",
962280183Sdumbbell			   (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq));
963254885Sdumbbell		seq_printf(m, "Last emitted        0x%016llx\n",
964254885Sdumbbell			   rdev->fence_drv[i].sync_seq[i]);
965254885Sdumbbell
966254885Sdumbbell		for (j = 0; j < RADEON_NUM_RINGS; ++j) {
967254885Sdumbbell			if (i != j && rdev->fence_drv[j].initialized)
968254885Sdumbbell				seq_printf(m, "Last sync to ring %d 0x%016llx\n",
969254885Sdumbbell					   j, rdev->fence_drv[i].sync_seq[j]);
970254885Sdumbbell		}
971254885Sdumbbell	}
972254885Sdumbbell	return 0;
973254885Sdumbbell}
974254885Sdumbbell
975254885Sdumbbellstatic struct drm_info_list radeon_debugfs_fence_list[] = {
976254885Sdumbbell	{"radeon_fence_info", &radeon_debugfs_fence_info, 0, NULL},
977254885Sdumbbell};
978254885Sdumbbell#endif
979254885Sdumbbell
980254885Sdumbbellint radeon_debugfs_fence_init(struct radeon_device *rdev)
981254885Sdumbbell{
982254885Sdumbbell#if defined(CONFIG_DEBUG_FS)
983254885Sdumbbell	return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1);
984254885Sdumbbell#else
985254885Sdumbbell	return 0;
986254885Sdumbbell#endif
987254885Sdumbbell}
988