drm/amdgpu: Add gem_prime_mmap support
Subsystems (2)
PATCH 6/6 drm/amdgpu: Add gem_prime_mmap support
--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 95 ++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +3 -0
@@ -395,11 +395,14 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,struct dma_buf *amdgpu_gem_prime_export (struct drm_device *dev,struct drm_gem_object *gobj,int flags); +struct drm_gem_object *amdgpu_gem_prime_import (struct drm_device *dev, +struct dma_buf *dma_buf);int amdgpu_gem_prime_pin (struct drm_gem_object *obj);void amdgpu_gem_prime_unpin (struct drm_gem_object *obj);struct reservation_object *amdgpu_gem_prime_res_obj (struct drm_gem_object *);void *amdgpu_gem_prime_vmap (struct drm_gem_object *obj);void amdgpu_gem_prime_vunmap (struct drm_gem_object *obj,void *vaddr); +int amdgpu_gem_prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma);int amdgpu_gem_debugfs_init (struct amdgpu_device *adev);/* sub-allocation manager, it has to be protected by another lock.
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +2 -1
@@ -835,7 +835,7 @@ static struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = amdgpu_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, + .gem_prime_import = amdgpu_gem_prime_import, .gem_prime_pin = amdgpu_gem_prime_pin, .gem_prime_unpin = amdgpu_gem_prime_unpin, .gem_prime_res_obj = amdgpu_gem_prime_res_obj,
@@ -843,6 +843,7 @@ static struct drm_driver kms_driver = { .gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table, .gem_prime_vmap = amdgpu_gem_prime_vmap, .gem_prime_vunmap = amdgpu_gem_prime_vunmap, + .gem_prime_mmap = amdgpu_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC,
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +94 -1
114 lines not on this page · raw message
Signature · 6 lines
2.7.4 _______________________________________________ amd-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/amd-gfx
A message that is not in the archive (sent off-list or not yet received): 1504735644-31225-1-git-send-email-Samuel.Li-5C7GfCeVMHo@public.gmane.org
Am 07.09.2017 um 00:07 schrieb Samuel Li:
Quoted 101 lines
Signed-off-by Samuel Li <[email protected]>--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 95 ++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 2 deletions(-)drivers/gpu/drm/amd/amdgpu/amdgpu.h +3
-0@@ -395,11 +395,14 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,struct dma_buf *amdgpu_gem_prime_export (struct drm_device *dev,struct drm_gem_object *gobj,int flags); +struct drm_gem_object *amdgpu_gem_prime_import (struct drm_device *dev, +struct dma_buf *dma_buf);int amdgpu_gem_prime_pin (struct drm_gem_object *obj);void amdgpu_gem_prime_unpin (struct drm_gem_object *obj);struct reservation_object *amdgpu_gem_prime_res_obj (struct drm_gem_object *);void *amdgpu_gem_prime_vmap (struct drm_gem_object *obj);void amdgpu_gem_prime_vunmap (struct drm_gem_object *obj,void *vaddr); +int amdgpu_gem_prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma);int amdgpu_gem_debugfs_init (struct amdgpu_device *adev);/* sub-allocation manager, it has to be protected by another lock. drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +2
-1@@ -835,7 +835,7 @@ static struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = amdgpu_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, + .gem_prime_import = amdgpu_gem_prime_import, .gem_prime_pin = amdgpu_gem_prime_pin, .gem_prime_unpin = amdgpu_gem_prime_unpin, .gem_prime_res_obj = amdgpu_gem_prime_res_obj,@@ -843,6 +843,7 @@ static struct drm_driver kms_driver = { .gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table, .gem_prime_vmap = amdgpu_gem_prime_vmap, .gem_prime_vunmap = amdgpu_gem_prime_vunmap, + .gem_prime_mmap = amdgpu_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC,drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +39
-0@@ -57,6 +57,42 @@ void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)ttm_bo_kunmap (&bo->dma_buf_vmap); } +int amdgpu_gem_prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma) +{ +struct amdgpu_bo *bo =gem_to_amdgpu_bo (obj); +struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); +unsigned asize =amdgpu_bo_size (bo); +int ret; + +if (!obj->filp || !vma->vm_file) +return -ENODEV ; + +if (adev ==NULL ) +return -ENODEV ; + +/* Check for valid size. */ +if (asize < vma->vm_end - vma->vm_start) +return -EINVAL ; + +if (amdgpu_ttm_tt_get_usermm (bo->tbo.ttm) || + (bo->flags &AMDGPU_GEM_CREATE_NO_CPU_ACCESS )) { +return -EPERM ; + } + vma->vm_pgoff =amdgpu_bo_mmap_offset (bo) >>PAGE_SHIFT ; + +/* prime mmap does not need to check access, so allow here */ + ret =drm_vma_node_allow (&obj->vma_node, vma->vm_file->private_data); +if (ret) +return ret; + + ret =ttm_bo_mmap (vma->vm_file, vma, &adev->mman.bdev); +drm_vma_node_revoke (&obj->vma_node, vma->vm_file->private_data); +if (ret) +return ret; + +return 0 ; +} +struct drm_gem_object * amdgpu_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach,@@ -130,14 +166,71 @@ struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj)return bo->tbo.resv; } +static int amdgpu_gem_begin_cpu_access (struct dma_buf *dma_buf,enum dma_data_direction direction) +{ +struct amdgpu_bo *bo =gem_to_amdgpu_bo (dma_buf->priv);
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 181
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +10
-0+struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); +bool write = (direction ==DMA_BIDIRECTIONAL || direction ==DMA_TO_DEVICE ); +int ret; + + ret =amdgpu_gem_prime_pin (dma_buf->priv); +if (ret) +return ret; +/* invalidate the HDP read cache */ +if (write) +amdgpu_asic_invalidate_hdp (adev);
You can drop the HDP invalidation here. amdgpu_gem_prime_pin() will pin the BO into system memory.
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 192
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +11
-0+ +return ret; +} + +static int amdgpu_gem_end_cpu_access (struct dma_buf *dma_buf,enum dma_data_direction direction) +{ +struct amdgpu_bo *bo =gem_to_amdgpu_bo (dma_buf->priv); +struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); + +/* flush hdp write queue */ +amdgpu_asic_flush_hdp (adev);
Dito, HDP flush is completely unnecessary here.
BTW: You mixed up flush and invalidate. If we need to implement CPU access to VRAM you need to flush when the cpu access starts and invalidate when it ends.
Regards,
Christian.
Quoted 35 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +25
-1+amdgpu_gem_prime_unpin (dma_buf->priv); +return 0 ; +} + +static struct dma_buf_ops amdgpu_dmabuf_ops; +struct dma_buf *amdgpu_gem_prime_export (struct drm_device *dev,struct drm_gem_object *gobj,int flags) {struct amdgpu_bo *bo =gem_to_amdgpu_bo (gobj); +struct dma_buf *dma_buf;if (amdgpu_ttm_tt_get_usermm (bo->tbo.ttm))return ERR_PTR (-EPERM ); -return drm_gem_prime_export (dev, gobj, flags); + dma_buf =drm_gem_prime_export (dev, gobj, flags); + amdgpu_dmabuf_ops = *(dma_buf->ops); + amdgpu_dmabuf_ops.begin_cpu_access = amdgpu_gem_begin_cpu_access; + amdgpu_dmabuf_ops.end_cpu_access = amdgpu_gem_end_cpu_access; + dma_buf->ops = &amdgpu_dmabuf_ops; + +return dma_buf; +} + +struct drm_gem_object *amdgpu_gem_prime_import (struct drm_device *dev, +struct dma_buf *dma_buf) +{ +struct drm_gem_object *obj; + +if (dma_buf->ops == &amdgpu_dmabuf_ops) { + obj = dma_buf->priv; +if (obj->dev == dev) { +/*
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 236
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +9
-0+* Importing dmabuf exported from out own gem increases +* refcount on gem itself instead of f_count of dmabuf. +*/ +drm_gem_object_get (obj); +return obj; + } + } + +return drm_gem_prime_import (dev, dma_buf); }
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
A message that is not in the archive (sent off-list or not yet received): 30852e0e-85fe-f3ee-26fb-c86ac0038f43-ANTagKRnAhcb1SvskN2V4Q@public.gmane.org
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 181
Quoted 2 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +2
-0+if (write) +amdgpu_asic_invalidate_hdp (adev);You can drop the HDP invalidation here.
amdgpu_gem_prime_pin()will pin the BO into system memory.
My understanding here is between CPU and GPU access, the invalidate/flush is still needed, since amdgpu_gem_prime_pin() does not do that. For this one, I might need to move the invalidate() before pin(). Thoughts?
Quoted 1 line
BTW: You mixed up flush and invalidate. If we need to implement CPU access to VRAM you need to flush when the cpu access starts and invalidate when it ends.
As per the doc I forwarded to you (HDP coherency check), I think the code here is correct.
Regards,
Sam
On 2017-09-07 03:02 AM, Christian König wrote:
Am 07.09.2017 um 00:07 schrieb Samuel Li:
Quoted 97 lines
Signed-off-by Samuel Li <[email protected]>--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 95 ++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 2 deletions(-)drivers/gpu/drm/amd/amdgpu/amdgpu.h +3
-0@@ -395,11 +395,14 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,struct dma_buf *amdgpu_gem_prime_export (struct drm_device *dev,struct drm_gem_object *gobj,int flags); +struct drm_gem_object *amdgpu_gem_prime_import (struct drm_device *dev, +struct dma_buf *dma_buf);int amdgpu_gem_prime_pin (struct drm_gem_object *obj);void amdgpu_gem_prime_unpin (struct drm_gem_object *obj);struct reservation_object *amdgpu_gem_prime_res_obj (struct drm_gem_object *);void *amdgpu_gem_prime_vmap (struct drm_gem_object *obj);void amdgpu_gem_prime_vunmap (struct drm_gem_object *obj,void *vaddr); +int amdgpu_gem_prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma);int amdgpu_gem_debugfs_init (struct amdgpu_device *adev);/* sub-allocation manager, it has to be protected by another lock. drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +2
-1@@ -835,7 +835,7 @@ static struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = amdgpu_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, + .gem_prime_import = amdgpu_gem_prime_import, .gem_prime_pin = amdgpu_gem_prime_pin, .gem_prime_unpin = amdgpu_gem_prime_unpin, .gem_prime_res_obj = amdgpu_gem_prime_res_obj,@@ -843,6 +843,7 @@ static struct drm_driver kms_driver = { .gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table, .gem_prime_vmap = amdgpu_gem_prime_vmap, .gem_prime_vunmap = amdgpu_gem_prime_vunmap, + .gem_prime_mmap = amdgpu_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC,drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +37
-0@@ -57,6 +57,42 @@ void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)ttm_bo_kunmap (&bo->dma_buf_vmap); } +int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); +struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); +unsigned asize =amdgpu_bo_size (bo); +int ret; + +if (!obj->filp || !vma->vm_file) +return -ENODEV ; + +if (adev ==NULL ) +return -ENODEV ; + +/* Check for valid size. */ +if (asize < vma->vm_end - vma->vm_start) +return -EINVAL ; + +if (amdgpu_ttm_tt_get_usermm (bo->tbo.ttm) || + (bo->flags &AMDGPU_GEM_CREATE_NO_CPU_ACCESS )) { +return -EPERM ; + } + vma->vm_pgoff =amdgpu_bo_mmap_offset (bo) >>PAGE_SHIFT ; + +/* prime mmap does not need to check access, so allow here */ + ret =drm_vma_node_allow (&obj->vma_node, vma->vm_file->private_data); +if (ret) +return ret; + + ret =ttm_bo_mmap (vma->vm_file, vma, &adev->mman.bdev); +drm_vma_node_revoke (&obj->vma_node, vma->vm_file->private_data); +if (ret) +return ret; + +return 0 ; +} + struct drm_gem_object * amdgpu_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach,@@ -130,14 +166,71 @@ struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj)return bo->tbo.resv; } +static int amdgpu_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction) +{ +struct amdgpu_bo *bo =gem_to_amdgpu_bo (dma_buf->priv);
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 180
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +10
-0+struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); +bool write = (direction ==DMA_BIDIRECTIONAL || direction ==DMA_TO_DEVICE ); +int ret; + + ret =amdgpu_gem_prime_pin (dma_buf->priv); +if (ret) +return ret; +/* invalidate the HDP read cache */ +if (write) +amdgpu_asic_invalidate_hdp (adev);
You can drop the HDP invalidation here. amdgpu_gem_prime_pin() will pin the BO into system memory.
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 192
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +11
-0+ +return ret; +} + +static int amdgpu_gem_end_cpu_access (struct dma_buf *dma_buf,enum dma_data_direction direction) +{ +struct amdgpu_bo *bo =gem_to_amdgpu_bo (dma_buf->priv); +struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); + +/* flush hdp write queue */ +amdgpu_asic_flush_hdp (adev);
Dito, HDP flush is completely unnecessary here.
BTW: You mixed up flush and invalidate. If we need to implement CPU access to VRAM you need to flush when the cpu access starts and invalidate when it ends.
Regards,
Christian.
Quoted 33 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +25
-0+amdgpu_gem_prime_unpin (dma_buf->priv); +return 0 ; +} + +static struct dma_buf_ops amdgpu_dmabuf_ops; +struct dma_buf *amdgpu_gem_prime_export (struct drm_device *dev,struct drm_gem_object *gobj,int flags) {struct amdgpu_bo *bo =gem_to_amdgpu_bo (gobj); +struct dma_buf *dma_buf;if (amdgpu_ttm_tt_get_usermm (bo->tbo.ttm))return ERR_PTR (-EPERM ); - return drm_gem_prime_export(dev, gobj, flags); + dma_buf =drm_gem_prime_export (dev, gobj, flags); + amdgpu_dmabuf_ops = *(dma_buf->ops); + amdgpu_dmabuf_ops.begin_cpu_access = amdgpu_gem_begin_cpu_access; + amdgpu_dmabuf_ops.end_cpu_access = amdgpu_gem_end_cpu_access; + dma_buf->ops = &amdgpu_dmabuf_ops; + +return dma_buf; +} + +struct drm_gem_object *amdgpu_gem_prime_import (struct drm_device *dev, +struct dma_buf *dma_buf) +{ +struct drm_gem_object *obj; + +if (dma_buf->ops == &amdgpu_dmabuf_ops) { + obj = dma_buf->priv; +if (obj->dev == dev) { +/*
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 236
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +9
-0+* Importing dmabuf exported from out own gem increases +* refcount on gem itself instead of f_count of dmabuf. +*/ +drm_gem_object_get (obj); +return obj; + } + } + +return drm_gem_prime_import (dev, dma_buf); }
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
A message that is not in the archive (sent off-list or not yet received): d454ab74-2254-49c2-7dab-063e4f6cc770-5C7GfCeVMHo@public.gmane.org
Am 08.09.2017 um 00:17 schrieb Samuel Li:
Quoted 6 lines
Quoted 3 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 181
Quoted 2 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +2
-0+if (write) +amdgpu_asic_invalidate_hdp (adev);You can drop the HDP invalidation here.
amdgpu_gem_prime_pin()willpin the BO into system memory.
My understanding here is between CPU and GPU access, the invalidate/flush is still needed, since
amdgpu_gem_prime_pin()does not do that.
That understanding is incorrect. The HDP is a small read/write cache between the CPU and the VRAM.
So an HDP invalidate/flush is always needed when you want to access VRAM (local memory), since amdgpu_gem_prime_pin() pins the memory into system memory that is not necessary.
Quoted 5 lines
For this one, I might need to move the
invalidate()beforepin(). Thoughts?Quoted 1 line
BTW: You mixed up flush and invalidate. If we need to implement CPU
access to VRAM you need to flush when the cpu access starts and invalidate when it ends. As per the doc I forwarded to you (HDP coherency check), I think the code here is correct.
That might be correct. Need to double check the HDP documentation once more.
Anyway as long as we pin to system memory the whole HDP handling here is unnecessary anyway, so please remove that.
Regards,
Christian.
Quoted 184 lines
Regards,
SamOn 2017-09-07 03:02 AM, Christian König wrote:
Am 07.09.2017 um 00:07 schrieb Samuel Li:Quoted 107 lines
Signed-off-by Samuel Li <[email protected]>--- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 95 ++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 2 deletions(-)drivers/gpu/drm/amd/amdgpu/amdgpu.h +3
-0@@ -395,11 +395,14 @@ amdgpu_gem_prime_import_sg_table(structdrm_device *dev, struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,struct drm_gem_object *gobj,int flags); +struct drm_gem_object *amdgpu_gem_prime_import (struct drm_device *dev, +struct dma_buf *dma_buf);int amdgpu_gem_prime_pin (struct drm_gem_object *obj);void amdgpu_gem_prime_unpin (struct drm_gem_object *obj);struct reservation_object *amdgpu_gem_prime_res_obj (struct drm_gem_object *);void *amdgpu_gem_prime_vmap (struct drm_gem_object *obj);void amdgpu_gem_prime_vunmap (struct drm_gem_object *obj,void *vaddr); +int amdgpu_gem_prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma);int amdgpu_gem_debugfs_init(struct amdgpu_device *adev); /* sub-allocation manager, it has to be protected by another lock.drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +2
-1@@ -835,7 +835,7 @@ static struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = amdgpu_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, + .gem_prime_import = amdgpu_gem_prime_import, .gem_prime_pin = amdgpu_gem_prime_pin, .gem_prime_unpin = amdgpu_gem_prime_unpin, .gem_prime_res_obj = amdgpu_gem_prime_res_obj,@@ -843,6 +843,7 @@ static struct drm_driver kms_driver = { .gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table, .gem_prime_vmap = amdgpu_gem_prime_vmap, .gem_prime_vunmap = amdgpu_gem_prime_vunmap, + .gem_prime_mmap = amdgpu_gem_prime_mmap, .name = DRIVER_NAME, .desc = DRIVER_DESC,drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +38
-0@@ -57,6 +57,42 @@ void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)ttm_bo_kunmap (&bo->dma_buf_vmap); } +int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) +{ + struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); +struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); +unsigned asize =amdgpu_bo_size (bo); +int ret; + +if (!obj->filp || !vma->vm_file) +return -ENODEV ; + +if (adev ==NULL ) +return -ENODEV ; + +/* Check for valid size. */ +if (asize < vma->vm_end - vma->vm_start) +return -EINVAL ; + +if (amdgpu_ttm_tt_get_usermm (bo->tbo.ttm) || + (bo->flags &AMDGPU_GEM_CREATE_NO_CPU_ACCESS )) { +return -EPERM ; + } + vma->vm_pgoff =amdgpu_bo_mmap_offset (bo) >>PAGE_SHIFT ; + +/* prime mmap does not need to check access, so allow here */ + ret =drm_vma_node_allow (&obj->vma_node, vma->vm_file->private_data); +if (ret) +return ret; + + ret =ttm_bo_mmap (vma->vm_file, vma, &adev->mman.bdev); +drm_vma_node_revoke (&obj->vma_node, vma->vm_file->private_data); +if (ret) +return ret; + +return 0 ; +} + struct drm_gem_object * amdgpu_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach,@@ -130,14 +166,71 @@ struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj)return bo->tbo.resv; } +static int amdgpu_gem_begin_cpu_access(struct dma_buf *dma_buf,enum dma_data_direction direction) +{ +struct amdgpu_bo *bo =gem_to_amdgpu_bo (dma_buf->priv); +struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev);drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object · line 183
Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +9
-0+bool write = (direction ==DMA_BIDIRECTIONAL || direction ==DMA_TO_DEVICE ); +int ret; + + ret =amdgpu_gem_prime_pin (dma_buf->priv); +if (ret) +return ret; +/* invalidate the HDP read cache */ +if (write) +amdgpu_asic_invalidate_hdp (adev);You can drop the HDP invalidation here.
amdgpu_gem_prime_pin()will pin the BO into system memory.drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 192
Quoted 12 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +11
-0+ +return ret; +} + +static int amdgpu_gem_end_cpu_access (struct dma_buf *dma_buf,enum dma_data_direction direction) +{ +struct amdgpu_bo *bo =gem_to_amdgpu_bo (dma_buf->priv); +struct amdgpu_device *adev =amdgpu_ttm_adev (bo->tbo.bdev); + +/* flush hdp write queue */ +amdgpu_asic_flush_hdp (adev);Dito, HDP flush is completely unnecessary here.
BTW: You mixed up flush and invalidate. If we need to implement CPU access to VRAM you need to flush when the cpu access starts and invalidate when it ends.
Regards,
Christian.Quoted 35 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +27
-0+amdgpu_gem_prime_unpin (dma_buf->priv); +return 0 ; +} + +static struct dma_buf_ops amdgpu_dmabuf_ops; +struct dma_buf *amdgpu_gem_prime_export (struct drm_device *dev,struct drm_gem_object *gobj,int flags) {struct amdgpu_bo *bo =gem_to_amdgpu_bo (gobj); +struct dma_buf *dma_buf;if (amdgpu_ttm_tt_get_usermm (bo->tbo.ttm))return ERR_PTR (-EPERM ); - return drm_gem_prime_export(dev, gobj, flags); + dma_buf =drm_gem_prime_export (dev, gobj, flags); + amdgpu_dmabuf_ops = *(dma_buf->ops); + amdgpu_dmabuf_ops.begin_cpu_access = amdgpu_gem_begin_cpu_access; + amdgpu_dmabuf_ops.end_cpu_access = amdgpu_gem_end_cpu_access; + dma_buf->ops = &amdgpu_dmabuf_ops; + +return dma_buf; +} + +struct drm_gem_object *amdgpu_gem_prime_import (struct drm_device *dev, +struct dma_buf *dma_buf) +{ +struct drm_gem_object *obj; + +if (dma_buf->ops == &amdgpu_dmabuf_ops) { + obj = dma_buf->priv; +if (obj->dev == dev) { +/* +* Importing dmabuf exported from out own gem increases +* refcount on gem itself instead of f_count of dmabuf.
Quoted 11 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) · line 236
Quoted 8 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +7
-0+*/ +drm_gem_object_get (obj); +return obj; + } + } + +return drm_gem_prime_import (dev, dma_buf); }
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx