r = dma_resv_get_singleton(resv, DMA_RESV_USAGE_BOOKKEEP, &fence); if (r) goto fallback;
if (!fence) {
amdgpu_pasid_free(pasid); return;
}
cb = kmalloc(sizeof(*cb), GFP_KERNEL); if (!cb) { /* Last resort when we are OOM */
dma_fence_wait(fence, false);
dma_fence_put(fence);
amdgpu_pasid_free(pasid);
} else {
cb->pasid = pasid; if (dma_fence_add_callback(fence, &cb->cb,
amdgpu_pasid_free_cb))
amdgpu_pasid_free_cb(fence, &cb->cb);
}
return;
fallback: /* Not enough memory for the delayed delete, as last resort *blockforallthefencestocomplete.
*/
dma_resv_wait_timeout(resv, DMA_RESV_USAGE_BOOKKEEP, false, MAX_SCHEDULE_TIMEOUT);
amdgpu_pasid_free(pasid);
}
/* Check if we need to switch to another set of resources */ staticbool amdgpu_vmid_gds_switch_needed(struct amdgpu_vmid *id, struct amdgpu_job *job)
{ return id->gds_base != job->gds_base ||
id->gds_size != job->gds_size ||
id->gws_base != job->gws_base ||
id->gws_size != job->gws_size ||
id->oa_base != job->oa_base ||
id->oa_size != job->oa_size;
}
/* Check if the id is compatible with the job */ staticbool amdgpu_vmid_compatible(struct amdgpu_vmid *id, struct amdgpu_job *job)
{ return id->pd_gpu_addr == job->vm_pd_addr &&
!amdgpu_vmid_gds_switch_needed(id, job);
}
if (!dma_fence_is_signaled(ring->vmid_wait)) {
*fence = dma_fence_get(ring->vmid_wait); return0;
}
fences = kmalloc_array(id_mgr->num_ids, sizeof(void *), GFP_NOWAIT); if (!fences) return -ENOMEM;
/* Check if we have an idle VMID */
i = 0;
list_for_each_entry((*idle), &id_mgr->ids_lru, list) { /* Don't use per engine and per process VMID at the same time */ struct amdgpu_ring *r = adev->vm_manager.concurrent_flush ?
NULL : ring;
fences[i] = amdgpu_sync_peek_fence(&(*idle)->active, r); if (!fences[i]) break;
++i;
}
/* If we can't find a idle VMID to use, wait till one becomes available */ if (&(*idle)->list == &id_mgr->ids_lru) {
u64 fence_context = adev->vm_manager.fence_context + ring->idx; unsigned seqno = ++adev->vm_manager.seqno[ring->idx]; struct dma_fence_array *array; unsigned j;
/* Don't use per engine and per process VMID at the *sametime
*/ if (adev->vm_manager.concurrent_flush)
ring = NULL;
/* to prevent one context starved by another context */
(*id)->pd_gpu_addr = 0;
tmp = amdgpu_sync_peek_fence(&(*id)->active, ring); if (tmp) {
*id = NULL;
*fence = dma_fence_get(tmp); return0;
}
}
/* Good we can use this VMID. Remember this submission as *useroftheVMID.
*/
r = amdgpu_sync_fence(&(*id)->active, &job->base.s_fence->finished,
GFP_NOWAIT); if (r) return r;
/* Check if we can use a VMID already assigned to this VM */
list_for_each_entry_reverse((*id), &id_mgr->ids_lru, list) { bool needs_flush = vm->use_cpu_for_update;
/* Check all the prerequisites to using this VMID */ if ((*id)->owner != vm->immediate.fence_context) continue;
if ((*id)->flushed_updates < updates)
needs_flush = true;
if (needs_flush && !adev->vm_manager.concurrent_flush) continue;
/* Good, we can use this VMID. Remember this submission as *useroftheVMID.
*/
r = amdgpu_sync_fence(&(*id)->active,
&job->base.s_fence->finished,
GFP_NOWAIT); if (r) return r;
++id_mgr->reserved_use_count; if (!id_mgr->reserved) { struct amdgpu_vmid *id;
id = list_first_entry(&id_mgr->ids_lru, struct amdgpu_vmid,
list); /* Remove from normal round robin handling */
list_del_init(&id->list);
id_mgr->reserved = id;
}
mutex_lock(&id_mgr->lock); if (!--id_mgr->reserved_use_count) { /* give the reserved ID back to normal round robin */
list_add(&id_mgr->reserved->list, &id_mgr->ids_lru);
id_mgr->reserved = NULL;
}
/* for GC <10, SDMA uses MMHUB so use first_kfd_vmid for both GC and MM */ if (amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(10, 0, 0)) /* manage only VMIDs not used by KFD */
id_mgr->num_ids = adev->vm_manager.first_kfd_vmid; elseif (AMDGPU_IS_MMHUB0(i) ||
AMDGPU_IS_MMHUB1(i))
id_mgr->num_ids = 16; else /* manage only VMIDs not used by KFD */
id_mgr->num_ids = adev->vm_manager.first_kfd_vmid;
/* skip over VMID 0, since it is the system VM */ for (j = 1; j < id_mgr->num_ids; ++j) {
amdgpu_vmid_reset(adev, i, j);
amdgpu_sync_create(&id_mgr->ids[j].active);
list_add_tail(&id_mgr->ids[j].list, &id_mgr->ids_lru);
}
} /* alloc a default reserved vmid to enforce isolation */ for (i = 0; i < (adev->xcp_mgr ? adev->xcp_mgr->num_xcps : 1); i++) { if (adev->enforce_isolation[i] != AMDGPU_ENFORCE_ISOLATION_DISABLE)
amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(i));
}
}
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.