]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/radeon: make page table updates async v2
authorChristian König <deathsimple@vodafone.de>
Sat, 11 Aug 2012 13:00:30 +0000 (15:00 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 20 Sep 2012 17:10:40 +0000 (13:10 -0400)
Currently doing the update with the CP.

v2: Rebased on Jeromes bugfix. Make validity comparison
    more human readable.

Signed-off-by: Christian König <deathsimple@vodafone.de>
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_gart.c

index 8bec8113d3a175049a84045b1f9f523244e59577..c803328c0cf94eec704deed8408576ff60f0457b 100644 (file)
@@ -1521,20 +1521,24 @@ void cayman_vm_set_page(struct radeon_device *rdev, struct radeon_vm *vm,
                        unsigned pfn, struct ttm_mem_reg *mem,
                        unsigned npages, uint32_t flags)
 {
-       void __iomem *ptr = (void *)vm->pt;
-       uint64_t addr;
+       struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
+       uint64_t addr, pt = vm->pt_gpu_addr + pfn * 8;
        int i;
 
        addr = flags = cayman_vm_page_flags(rdev, flags);
 
-        for (i = 0; i < npages; ++i, ++pfn) {
-                if (mem) {
-                        addr = radeon_vm_get_addr(rdev, mem, i);
+       radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + npages * 2));
+       radeon_ring_write(ring, pt & 0xffffffff);
+       radeon_ring_write(ring, (pt >> 32) & 0xff);
+       for (i = 0; i < npages; ++i) {
+               if (mem) {
+                       addr = radeon_vm_get_addr(rdev, mem, i);
                        addr = addr & 0xFFFFFFFFFFFFF000ULL;
                        addr |= flags;
-                }
-               writeq(addr, ptr + (pfn * 8));
-        }
+               }
+               radeon_ring_write(ring, addr & 0xffffffff);
+               radeon_ring_write(ring, (addr >> 32) & 0xffffffff);
+       }
 }
 
 void cayman_vm_flush(struct radeon_device *rdev, struct radeon_ib *ib)
index 870db340d37760127e1ebb3314680b4715666789..2423d1b5d385938f2445706abc97ab74198e1b0f 100644 (file)
 #define        PACKET3_SET_CONTEXT_REG_INDIRECT                0x73
 #define        PACKET3_SET_RESOURCE_INDIRECT                   0x74
 #define        PACKET3_SET_APPEND_CNT                          0x75
+#define        PACKET3_ME_WRITE                                0x7A
 
 #endif
 
