void
amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq)
{
amdgpu_userq_walk_and_drop_fence_drv(&userq->fence_drv_xa);
xa_destroy(&userq->fence_drv_xa); /* Drop the fence_drv reference held by user queue */
amdgpu_userq_fence_driver_put(userq->fence_drv);
}
/* Check if hardware has already processed the job */
spin_lock_irqsave(&fence_drv->fence_list_lock, flags); if (!dma_fence_is_signaled(fence))
list_add_tail(&userq_fence->link, &fence_drv->fences); else
dma_fence_put(fence);
mapping = amdgpu_vm_bo_lookup_mapping(queue->vm, addr >> PAGE_SHIFT); if (!mapping) {
amdgpu_bo_unreserve(queue->vm->root.bo);
DRM_ERROR("Failed to lookup amdgpu_bo_va_mapping\n"); return -EINVAL;
}
bo = amdgpu_bo_ref(mapping->bo_va->base.bo);
amdgpu_bo_unreserve(queue->vm->root.bo);
r = amdgpu_bo_reserve(bo, true); if (r) {
DRM_ERROR("Failed to reserve userqueue wptr bo"); return r;
}
r = amdgpu_bo_kmap(bo, (void **)&ptr); if (r) {
DRM_ERROR("Failed mapping the userqueue wptr bo"); goto map_error;
}
/* Array of pointers to the looked up syncobjs */
syncobj = kmalloc_array(num_syncobj_handles, sizeof(*syncobj), GFP_KERNEL); if (!syncobj) {
r = -ENOMEM; goto free_syncobj_handles;
}
for (entry = 0; entry < num_syncobj_handles; entry++) {
syncobj[entry] = drm_syncobj_find(filp, syncobj_handles[entry]); if (!syncobj[entry]) {
r = -ENOENT; goto free_syncobj;
}
}
num_read_bo_handles = args->num_bo_read_handles;
bo_handles_read = memdup_user(u64_to_user_ptr(args->bo_read_handles), sizeof(u32) * num_read_bo_handles); if (IS_ERR(bo_handles_read)) {
r = PTR_ERR(bo_handles_read); goto free_syncobj;
}
/* Array of pointers to the GEM read objects */
gobj_read = kmalloc_array(num_read_bo_handles, sizeof(*gobj_read), GFP_KERNEL); if (!gobj_read) {
r = -ENOMEM; goto free_bo_handles_read;
}
for (rentry = 0; rentry < num_read_bo_handles; rentry++) {
gobj_read[rentry] = drm_gem_object_lookup(filp, bo_handles_read[rentry]); if (!gobj_read[rentry]) {
r = -ENOENT; goto put_gobj_read;
}
}
num_write_bo_handles = args->num_bo_write_handles;
bo_handles_write = memdup_user(u64_to_user_ptr(args->bo_write_handles), sizeof(u32) * num_write_bo_handles); if (IS_ERR(bo_handles_write)) {
r = PTR_ERR(bo_handles_write); goto put_gobj_read;
}
/* Array of pointers to the GEM write objects */
gobj_write = kmalloc_array(num_write_bo_handles, sizeof(*gobj_write), GFP_KERNEL); if (!gobj_write) {
r = -ENOMEM; goto free_bo_handles_write;
}
for (wentry = 0; wentry < num_write_bo_handles; wentry++) {
gobj_write[wentry] = drm_gem_object_lookup(filp, bo_handles_write[wentry]); if (!gobj_write[wentry]) {
r = -ENOENT; goto put_gobj_write;
}
}
/* Retrieve the user queue */
queue = idr_find(&userq_mgr->userq_idr, args->queue_id); if (!queue) {
r = -ENOENT; goto put_gobj_write;
}
r = amdgpu_userq_fence_read_wptr(queue, &wptr); if (r) goto put_gobj_write;
r = amdgpu_userq_fence_alloc(&userq_fence); if (r) goto put_gobj_write;
/* We are here means UQ is active, make sure the eviction fence is valid */
amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
/* Create a new fence */
r = amdgpu_userq_fence_create(queue, userq_fence, wptr, &fence); if (r) {
mutex_unlock(&userq_mgr->userq_mutex);
kmem_cache_free(amdgpu_userq_fence_slab, userq_fence); goto put_gobj_write;
}
/* Lock all BOs with retry handling */
drm_exec_until_all_locked(&exec) {
r = drm_exec_prepare_array(&exec, gobj_read, num_read_bo_handles, 1);
drm_exec_retry_on_contention(&exec); if (r) {
drm_exec_fini(&exec); goto put_gobj_write;
}
r = drm_exec_prepare_array(&exec, gobj_write, num_write_bo_handles, 1);
drm_exec_retry_on_contention(&exec); if (r) {
drm_exec_fini(&exec); goto put_gobj_write;
}
}
if (!wait_info->num_fences) { if (num_points) { struct dma_fence_unwrap iter; struct dma_fence *fence; struct dma_fence *f;
for (i = 0; i < num_points; i++) {
r = drm_syncobj_find_fence(filp, timeline_handles[i],
timeline_points[i],
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
&fence); if (r) goto exec_fini;
for (i = 0; i < num_points; i++) {
r = drm_syncobj_find_fence(filp, timeline_handles[i],
timeline_points[i],
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
&fence); if (r) goto free_fences;
dma_fence_unwrap_for_each(f, &iter, fence) { if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
r = -EINVAL; goto free_fences;
}
dma_fence_get(f);
fences[num_fences++] = f;
}
dma_fence_put(fence);
}
}
/* Retrieve syncobj's fence */ for (i = 0; i < num_syncobj; i++) { struct dma_fence *fence;
r = drm_syncobj_find_fence(filp, syncobj_handles[i], 0,
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
&fence); if (r) goto free_fences;
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
r = -EINVAL; goto free_fences;
}
waitq = idr_find(&userq_mgr->userq_idr, wait_info->waitq_id); if (!waitq) {
r = -EINVAL; goto free_fences;
}
for (i = 0, cnt = 0; i < num_fences; i++) { struct amdgpu_userq_fence_driver *fence_drv; struct amdgpu_userq_fence *userq_fence;
u32 index;
userq_fence = to_amdgpu_userq_fence(fences[i]); if (!userq_fence) { /* *Justwaitingonotherdriverfencesshould *begoodfornow
*/
r = dma_fence_wait(fences[i], true); if (r) {
dma_fence_put(fences[i]); goto free_fences;
}
dma_fence_put(fences[i]); continue;
}
fence_drv = userq_fence->fence_drv; /* *Weneedtomakesuretheuserqueuereleasetheirreference *tothefencedriversatsomepointbeforequeuedestruction. *Otherwise,wewouldgatherthosereferencesuntilwedon't *haveanymorespaceleftandcrash.
*/
r = xa_alloc(&waitq->fence_drv_xa, &index, fence_drv,
xa_limit_32b, GFP_KERNEL); if (r) goto free_fences;
amdgpu_userq_fence_driver_get(fence_drv);
/* Store drm syncobj's gpu va address and value */
fence_info[cnt].va = fence_drv->va;
fence_info[cnt].value = fences[i]->seqno;
dma_fence_put(fences[i]); /* Increment the actual userq fence count */
cnt++;
}
wait_info->num_fences = cnt; /* Copy userq fence info to user space */ if (copy_to_user(u64_to_user_ptr(wait_info->out_fences),
fence_info, wait_info->num_fences * sizeof(*fence_info))) {
r = -EFAULT; goto free_fences;
}
kfree(fences);
kfree(fence_info);
}
drm_exec_fini(&exec); for (i = 0; i < num_read_bo_handles; i++)
drm_gem_object_put(gobj_read[i]);
kfree(gobj_read);
for (i = 0; i < num_write_bo_handles; i++)
drm_gem_object_put(gobj_write[i]);
kfree(gobj_write);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.