summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 9920a6fc11bf..a7699194edf9 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -899,6 +899,67 @@ static vm_fault_t radeon_ttm_fault(struct vm_fault *vmf)
return ret;
}
+static long radeon_ttm_p2p_map(struct vm_area_struct *vma,
+ struct device *device,
+ unsigned long start,
+ unsigned long end,
+ dma_addr_t *pa,
+ bool write)
+{
+ struct ttm_buffer_object *bo;
+ struct radeon_device *rdev;
+ unsigned long i, npages;
+ struct radeon_bo *rbo;
+ long ret = 0;
+
+ bo = (struct ttm_buffer_object *)vmf->vma->vm_private_data;
+ if (bo == NULL)
+ return -EINVAL;
+ rdev = radeon_get_rdev(bo->bdev);
+ down_read(&rdev->pm.mclk_lock);
+
+ rbo = container_of(bo, struct radeon_bo, bo);
+
+ ret = ttm_bo_reserve(bo, true, true, NULL);
+ if (ret)
+ goto out;
+ ret = ttm_mem_io_lock(man, true);
+ if (ret)
+ goto out_reserve;
+ ret = ttm_mem_io_reserve_vm(bo);
+ if (ret)
+ goto out_io_lock;
+ if (!bo->mem.bus.is_iomem) {
+ /* Only allow to map GPU memory */
+ ret = -EINVAL;
+ goto out;
+ }
+
+ poff = ((start - vma->vm_start) >> PAGE_SHIFT) +
+ vma->vm_pgoff - drm_vma_node_start(&bo->vma_node);
+ npages = (end - start) >> PAGE_SHIFT;
+ for (i = 0; i < npages; ++i, ++poff) {
+ pa[i] = ttm_bo_io_mem_pfn(bo, poff);
+ }
+
+out_io_lock:
+ ttm_mem_io_unlock(man);
+out_reserve:
+ ttm_bo_unreserve(bo);
+out:
+ up_read(&rdev->pm.mclk_lock);
+ return ret ? ret :npages;
+}
+
+static long radeon_p2p_unmap(struct vm_area_struct *vma,
+ struct device *device,
+ unsigned long start,
+ unsigned long end,
+ dma_addr_t *pa)
+{
+ /* Nothing to do here. This is a crude example. */
+}
+
int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *file_priv;
@@ -922,6 +983,8 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
ttm_vm_ops = vma->vm_ops;
radeon_ttm_vm_ops = *ttm_vm_ops;
radeon_ttm_vm_ops.fault = &radeon_ttm_fault;
+ radeon_ttm_vm_ops.p2p_map = radeon_ttm_p2p_map;
+ radeon_ttm_vm_ops.p2p_unmap = radeon_p2p_unmap;
}
vma->vm_ops = &radeon_ttm_vm_ops;
return 0;