/** * radeon_vce_resume - pin VCE fw memory * * @rdev: radeon_device pointer * */ int radeon_vce_resume(struct radeon_device *rdev) { void *cpu_addr; int r; if (rdev->vce.vcpu_bo == NULL) return -EINVAL; r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); if (r) { dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r); return r; } r = radeon_bo_kmap(rdev->vce.vcpu_bo, &cpu_addr); if (r) { radeon_bo_unreserve(rdev->vce.vcpu_bo); dev_err(rdev->dev, "(%d) VCE map failed\n", r); return r; } memset(cpu_addr, 0, radeon_bo_size(rdev->vce.vcpu_bo)); if (rdev->family < CHIP_BONAIRE) r = vce_v1_0_load_fw(rdev, cpu_addr); else memcpy(cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size); radeon_bo_kunmap(rdev->vce.vcpu_bo); radeon_bo_unreserve(rdev->vce.vcpu_bo); return r; }
/** * radeon_vce_resume - pin VCE fw memory * * @rdev: radeon_device pointer * */ int radeon_vce_resume(struct radeon_device *rdev) { void *cpu_addr; int r; if (rdev->vce.vcpu_bo == NULL) return -EINVAL; r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); if (r) { dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r); return r; } r = radeon_bo_kmap(rdev->vce.vcpu_bo, &cpu_addr); if (r) { radeon_bo_unreserve(rdev->vce.vcpu_bo); dev_err(rdev->dev, "(%d) VCE map failed\n", r); return r; } memcpy(cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size); radeon_bo_kunmap(rdev->vce.vcpu_bo); radeon_bo_unreserve(rdev->vce.vcpu_bo); return 0; }
/** * radeon_ring_init - init driver ring struct. * * @rdev: radeon_device pointer * @ring: radeon_ring structure holding ring information * @ring_size: size of the ring * @rptr_offs: offset of the rptr writeback location in the WB buffer * @rptr_reg: MMIO offset of the rptr register * @wptr_reg: MMIO offset of the wptr register * @ptr_reg_shift: bit offset of the rptr/wptr values * @ptr_reg_mask: bit mask of the rptr/wptr values * @nop: nop packet for this ring * * Initialize the driver information for the selected ring (all asics). * Returns 0 on success, error on failure. */ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) { int r; ring->ring_size = ring_size; ring->rptr_offs = rptr_offs; ring->rptr_reg = rptr_reg; ring->wptr_reg = wptr_reg; ring->ptr_reg_shift = ptr_reg_shift; ring->ptr_reg_mask = ptr_reg_mask; ring->nop = nop; /* Allocate ring buffer */ if (ring->ring_obj == NULL) { r = radeon_bo_create(rdev, ring->ring_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, NULL, &ring->ring_obj); if (r) { dev_err(rdev->dev, "(%d) ring create failed\n", r); return r; } r = radeon_bo_reserve(ring->ring_obj, false); if (unlikely(r != 0)) return r; r = radeon_bo_pin(ring->ring_obj, RADEON_GEM_DOMAIN_GTT, &ring->gpu_addr); if (r) { radeon_bo_unreserve(ring->ring_obj); dev_err(rdev->dev, "(%d) ring pin failed\n", r); return r; } r = radeon_bo_kmap(ring->ring_obj, (void **)&ring->ring); radeon_bo_unreserve(ring->ring_obj); if (r) { dev_err(rdev->dev, "(%d) ring map failed\n", r); return r; } } ring->ptr_mask = (ring->ring_size / 4) - 1; ring->ring_free_dw = ring->ring_size / 4; if (rdev->wb.enabled) { u32 index = RADEON_WB_RING0_NEXT_RPTR + (ring->idx * 4); ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index; ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4]; } if (radeon_debugfs_ring_init(rdev, ring)) { DRM_ERROR("Failed to register debugfs file for rings !\n"); } radeon_ring_lockup_update(ring); return 0; }
void radeon_gem_object_close(struct drm_gem_object *obj, struct drm_file *file_priv) { struct radeon_bo *rbo = gem_to_radeon_bo(obj); struct radeon_device *rdev = rbo->rdev; struct radeon_fpriv *fpriv = file_priv->driver_priv; struct radeon_vm *vm = &fpriv->vm; struct radeon_bo_va *bo_va; int r; if (rdev->family < CHIP_CAYMAN) { return; } r = radeon_bo_reserve(rbo, true); if (r) { dev_err(rdev->dev, "leaking bo va because " "we fail to reserve bo (%d)\n", r); return; } bo_va = radeon_vm_bo_find(vm, rbo); if (bo_va) { if (--bo_va->ref_count == 0) { radeon_vm_bo_rmv(rdev, bo_va); } } radeon_bo_unreserve(rbo); }
/* * Call from drm_gem_handle_create which appear in both new and open ioctl * case. */ int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv) { struct radeon_bo *rbo = gem_to_radeon_bo(obj); struct radeon_device *rdev = rbo->rdev; struct radeon_fpriv *fpriv = file_priv->driver_priv; struct radeon_vm *vm = &fpriv->vm; struct radeon_bo_va *bo_va; int r; if (rdev->family < CHIP_CAYMAN) { return 0; } r = radeon_bo_reserve(rbo, false); if (r) { return r; } bo_va = radeon_vm_bo_find(vm, rbo); if (!bo_va) { bo_va = radeon_vm_bo_add(rdev, vm, rbo); } else { ++bo_va->ref_count; } radeon_bo_unreserve(rbo); return 0; }
/** * radeon_driver_postclose_kms - drm callback for post close * * @dev: drm dev pointer * @file_priv: drm file * * On device post close, tear down vm on cayman+ (all asics). */ void radeon_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { struct radeon_device *rdev = dev->dev_private; /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { struct radeon_fpriv *fpriv = file_priv->driver_priv; struct radeon_vm *vm = &fpriv->vm; int r; if (rdev->accel_working) { r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (!r) { if (vm->ib_bo_va) radeon_vm_bo_rmv(rdev, vm->ib_bo_va); radeon_bo_unreserve(rdev->ring_tmp_bo.bo); } radeon_vm_fini(rdev, vm); } kfree(fpriv); file_priv->driver_priv = NULL; } }
void rv770_pcie_gart_disable(struct radeon_device *rdev) { u32 tmp; int i, r; /* Disable all tables */ for (i = 0; i < 7; i++) WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); /* Setup L2 cache */ WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING | EFFECTIVE_L2_QUEUE_SIZE(7)); WREG32(VM_L2_CNTL2, 0); WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2)); /* Setup TLB control */ tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); if (rdev->gart.table.vram.robj) { r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); if (likely(r == 0)) { radeon_bo_kunmap(rdev->gart.table.vram.robj); radeon_bo_unpin(rdev->gart.table.vram.robj); radeon_bo_unreserve(rdev->gart.table.vram.robj); } } }
int radeon_uvd_suspend(struct radeon_device *rdev) { int r; if (rdev->uvd.vcpu_bo == NULL) return 0; r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); if (!r) { radeon_bo_kunmap(rdev->uvd.vcpu_bo); radeon_bo_unpin(rdev->uvd.vcpu_bo); rdev->uvd.cpu_addr = NULL; if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) { radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); } radeon_bo_unreserve(rdev->uvd.vcpu_bo); if (rdev->uvd.cpu_addr) { radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); } else { rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL; } } return r; }
int radeon_ttm_init(struct radeon_device *rdev) { int r; r = radeon_ttm_global_init(rdev); if (r) { return r; } /* No others user of address space so set it to 0 */ r = ttm_bo_device_init(&rdev->mman.bdev, rdev->mman.bo_global_ref.ref.object, &radeon_bo_driver, DRM_FILE_PAGE_OFFSET, rdev->need_dma32); if (r) { DRM_ERROR("failed initializing buffer object driver(%d).\n", r); return r; } rdev->mman.initialized = true; r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, rdev->mc.real_vram_size >> PAGE_SHIFT); if (r) { DRM_ERROR("Failed initializing VRAM heap.\n"); return r; } r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, &rdev->stollen_vga_memory); if (r) { return r; } r = radeon_bo_reserve(rdev->stollen_vga_memory, false); if (r) return r; r = radeon_bo_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL); radeon_bo_unreserve(rdev->stollen_vga_memory); if (r) { radeon_bo_unref(&rdev->stollen_vga_memory); return r; } DRM_INFO("radeon: %uM of VRAM memory ready\n", (unsigned)rdev->mc.real_vram_size / (1024 * 1024)); r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, rdev->mc.gtt_size >> PAGE_SHIFT); if (r) { DRM_ERROR("Failed initializing GTT heap.\n"); return r; } DRM_INFO("radeon: %uM of GTT memory ready.\n", (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; } r = radeon_ttm_debugfs_init(rdev); if (r) { DRM_ERROR("Failed to init debugfs\n"); return r; } return 0; }
/** * radeon_driver_open_kms - drm callback for open * * @dev: drm dev pointer * @file_priv: drm file * * On device open, init vm on cayman+ (all asics). * Returns 0 on success, error on failure. */ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) { struct radeon_device *rdev = dev->dev_private; int r; file_priv->driver_priv = NULL; r = pm_runtime_get_sync(dev->dev); if (r < 0) return r; /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN) { struct radeon_fpriv *fpriv; struct radeon_vm *vm; int r; fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); if (unlikely(!fpriv)) { return -ENOMEM; } if (rdev->accel_working) { vm = &fpriv->vm; r = radeon_vm_init(rdev, vm); if (r) { kfree(fpriv); return r; } r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (r) { radeon_vm_fini(rdev, vm); kfree(fpriv); return r; } /* map the ib pool buffer read only into * virtual address space */ vm->ib_bo_va = radeon_vm_bo_add(rdev, vm, rdev->ring_tmp_bo.bo); r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va, RADEON_VA_IB_OFFSET, RADEON_VM_PAGE_READABLE | RADEON_VM_PAGE_SNOOPED); radeon_bo_unreserve(rdev->ring_tmp_bo.bo); if (r) { radeon_vm_fini(rdev, vm); kfree(fpriv); return r; } } file_priv->driver_priv = fpriv; } pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); return 0; }
/** * radeon_driver_postclose_kms - drm callback for post close * * @dev: drm dev pointer * @file_priv: drm file * * On device post close, tear down vm on cayman+ (all asics). */ void radeon_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { struct radeon_device *rdev = dev->dev_private; /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { struct radeon_fpriv *fpriv = file_priv->driver_priv; struct radeon_bo_va *bo_va; int r; r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (!r) { bo_va = radeon_vm_bo_find(&fpriv->vm, rdev->ring_tmp_bo.bo); if (bo_va) radeon_vm_bo_rmv(rdev, bo_va); radeon_bo_unreserve(rdev->ring_tmp_bo.bo); } radeon_vm_fini(rdev, &fpriv->vm); kfree(fpriv); file_priv->driver_priv = NULL; } }
int radeon_gem_prime_pin(struct drm_gem_object *obj) { struct radeon_bo *bo = gem_to_radeon_bo(obj); int ret = 0; ret = radeon_bo_reserve(bo, false); if (unlikely(ret != 0)) return ret; /* pin buffer into GTT */ ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL); if (ret) { radeon_bo_unreserve(bo); return ret; } radeon_bo_unreserve(bo); return 0; }
void radeon_gem_object_unpin(struct drm_gem_object *obj) { struct radeon_bo *robj = gem_to_radeon_bo(obj); int r; r = radeon_bo_reserve(robj, false); if (likely(r == 0)) { radeon_bo_unpin(robj); radeon_bo_unreserve(robj); } }
void radeon_gem_object_unpin(struct drm_gem_object *obj) { struct radeon_bo *robj = obj->driver_private; int r; r = radeon_bo_reserve(robj, false); if (likely(r == 0)) { radeon_bo_unpin(robj); radeon_bo_unreserve(robj); } }
struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) { struct radeon_bo *bo = gem_to_radeon_bo(obj); int ret = 0; ret = radeon_bo_reserve(bo, false); if (unlikely(ret != 0)) return ERR_PTR(ret); /* pin buffer into GTT */ ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL); if (ret) { radeon_bo_unreserve(bo); return ERR_PTR(ret); } radeon_bo_unreserve(bo); return dma_buf_export(bo, &radeon_dmabuf_ops, obj->size, flags); }
void radeon_gem_prime_unpin(struct drm_gem_object *obj) { struct radeon_bo *bo = gem_to_radeon_bo(obj); int ret = 0; ret = radeon_bo_reserve(bo, false); if (unlikely(ret != 0)) return; radeon_bo_unpin(bo); radeon_bo_unreserve(bo); }
int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, uint64_t *gpu_addr) { struct radeon_bo *robj = obj->driver_private; int r; r = radeon_bo_reserve(robj, false); if (unlikely(r != 0)) return r; r = radeon_bo_pin(robj, pin_domain, gpu_addr); radeon_bo_unreserve(robj); return r; }
static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) { struct radeon_bo *rbo = gem_to_radeon_bo(gobj); int ret; ret = radeon_bo_reserve(rbo, false); if (likely(ret == 0)) { radeon_bo_kunmap(rbo); radeon_bo_unpin(rbo); radeon_bo_unreserve(rbo); } drm_gem_object_unreference_unlocked(gobj); }
int radeon_uvd_resume(struct radeon_device *rdev) { int r; if (rdev->uvd.vcpu_bo == NULL) return -EINVAL; r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); if (r) { radeon_bo_unref(&rdev->uvd.vcpu_bo); dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r); return r; } /* Have been pin in cpu unmap unpin */ radeon_bo_kunmap(rdev->uvd.vcpu_bo); radeon_bo_unpin(rdev->uvd.vcpu_bo); r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, &rdev->uvd.gpu_addr); if (r) { radeon_bo_unreserve(rdev->uvd.vcpu_bo); radeon_bo_unref(&rdev->uvd.vcpu_bo); dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r); return r; } r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); if (r) { dev_err(rdev->dev, "(%d) UVD map failed\n", r); return r; } radeon_bo_unreserve(rdev->uvd.vcpu_bo); return 0; }
void radeon_uvd_fini(struct radeon_device *rdev) { int r; if (rdev->uvd.vcpu_bo == NULL) return; r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); if (!r) { radeon_bo_kunmap(rdev->uvd.vcpu_bo); radeon_bo_unpin(rdev->uvd.vcpu_bo); radeon_bo_unreserve(rdev->uvd.vcpu_bo); } radeon_bo_unref(&rdev->uvd.vcpu_bo); release_firmware(rdev->uvd_fw); }
void radeon_uvd_fini(struct radeon_device *rdev) { int r; if (rdev->uvd.vcpu_bo == NULL) return; r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); if (!r) { radeon_bo_kunmap(rdev->uvd.vcpu_bo); radeon_bo_unpin(rdev->uvd.vcpu_bo); radeon_bo_unreserve(rdev->uvd.vcpu_bo); } radeon_bo_unref(&rdev->uvd.vcpu_bo); radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]); release_firmware(rdev->uvd_fw); }
int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct drm_radeon_gem_get_tiling *args = data; struct drm_gem_object *gobj; struct radeon_bo *rbo; int r = 0; DRM_DEBUG("\n"); gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) return -ENOENT; rbo = gem_to_radeon_bo(gobj); r = radeon_bo_reserve(rbo, false); if (unlikely(r != 0)) goto out; radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch); radeon_bo_unreserve(rbo); out: drm_gem_object_unreference_unlocked(gobj); return r; }
void radeon_ttm_fini(struct radeon_device *rdev) { int r; if (!rdev->mman.initialized) return; if (rdev->stollen_vga_memory) { r = radeon_bo_reserve(rdev->stollen_vga_memory, false); if (r == 0) { radeon_bo_unpin(rdev->stollen_vga_memory); radeon_bo_unreserve(rdev->stollen_vga_memory); } radeon_bo_unref(&rdev->stollen_vga_memory); } ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM); ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT); ttm_bo_device_release(&rdev->mman.bdev); radeon_gart_fini(rdev); radeon_ttm_global_fini(rdev); rdev->mman.initialized = false; DRM_INFO("radeon: ttm finalized\n"); }
/** * radeon_ring_fini - tear down the driver ring struct. * * @rdev: radeon_device pointer * @ring: radeon_ring structure holding ring information * * Tear down the driver information for the selected ring (all asics). */ void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) { int r; struct radeon_bo *ring_obj; mutex_lock(&rdev->ring_lock); ring_obj = ring->ring_obj; ring->ready = false; ring->ring = NULL; ring->ring_obj = NULL; mutex_unlock(&rdev->ring_lock); if (ring_obj) { r = radeon_bo_reserve(ring_obj, false); if (likely(r == 0)) { radeon_bo_kunmap(ring_obj); radeon_bo_unpin(ring_obj); radeon_bo_unreserve(ring_obj); } radeon_bo_unref(&ring_obj); } }
/** * radeon_driver_postclose_kms - drm callback for post close * * @dev: drm dev pointer * @file_priv: drm file * * On device close, tear down hyperz and cmask filps on r1xx-r5xx * (all asics). And tear down vm on cayman+ (all asics). */ void radeon_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { struct radeon_device *rdev = dev->dev_private; pm_runtime_get_sync(dev->dev); mutex_lock(&rdev->gem.mutex); if (rdev->hyperz_filp == file_priv) rdev->hyperz_filp = NULL; if (rdev->cmask_filp == file_priv) rdev->cmask_filp = NULL; mutex_unlock(&rdev->gem.mutex); radeon_uvd_free_handles(rdev, file_priv); radeon_vce_free_handles(rdev, file_priv); /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { struct radeon_fpriv *fpriv = file_priv->driver_priv; struct radeon_vm *vm = &fpriv->vm; int r; if (rdev->accel_working) { r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (!r) { if (vm->ib_bo_va) radeon_vm_bo_rmv(rdev, vm->ib_bo_va); radeon_bo_unreserve(rdev->ring_tmp_bo.bo); } radeon_vm_fini(rdev, vm); } kfree(fpriv); file_priv->driver_priv = NULL; } pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); }
static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, unsigned sdomain, unsigned ddomain) { struct radeon_bo *dobj = NULL; struct radeon_bo *sobj = NULL; uint64_t saddr, daddr; int r, n; int time; n = RADEON_BENCHMARK_ITERATIONS; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, NULL, &sobj); if (r) { goto out_cleanup; } r = radeon_bo_reserve(sobj, false); if (unlikely(r != 0)) goto out_cleanup; r = radeon_bo_pin(sobj, sdomain, &saddr); radeon_bo_unreserve(sobj); if (r) { goto out_cleanup; } r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, NULL, &dobj); if (r) { goto out_cleanup; } r = radeon_bo_reserve(dobj, false); if (unlikely(r != 0)) goto out_cleanup; r = radeon_bo_pin(dobj, ddomain, &daddr); radeon_bo_unreserve(dobj); if (r) { goto out_cleanup; } /* r100 doesn't have dma engine so skip the test */ /* also, VRAM-to-VRAM test doesn't make much sense for DMA */ /* skip it as well if domains are the same */ if ((rdev->asic->copy.dma) && (sdomain != ddomain)) { time = radeon_benchmark_do_move(rdev, size, saddr, daddr, RADEON_BENCHMARK_COPY_DMA, n); if (time < 0) goto out_cleanup; if (time > 0) radeon_benchmark_log_results(n, size, time, sdomain, ddomain, "dma"); } time = radeon_benchmark_do_move(rdev, size, saddr, daddr, RADEON_BENCHMARK_COPY_BLIT, n); if (time < 0) goto out_cleanup; if (time > 0) radeon_benchmark_log_results(n, size, time, sdomain, ddomain, "blit"); out_cleanup: if (sobj) { r = radeon_bo_reserve(sobj, false); if (likely(r == 0)) { radeon_bo_unpin(sobj); radeon_bo_unreserve(sobj); } radeon_bo_unref(&sobj); } if (dobj) { r = radeon_bo_reserve(dobj, false); if (likely(r == 0)) { radeon_bo_unpin(dobj); radeon_bo_unreserve(dobj); } radeon_bo_unref(&dobj); } if (r) { DRM_ERROR("Error while benchmarking BO move.\n"); } }
int radeon_uvd_init(struct radeon_device *rdev) { unsigned long bo_size; const char *fw_name; int i, r; INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler); switch (rdev->family) { case CHIP_RV710: case CHIP_RV730: case CHIP_RV740: fw_name = FIRMWARE_RV710; break; case CHIP_CYPRESS: case CHIP_HEMLOCK: case CHIP_JUNIPER: case CHIP_REDWOOD: case CHIP_CEDAR: fw_name = FIRMWARE_CYPRESS; break; case CHIP_SUMO: case CHIP_SUMO2: case CHIP_PALM: case CHIP_CAYMAN: case CHIP_BARTS: case CHIP_TURKS: case CHIP_CAICOS: fw_name = FIRMWARE_SUMO; break; case CHIP_TAHITI: case CHIP_VERDE: case CHIP_PITCAIRN: case CHIP_ARUBA: fw_name = FIRMWARE_TAHITI; break; case CHIP_BONAIRE: case CHIP_KABINI: case CHIP_KAVERI: fw_name = FIRMWARE_BONAIRE; break; default: return -EINVAL; } r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev); if (r) { dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n", fw_name); return r; } bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) + RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE; r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo); if (r) { dev_err(rdev->dev, "(%d) failed to allocate UVD bo\n", r); return r; } r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); if (r) { radeon_bo_unref(&rdev->uvd.vcpu_bo); dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r); return r; } r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, &rdev->uvd.gpu_addr); if (r) { radeon_bo_unreserve(rdev->uvd.vcpu_bo); radeon_bo_unref(&rdev->uvd.vcpu_bo); dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r); return r; } r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); if (r) { dev_err(rdev->dev, "(%d) UVD map failed\n", r); return r; } radeon_bo_unreserve(rdev->uvd.vcpu_bo); for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { atomic_set(&rdev->uvd.handles[i], 0); rdev->uvd.filp[i] = NULL; } return 0; }
/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ void radeon_test_moves(struct radeon_device *rdev) { struct radeon_bo *vram_obj = NULL; struct radeon_bo **gtt_obj = NULL; struct radeon_fence *fence = NULL; uint64_t gtt_addr, vram_addr; unsigned i, n, size; int r; size = 1024 * 1024; /* Number of tests = * (Total GTT - IB pool - writeback page - ring buffers) / test size */ n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024; for (i = 0; i < RADEON_NUM_RINGS; ++i) n -= rdev->ring[i].ring_size; if (rdev->wb.wb_obj) n -= RADEON_GPU_PAGE_SIZE; if (rdev->ih.ring_obj) n -= rdev->ih.ring_size; n /= size; gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) { DRM_ERROR("Failed to allocate %d pointers\n", n); r = 1; goto out_cleanup; } r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, &vram_obj); if (r) { DRM_ERROR("Failed to create VRAM object\n"); goto out_cleanup; } r = radeon_bo_reserve(vram_obj, false); if (unlikely(r != 0)) goto out_cleanup; r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); if (r) { DRM_ERROR("Failed to pin VRAM object\n"); goto out_cleanup; } for (i = 0; i < n; i++) { void *gtt_map, *vram_map; void **gtt_start, **gtt_end; void **vram_start, **vram_end; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, gtt_obj + i); if (r) { DRM_ERROR("Failed to create GTT object %d\n", i); goto out_cleanup; } r = radeon_bo_reserve(gtt_obj[i], false); if (unlikely(r != 0)) goto out_cleanup; r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); if (r) { DRM_ERROR("Failed to pin GTT object %d\n", i); goto out_cleanup; } r = radeon_bo_kmap(gtt_obj[i], >t_map); if (r) { DRM_ERROR("Failed to map GTT object %d\n", i); goto out_cleanup; } for (gtt_start = gtt_map, gtt_end = gtt_map + size; gtt_start < gtt_end; gtt_start++) *gtt_start = gtt_start; radeon_bo_kunmap(gtt_obj[i]); r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); if (r) { DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i); goto out_cleanup; } r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, fence); if (r) { DRM_ERROR("Failed GTT->VRAM copy %d\n", i); goto out_cleanup; } r = radeon_fence_wait(fence, false); if (r) { DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); goto out_cleanup; } radeon_fence_unref(&fence); r = radeon_bo_kmap(vram_obj, &vram_map); if (r) { DRM_ERROR("Failed to map VRAM object after copy %d\n", i); goto out_cleanup; } for (gtt_start = gtt_map, gtt_end = gtt_map + size, vram_start = vram_map, vram_end = vram_map + size; vram_start < vram_end; gtt_start++, vram_start++) { if (*vram_start != gtt_start) { DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " "expected 0x%p (GTT/VRAM offset " "0x%16llx/0x%16llx)\n", i, *vram_start, gtt_start, (unsigned long long) (gtt_addr - rdev->mc.gtt_start + (void*)gtt_start - gtt_map), (unsigned long long) (vram_addr - rdev->mc.vram_start + (void*)gtt_start - gtt_map)); radeon_bo_kunmap(vram_obj); goto out_cleanup; } *vram_start = vram_start; } radeon_bo_kunmap(vram_obj); r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); if (r) { DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i); goto out_cleanup; } r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, fence); if (r) { DRM_ERROR("Failed VRAM->GTT copy %d\n", i); goto out_cleanup; } r = radeon_fence_wait(fence, false); if (r) { DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); goto out_cleanup; } radeon_fence_unref(&fence); r = radeon_bo_kmap(gtt_obj[i], >t_map); if (r) { DRM_ERROR("Failed to map GTT object after copy %d\n", i); goto out_cleanup; } for (gtt_start = gtt_map, gtt_end = gtt_map + size, vram_start = vram_map, vram_end = vram_map + size; gtt_start < gtt_end; gtt_start++, vram_start++) { if (*gtt_start != vram_start) { DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " "expected 0x%p (VRAM/GTT offset " "0x%16llx/0x%16llx)\n", i, *gtt_start, vram_start, (unsigned long long) (vram_addr - rdev->mc.vram_start + (void*)vram_start - vram_map), (unsigned long long) (gtt_addr - rdev->mc.gtt_start + (void*)vram_start - vram_map)); radeon_bo_kunmap(gtt_obj[i]); goto out_cleanup; } } radeon_bo_kunmap(gtt_obj[i]); DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", gtt_addr - rdev->mc.gtt_start); } out_cleanup: if (vram_obj) { if (radeon_bo_is_reserved(vram_obj)) { radeon_bo_unpin(vram_obj); radeon_bo_unreserve(vram_obj); } radeon_bo_unref(&vram_obj); } if (gtt_obj) { for (i = 0; i < n; i++) { if (gtt_obj[i]) { if (radeon_bo_is_reserved(gtt_obj[i])) { radeon_bo_unpin(gtt_obj[i]); radeon_bo_unreserve(gtt_obj[i]); } radeon_bo_unref(>t_obj[i]); } } kfree(gtt_obj); } if (fence) { radeon_fence_unref(&fence); } if (r) { printk(KERN_WARNING "Error while testing BO move.\n"); } }
/** * radeon_vce_init - allocate memory, load vce firmware * * @rdev: radeon_device pointer * * First step to get VCE online, allocate memory and load the firmware */ int radeon_vce_init(struct radeon_device *rdev) { static const char *fw_version = "[ATI LIB=VCEFW,"; static const char *fb_version = "[ATI LIB=VCEFWSTATS,"; unsigned long size; const char *fw_name, *c; uint8_t start, mid, end; int i, r; INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler); switch (rdev->family) { case CHIP_BONAIRE: case CHIP_KAVERI: case CHIP_KABINI: fw_name = FIRMWARE_BONAIRE; break; default: return -EINVAL; } r = request_firmware(&rdev->vce_fw, fw_name, rdev->dev); if (r) { dev_err(rdev->dev, "radeon_vce: Can't load firmware \"%s\"\n", fw_name); return r; } /* search for firmware version */ size = rdev->vce_fw->size - strlen(fw_version) - 9; c = rdev->vce_fw->data; for (;size > 0; --size, ++c) if (strncmp(c, fw_version, strlen(fw_version)) == 0) break; if (size == 0) return -EINVAL; c += strlen(fw_version); if (sscanf(c, "%2hhd.%2hhd.%2hhd]", &start, &mid, &end) != 3) return -EINVAL; /* search for feedback version */ size = rdev->vce_fw->size - strlen(fb_version) - 3; c = rdev->vce_fw->data; for (;size > 0; --size, ++c) if (strncmp(c, fb_version, strlen(fb_version)) == 0) break; if (size == 0) return -EINVAL; c += strlen(fb_version); if (sscanf(c, "%2u]", &rdev->vce.fb_version) != 1) return -EINVAL; DRM_INFO("Found VCE firmware/feedback version %hhd.%hhd.%hhd / %d!\n", start, mid, end, rdev->vce.fb_version); rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8); /* we can only work with this fw version for now */ if (rdev->vce.fw_version != ((40 << 24) | (2 << 16) | (2 << 8))) return -EINVAL; /* allocate firmware, stack and heap BO */ size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) + RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo); if (r) { dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r); return r; } r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); if (r) { radeon_bo_unref(&rdev->vce.vcpu_bo); dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r); return r; } r = radeon_bo_pin(rdev->vce.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, &rdev->vce.gpu_addr); radeon_bo_unreserve(rdev->vce.vcpu_bo); if (r) { radeon_bo_unref(&rdev->vce.vcpu_bo); dev_err(rdev->dev, "(%d) VCE bo pin failed\n", r); return r; } for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { atomic_set(&rdev->vce.handles[i], 0); rdev->vce.filp[i] = NULL; } return 0; }
/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) { struct radeon_bo *vram_obj = NULL; struct radeon_bo **gtt_obj = NULL; uint64_t gtt_addr, vram_addr; unsigned n, size; int i, r, ring; switch (flag) { case RADEON_TEST_COPY_DMA: ring = radeon_copy_dma_ring_index(rdev); break; case RADEON_TEST_COPY_BLIT: ring = radeon_copy_blit_ring_index(rdev); break; default: DRM_ERROR("Unknown copy method\n"); return; } size = 1024 * 1024; /* Number of tests = * (Total GTT - IB pool - writeback page - ring buffers) / test size */ n = rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024; for (i = 0; i < RADEON_NUM_RINGS; ++i) n -= rdev->ring[i].ring_size; if (rdev->wb.wb_obj) n -= RADEON_GPU_PAGE_SIZE; if (rdev->ih.ring_obj) n -= rdev->ih.ring_size; n /= size; gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) { DRM_ERROR("Failed to allocate %d pointers\n", n); r = 1; goto out_cleanup; } r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, NULL, &vram_obj); if (r) { DRM_ERROR("Failed to create VRAM object\n"); goto out_cleanup; } r = radeon_bo_reserve(vram_obj, false); if (unlikely(r != 0)) goto out_unref; r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr); if (r) { DRM_ERROR("Failed to pin VRAM object\n"); goto out_unres; } for (i = 0; i < n; i++) { void *gtt_map, *vram_map; void **gtt_start, **gtt_end; void **vram_start, **vram_end; struct radeon_fence *fence = NULL; r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, NULL, gtt_obj + i); if (r) { DRM_ERROR("Failed to create GTT object %d\n", i); goto out_lclean; } r = radeon_bo_reserve(gtt_obj[i], false); if (unlikely(r != 0)) goto out_lclean_unref; r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, >t_addr); if (r) { DRM_ERROR("Failed to pin GTT object %d\n", i); goto out_lclean_unres; } r = radeon_bo_kmap(gtt_obj[i], >t_map); if (r) { DRM_ERROR("Failed to map GTT object %d\n", i); goto out_lclean_unpin; } for (gtt_start = gtt_map, gtt_end = gtt_map + size; gtt_start < gtt_end; gtt_start++) *gtt_start = gtt_start; radeon_bo_kunmap(gtt_obj[i]); if (ring == R600_RING_TYPE_DMA_INDEX) r = radeon_copy_dma(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); else r = radeon_copy_blit(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); if (r) { DRM_ERROR("Failed GTT->VRAM copy %d\n", i); goto out_lclean_unpin; } r = radeon_fence_wait(fence, false); if (r) { DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i); goto out_lclean_unpin; } radeon_fence_unref(&fence); r = radeon_bo_kmap(vram_obj, &vram_map); if (r) { DRM_ERROR("Failed to map VRAM object after copy %d\n", i); goto out_lclean_unpin; } for (gtt_start = gtt_map, gtt_end = gtt_map + size, vram_start = vram_map, vram_end = vram_map + size; vram_start < vram_end; gtt_start++, vram_start++) { if (*vram_start != gtt_start) { DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, " "expected 0x%p (GTT/VRAM offset " "0x%16llx/0x%16llx)\n", i, *vram_start, gtt_start, (unsigned long long) (gtt_addr - rdev->mc.gtt_start + (void*)gtt_start - gtt_map), (unsigned long long) (vram_addr - rdev->mc.vram_start + (void*)gtt_start - gtt_map)); radeon_bo_kunmap(vram_obj); goto out_lclean_unpin; } *vram_start = vram_start; } radeon_bo_kunmap(vram_obj); if (ring == R600_RING_TYPE_DMA_INDEX) r = radeon_copy_dma(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); else r = radeon_copy_blit(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); if (r) { DRM_ERROR("Failed VRAM->GTT copy %d\n", i); goto out_lclean_unpin; } r = radeon_fence_wait(fence, false); if (r) { DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i); goto out_lclean_unpin; } radeon_fence_unref(&fence); r = radeon_bo_kmap(gtt_obj[i], >t_map); if (r) { DRM_ERROR("Failed to map GTT object after copy %d\n", i); goto out_lclean_unpin; } for (gtt_start = gtt_map, gtt_end = gtt_map + size, vram_start = vram_map, vram_end = vram_map + size; gtt_start < gtt_end; gtt_start++, vram_start++) { if (*gtt_start != vram_start) { DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, " "expected 0x%p (VRAM/GTT offset " "0x%16llx/0x%16llx)\n", i, *gtt_start, vram_start, (unsigned long long) (vram_addr - rdev->mc.vram_start + (void*)vram_start - vram_map), (unsigned long long) (gtt_addr - rdev->mc.gtt_start + (void*)vram_start - vram_map)); radeon_bo_kunmap(gtt_obj[i]); goto out_lclean_unpin; } } radeon_bo_kunmap(gtt_obj[i]); DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n", gtt_addr - rdev->mc.gtt_start); continue; out_lclean_unpin: radeon_bo_unpin(gtt_obj[i]); out_lclean_unres: radeon_bo_unreserve(gtt_obj[i]); out_lclean_unref: radeon_bo_unref(>t_obj[i]); out_lclean: for (--i; i >= 0; --i) { radeon_bo_unpin(gtt_obj[i]); radeon_bo_unreserve(gtt_obj[i]); radeon_bo_unref(>t_obj[i]); } if (fence) radeon_fence_unref(&fence); break; } radeon_bo_unpin(vram_obj); out_unres: radeon_bo_unreserve(vram_obj); out_unref: radeon_bo_unref(&vram_obj); out_cleanup: kfree(gtt_obj); if (r) { printk(KERN_WARNING "Error while testing BO move.\n"); } }