FreeBSD/sys/dev/drm2/radeon/radeon_fence.c
/**
 * radeon_fence_process - process a fence
 *
 * @rdev: radeon_device pointer
 * @ring: ring index the fence is associated with
 *
 * Checks the current fence value and wakes the fence queue
 * if the sequence number has increased (all asics).
 */
process a fence
@rdev: radeon_device pointer
@ring: ring index the fence is associated with

Checks the current fence value and wakes the fence queue
if the sequence number has increased (all asics).
process a fence @rdev : radeon_device pointer @ring : ring index the fence is associated with Checks the current fence value and wakes the fence queue if the sequence number has increased ( all asics ) .
void radeon_fence_process(struct radeon_device *rdev, int ring)
{
	uint64_t seq, last_seq, last_emitted;
	unsigned count_loop = 0;
	bool wake = false;
	last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
	do {
		last_emitted = rdev->fence_drv[ring].sync_seq[ring];
		seq = radeon_fence_read(rdev, ring);
		seq |= last_seq & 0xffffffff00000000LL;
		if (seq < last_seq) {
			seq &= 0xffffffff;
			seq |= last_emitted & 0xffffffff00000000LL;
		}
		if (seq <= last_seq || seq > last_emitted) {
			break;
		}
		wake = true;
		last_seq = seq;
		if ((count_loop++) > 10) {
			break;
		}
	} while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq);
	if (wake) {
		rdev->fence_drv[ring].last_activity = jiffies;
		cv_broadcast(&rdev->fence_queue);
	}
}
void radeon_fence_process ( struct radeon_device * rdev , int ring ) { uint64_t seq , last_seq , last_emitted ; unsigned count_loop = 0 ; bool wake = false ; last_seq = atomic64_read ( & rdev -> fence_drv [ ring ] . last_seq ) ; do { last_emitted = rdev -> fence_drv [ ring ] . sync_seq [ ring ] ; seq = radeon_fence_read ( rdev , ring ) ; seq |= last_seq & 0xffffffff00000000LL ; if ( seq < last_seq ) { seq &= 0xffffffff ; seq |= last_emitted & 0xffffffff00000000LL ; } if ( seq <= last_seq || seq > last_emitted ) { break ; } wake = true ; last_seq = seq ; if ( ( count_loop ++ ) > 10 ) { break ; } } while ( atomic64_xchg ( & rdev -> fence_drv [ ring ] . last_seq , seq ) > seq ) ; if ( wake ) { rdev -> fence_drv [ ring ] . last_activity = jiffies ; cv_broadcast ( & rdev -> fence_queue ) ; } }
radeon_fence_process - process a fence
 @rdev: radeon_device pointer
 @ring: ring index the fence is associated with
radeon_fence_process - process a fence @rdev : radeon_device pointer @ring : ring index the fence is associated with
/* Note there is a scenario here for an infinite loop but it's
	 * very unlikely to happen. For it to happen, the current polling
	 * process need to be interrupted by another process and another
	 * process needs to update the last_seq btw the atomic read and
	 * xchg of the current process.
	 *
	 * More over for this to go in infinite loop there need to be
	 * continuously new fence signaled ie radeon_fence_read needs
	 * to return a different value each time for both the currently
	 * polling process and the other process that xchg the last_seq
	 * btw atomic read and xchg of the current process. And the
	 * value the other process set as last seq must be higher than
	 * the seq value we just read. Which means that current process
	 * need to be interrupted after radeon_fence_read and before
	 * atomic xchg.
	 *
	 * To be even more safe we count the number of time we loop and
	 * we bail after 10 loop just accepting the fact that we might
	 * have temporarly set the last_seq not to the true real last
	 * seq but to an older one.
	 */ /* If we loop over we don't want to return without
		 * checking if a fence is signaled as it means that the
		 * seq we just read is different from the previous on.
		 */ /* We looped over too many time leave with the
			 * fact that we might have set an older fence
			 * seq then the current real last seq as signaled
			 * by the hw.
			 */