struct amdgpu_bo_va_mapping *
amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
uint64_t addr, struct amdgpu_bo **bo);
+int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser);
#include "amdgpu_object.h"
#endif
}
}
- if (p->uf_entry.robj)
- p->job->uf_addr += amdgpu_bo_gpu_offset(p->uf_entry.robj);
+ if (!r && p->uf_entry.robj) {
+ struct amdgpu_bo *uf = p->uf_entry.robj;
+
+ r = amdgpu_ttm_bind(uf->tbo.ttm, &uf->tbo.mem);
+ p->job->uf_addr += amdgpu_bo_gpu_offset(uf);
+ }
error_validate:
if (r) {
return NULL;
}
+
+/**
+ * amdgpu_cs_sysvm_access_required - make BOs accessible by the system VM
+ *
+ * @parser: command submission parser context
+ *
+ * Helper for UVD/VCE VM emulation, make sure BOs are accessible by the system VM.
+ */
+int amdgpu_cs_sysvm_access_required(struct amdgpu_cs_parser *parser)
+{
+ unsigned i;
+ int r;
+
+ if (!parser->bo_list)
+ return 0;
+
+ for (i = 0; i < parser->bo_list->num_entries; i++) {
+ struct amdgpu_bo *bo = parser->bo_list->array[i].robj;
+
+ r = amdgpu_ttm_bind(bo->tbo.ttm, &bo->tbo.mem);
+ if (unlikely(r))
+ return r;
+ }
+
+ return 0;
+}
dev_err(bo->adev->dev, "%p pin failed\n", bo);
goto error;
}
+ r = amdgpu_ttm_bind(bo->tbo.ttm, &bo->tbo.mem);
+ if (unlikely(r)) {
+ dev_err(bo->adev->dev, "%p bind failed\n", bo);
+ goto error;
+ }
bo->pin_count = 1;
if (gpu_addr != NULL)
u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
{
WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM);
+ WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_TT &&
+ !amdgpu_ttm_is_bound(bo->tbo.ttm));
WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) &&
!bo->pin_count);
new_start = new_mem->start << PAGE_SHIFT;
switch (old_mem->mem_type) {
- case TTM_PL_VRAM:
case TTM_PL_TT:
+ r = amdgpu_ttm_bind(bo->ttm, old_mem);
+ if (r)
+ return r;
+
+ case TTM_PL_VRAM:
old_start += bo->bdev->man[old_mem->mem_type].gpu_offset;
break;
default:
return -EINVAL;
}
switch (new_mem->mem_type) {
- case TTM_PL_VRAM:
case TTM_PL_TT:
+ r = amdgpu_ttm_bind(bo->ttm, new_mem);
+ if (r)
+ return r;
+
+ case TTM_PL_VRAM:
new_start += bo->bdev->man[new_mem->mem_type].gpu_offset;
break;
default:
struct ttm_mem_reg *bo_mem)
{
struct amdgpu_ttm_tt *gtt = (void*)ttm;
- uint32_t flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem);
int r;
if (gtt->userptr) {
bo_mem->mem_type == AMDGPU_PL_OA)
return -EINVAL;
+ return 0;
+}
+
+bool amdgpu_ttm_is_bound(struct ttm_tt *ttm)
+{
+ struct amdgpu_ttm_tt *gtt = (void *)ttm;
+
+ return gtt && !list_empty(>t->list);
+}
+
+int amdgpu_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
+{
+ struct amdgpu_ttm_tt *gtt = (void *)ttm;
+ uint32_t flags;
+ int r;
+
+ if (!ttm || amdgpu_ttm_is_bound(ttm))
+ return 0;
+
+ flags = amdgpu_ttm_tt_pte_flags(gtt->adev, ttm, bo_mem);
r = amdgpu_gart_bind(gtt->adev, gtt->offset, ttm->num_pages,
ttm->pages, gtt->ttm.dma_address, flags);
struct fence **fence);
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
+bool amdgpu_ttm_is_bound(struct ttm_tt *ttm);
+int amdgpu_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem);
+
#endif
return -EINVAL;
}
+ r = amdgpu_cs_sysvm_access_required(parser);
+ if (r)
+ return r;
+
ctx.parser = parser;
ctx.buf_sizes = buf_sizes;
ctx.ib_idx = ib_idx;
uint32_t allocated = 0;
uint32_t tmp, handle = 0;
uint32_t *size = &tmp;
- int i, r = 0, idx = 0;
+ int i, r, idx = 0;
+
+ r = amdgpu_cs_sysvm_access_required(p);
+ if (r)
+ return r;
while (idx < ib->length_dw) {
uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
}
flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem);
- gtt_flags = (adev == bo_va->bo->adev) ? flags : 0;
+ gtt_flags = (amdgpu_ttm_is_bound(bo_va->bo->tbo.ttm) &&
+ adev == bo_va->bo->adev) ? flags : 0;
spin_lock(&vm->status_lock);
if (!list_empty(&bo_va->vm_status))