diff options
author | Jérôme Glisse <jglisse@redhat.com> | 2019-01-29 14:05:22 -0500 |
---|---|---|
committer | Jérôme Glisse <jglisse@redhat.com> | 2019-01-29 14:05:22 -0500 |
commit | 964214dcd4df96f296e2214042e8cfce135ae3d4 (patch) | |
tree | 0d54e45ce56c945e0e4ab9f0362102038b621bab | |
parent | 2f30e120fbd2787b3143cdede37d84858698b0bb (diff) |
radeon: show case how non HMM driver can export p2p for special vmawip-p2p-showcase
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ttm.c | 63 |
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; |