/** * amdgpu_fence_process - check for fence activity * * @ring: pointer to struct amdgpu_ring * * Checks the current fence value and calculates the last * signalled fence value. Wakes the fence queue if the * sequence number has increased. */ void amdgpu_fence_process(struct amdgpu_ring *ring) { struct amdgpu_fence_driver *drv = &ring->fence_drv; uint32_t seq, last_seq; int r; do { last_seq = atomic_read(&ring->fence_drv.last_seq); seq = amdgpu_fence_read(ring); } while (atomic_cmpxchg(&drv->last_seq, last_seq, seq) != last_seq); if (seq != ring->fence_drv.sync_seq) amdgpu_fence_schedule_fallback(ring); while (last_seq != seq) { struct fence *fence, **ptr; ptr = &drv->fences[++last_seq & drv->num_fences_mask]; /* There is always exactly one thread signaling this fence slot */ fence = rcu_dereference_protected(*ptr, 1); RCU_INIT_POINTER(*ptr, NULL); BUG_ON(!fence); r = fence_signal(fence); if (!r) FENCE_TRACE(fence, "signaled from irq context\n"); else BUG(); fence_put(fence); } }
/** * amdgpu_fence_wait_polling - busy wait for givn sequence number * * @ring: ring index the fence is associated with * @wait_seq: sequence number to wait * @timeout: the timeout for waiting in usecs * * Wait for all fences on the requested ring to signal (all asics). * Returns left time if no timeout, 0 or minus if timeout. */ signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring, uint32_t wait_seq, signed long timeout) { uint32_t seq; do { seq = amdgpu_fence_read(ring); udelay(5); timeout -= 5; } while ((int32_t)(wait_seq - seq) > 0 && timeout > 0); return timeout > 0 ? timeout : 0; }