index ae7409a0f62ba9ce33af486a6ab79dff36e8c939..d48bd3045db6d6f2a56970b5bec054377eaf4aaf 100644 (file)
@@ -1135,6 +1135,8 @@ struct radeon_asic {
        struct {
                int (*init)(struct radeon_device *rdev);
                void (*fini)(struct radeon_device *rdev);
+
+               u32 pt_ring_index;
                void (*set_page)(struct radeon_device *rdev, struct radeon_vm *vm,
                                 unsigned pfn, struct ttm_mem_reg *mem,
                                 unsigned npages, uint32_t flags);
index 6e4e67edf60fd76f4eae03b3faaa50f7d9d05680..2f7adeab049b7bc7bade409db71ed457d47f5e66 100644 (file)
@@ -1375,6 +1375,7 @@ static struct radeon_asic cayman_asic = {
        .vm = {
                .init = &cayman_vm_init,
                .fini = &cayman_vm_fini,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &cayman_vm_set_page,
        },
        .ring = {
@@ -1478,6 +1479,7 @@ static struct radeon_asic trinity_asic = {
        .vm = {
                .init = &cayman_vm_init,
                .fini = &cayman_vm_fini,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &cayman_vm_set_page,
        },
        .ring = {
@@ -1581,6 +1583,7 @@ static struct radeon_asic si_asic = {
        .vm = {
                .init = &si_vm_init,
                .fini = &si_vm_fini,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &cayman_vm_set_page,
        },
        .ring = {
index 0f9a40f84d7a173c4e892f63d890da9b8f44f079..d7bd46bd9067efb8a16caac79d6a9c6cb51dd71b 100644 (file)
@@ -464,15 +464,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
                        continue;
 
                list_for_each_entry(bo_va, &vm->va, vm_list) {
-                       struct ttm_mem_reg *mem = NULL;
-                       if (bo_va->valid)
-                               mem = &bo_va->bo->tbo.mem;
-
                        bo_va->valid = false;
-                       r = radeon_vm_bo_update_pte(rdev, vm, bo_va->bo, mem);
-                       if (r) {
-                               DRM_ERROR("Failed to update pte for vm %d!\n", vm->id);
-                       }
                }
        }
        return 0;
@@ -801,7 +793,6 @@ u64 radeon_vm_get_addr(struct radeon_device *rdev,
        return addr;
 }
 
-/* object have to be reserved & global and local mutex must be locked */
 /**
  * radeon_vm_bo_update_pte - map a bo into the vm page table
  *
@@ -812,15 +803,21 @@ u64 radeon_vm_get_addr(struct radeon_device *rdev,
  *
  * Fill in the page table entries for @bo (cayman+).
  * Returns 0 for success, -EINVAL for failure.
+ *
+ * Object have to be reserved & global and local mutex must be locked!
  */
 int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                            struct radeon_vm *vm,
                            struct radeon_bo *bo,
                            struct ttm_mem_reg *mem)
 {
+       unsigned ridx = rdev->asic->vm.pt_ring_index;
+       struct radeon_ring *ring = &rdev->ring[ridx];
+       struct radeon_semaphore *sem = NULL;
        struct radeon_bo_va *bo_va;
-       unsigned ngpu_pages;
+       unsigned ngpu_pages, ndw;
        uint64_t pfn;
+       int r;
 
        /* nothing to do if vm isn't bound */
        if (vm->sa_bo == NULL)
@@ -832,7 +829,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                return -EINVAL;
        }
 
-       if (bo_va->valid && mem)
+       if ((bo_va->valid && mem) || (!bo_va->valid && mem == NULL))
                return 0;
 
        ngpu_pages = radeon_bo_ngpu_pages(bo);
@@ -846,12 +843,50 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                if (mem->mem_type == TTM_PL_TT) {
                        bo_va->flags |= RADEON_VM_PAGE_SYSTEM;
                }
-       }
-       if (!bo_va->valid) {
-               mem = NULL;
+               if (!bo_va->valid) {
+                       mem = NULL;
+               }
+       } else {
+               bo_va->valid = false;
        }
        pfn = bo_va->soffset / RADEON_GPU_PAGE_SIZE;
-       radeon_asic_vm_set_page(rdev, bo_va->vm, pfn, mem, ngpu_pages, bo_va->flags);
+
+       if (vm->fence && radeon_fence_signaled(vm->fence)) {
+               radeon_fence_unref(&vm->fence);
+       }
+
+       if (vm->fence && vm->fence->ring != ridx) {
+               r = radeon_semaphore_create(rdev, &sem);
+               if (r) {
+                       return r;
+               }
+       }
+
+       /* estimate number of dw needed */
+       ndw = 32;
+       ndw += (ngpu_pages >> 12) * 3;
+       ndw += ngpu_pages * 2;
+
+       r = radeon_ring_lock(rdev, ring, ndw);
+       if (r) {
+               return r;
+       }
+
+       if (sem && radeon_fence_need_sync(vm->fence, ridx)) {
+               radeon_semaphore_sync_rings(rdev, sem, vm->fence->ring, ridx);
+               radeon_fence_note_sync(vm->fence, ridx);
+       }
+
+       radeon_asic_vm_set_page(rdev, vm, pfn, mem, ngpu_pages, bo_va->flags);
+
+       radeon_fence_unref(&vm->fence);
+       r = radeon_fence_emit(rdev, &vm->fence, ridx);
+       if (r) {
+               radeon_ring_unlock_undo(rdev, ring);
+               return r;
+       }
+       radeon_ring_unlock_commit(rdev, ring);
+       radeon_semaphore_free(rdev, &sem, vm->fence);
        radeon_fence_unref(&vm->last_flush);
        return 0;
 }
@@ -875,6 +910,7 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
                     struct radeon_bo *bo)
 {
        struct radeon_bo_va *bo_va;
+       int r;
 
        bo_va = radeon_bo_va(bo, vm);
        if (bo_va == NULL)
@@ -882,14 +918,14 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
 
        mutex_lock(&rdev->vm_manager.lock);
        mutex_lock(&vm->mutex);
-       radeon_vm_free_pt(rdev, vm);
+       r = radeon_vm_bo_update_pte(rdev, vm, bo, NULL);
        mutex_unlock(&rdev->vm_manager.lock);
        list_del(&bo_va->vm_list);
        mutex_unlock(&vm->mutex);
        list_del(&bo_va->bo_list);
 
        kfree(bo_va);
-       return 0;
+       return r;
 }
 
 /**