static int submit_fence_sync(const struct etnaviv_gem_submit *submit) { unsigned int context = submit->gpu->fence_context; int i, ret = 0; for (i = 0; i < submit->nr_bos; i++) { struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE; bool explicit = !!(submit->flags & ETNA_SUBMIT_NO_IMPLICIT); ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write, explicit); if (ret) break; } if (submit->flags & ETNA_SUBMIT_FENCE_FD_IN) { /* * Wait if the fence is from a foreign context, or if the fence * array contains any fence from a foreign context. */ if (!dma_fence_match_context(submit->in_fence, context)) ret = dma_fence_wait(submit->in_fence, true); } return ret; }
uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) { signed long r; uint32_t val; struct dma_fence *f; struct amdgpu_kiq *kiq = &adev->gfx.kiq; struct amdgpu_ring *ring = &kiq->ring; BUG_ON(!ring->funcs->emit_rreg); mutex_lock(&adev->virt.lock_kiq); amdgpu_ring_alloc(ring, 32); amdgpu_ring_emit_rreg(ring, reg); amdgpu_fence_emit(ring, &f); amdgpu_ring_commit(ring); mutex_unlock(&adev->virt.lock_kiq); r = dma_fence_wait(f, false); if (r) DRM_ERROR("wait for kiq fence error: %ld.\n", r); dma_fence_put(f); val = adev->wb.wb[adev->virt.reg_val_offs]; return val; }
int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, uint32_t vmid, uint64_t gpu_addr, uint32_t *ib_cmd, uint32_t ib_len) { struct amdgpu_device *adev = (struct amdgpu_device *)kgd; struct amdgpu_job *job; struct amdgpu_ib *ib; struct amdgpu_ring *ring; struct dma_fence *f = NULL; int ret; switch (engine) { case KGD_ENGINE_MEC1: ring = &adev->gfx.compute_ring[0]; break; case KGD_ENGINE_SDMA1: ring = &adev->sdma.instance[0].ring; break; case KGD_ENGINE_SDMA2: ring = &adev->sdma.instance[1].ring; break; default: pr_err("Invalid engine in IB submission: %d\n", engine); ret = -EINVAL; goto err; } ret = amdgpu_job_alloc(adev, 1, &job, NULL); if (ret) goto err; ib = &job->ibs[0]; memset(ib, 0, sizeof(struct amdgpu_ib)); ib->gpu_addr = gpu_addr; ib->ptr = ib_cmd; ib->length_dw = ib_len; /* This works for NO_HWS. TODO: need to handle without knowing VMID */ job->vmid = vmid; ret = amdgpu_ib_schedule(ring, 1, ib, job, &f); if (ret) { DRM_ERROR("amdgpu: failed to schedule IB.\n"); goto err_ib_sched; } ret = dma_fence_wait(f, false); err_ib_sched: dma_fence_put(f); amdgpu_job_free(job); err: return ret; }
int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, unsigned ring_id) { struct amdgpu_ctx_ring *cring = &ctx->rings[ring_id]; unsigned idx = cring->sequence & (amdgpu_sched_jobs - 1); struct dma_fence *other = cring->fences[idx]; if (other) { signed long r; r = dma_fence_wait(other, true); if (r < 0) { if (r != -ERESTARTSYS) DRM_ERROR("Error (%ld) waiting for fence!\n", r); return r; } } return 0; }
int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, struct drm_sched_entity *entity) { struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity); unsigned idx = centity->sequence & (amdgpu_sched_jobs - 1); struct dma_fence *other = centity->fences[idx]; if (other) { signed long r; r = dma_fence_wait(other, true); if (r < 0) { if (r != -ERESTARTSYS) DRM_ERROR("Error (%ld) waiting for fence!\n", r); return r; } } return 0; }
/** * amdgpu_vm_cpu_prepare - prepare page table update with the CPU * * @p: see amdgpu_vm_update_params definition * @owner: owner we need to sync to * @exclusive: exclusive move fence we need to sync to * * Returns: * Negativ errno, 0 for success. */ static int amdgpu_vm_cpu_prepare(struct amdgpu_vm_update_params *p, void *owner, struct dma_fence *exclusive) { int r; /* Wait for PT BOs to be idle. PTs share the same resv. object * as the root PD BO */ r = amdgpu_bo_sync_wait(p->vm->root.base.bo, owner, true); if (unlikely(r)) return r; /* Wait for any BO move to be completed */ if (exclusive) { r = dma_fence_wait(exclusive, true); if (unlikely(r)) return r; } return 0; }
/** * amdgpu_fence_wait_empty - wait for all fences to signal * * @adev: amdgpu device pointer * @ring: ring index the fence is associated with * * Wait for all fences on the requested ring to signal (all asics). * Returns 0 if the fences have passed, error for all other cases. */ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring) { uint64_t seq = READ_ONCE(ring->fence_drv.sync_seq); struct dma_fence *fence, **ptr; int r; if (!seq) return 0; ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; rcu_read_lock(); fence = rcu_dereference(*ptr); if (!fence || !dma_fence_get_rcu(fence)) { rcu_read_unlock(); return 0; } rcu_read_unlock(); r = dma_fence_wait(fence, false); dma_fence_put(fence); return r; }
void amdgpu_virt_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) { signed long r; struct dma_fence *f; struct amdgpu_kiq *kiq = &adev->gfx.kiq; struct amdgpu_ring *ring = &kiq->ring; BUG_ON(!ring->funcs->emit_wreg); mutex_lock(&adev->virt.lock); amdgpu_ring_alloc(ring, 32); amdgpu_ring_emit_hdp_flush(ring); amdgpu_ring_emit_wreg(ring, reg, v); amdgpu_ring_emit_hdp_invalidate(ring); amdgpu_fence_emit(ring, &f); amdgpu_ring_commit(ring); mutex_unlock(&adev->virt.lock); r = dma_fence_wait(f, false); if (r) DRM_ERROR("wait for kiq fence error: %ld.\n", r); dma_fence_put(f); }
/** * amdgpu_fence_emit - emit a fence on the requested ring * * @ring: ring the fence is associated with * @f: resulting fence object * * Emits a fence command on the requested ring (all asics). * Returns 0 on success, -ENOMEM on failure. */ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f) { struct amdgpu_device *adev = ring->adev; struct amdgpu_fence *fence; struct dma_fence *old, **ptr; uint32_t seq; fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL); if (fence == NULL) return -ENOMEM; seq = ++ring->fence_drv.sync_seq; fence->ring = ring; dma_fence_init(&fence->base, &amdgpu_fence_ops, &ring->fence_drv.lock, adev->fence_context + ring->idx, seq); amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, seq, AMDGPU_FENCE_FLAG_INT); ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; /* This function can't be called concurrently anyway, otherwise * emitting the fence would mess up the hardware ring buffer. */ old = rcu_dereference_protected(*ptr, 1); if (old && !dma_fence_is_signaled(old)) { DRM_INFO("rcu slot is busy\n"); dma_fence_wait(old, false); } rcu_assign_pointer(*ptr, dma_fence_get(&fence->base)); *f = &fence->base; return 0; }