[PATCH 6/6] drm/amdgpu: Add gem_prime_mmap support

Christian König deathsimple at vodafone.de
Fri Sep 8 08:16:19 UTC 2017


Am 08.09.2017 um 00:17 schrieb Samuel Li:
> >>+    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.

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.

> For this one, I might need to move the invalidate() before pin(). 
> Thoughts?
>
> > 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.

>
> Regards,
> Sam
>
>
>
>
> On 2017-09-07 03:02 AM, Christian König wrote:
> Am 07.09.2017 um 00:07 schrieb Samuel Li:
>> Signed-off-by: Samuel Li <Samuel.Li at amd.com>
>> ---
>>   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(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> index 6f262ce..3c43acf 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> @@ -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.
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>> index 2cdf844..9b63ac5 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
>> @@ -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,
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c 
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
>> index 5b3f928..629a654 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
>> @@ -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);
>> +    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.
>
>> +
>> +    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.
>
>> + 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.
>> +             */
>> +            drm_gem_object_get(obj);
>> +            return obj;
>> +        }
>> +    }
>> +
>> +    return drm_gem_prime_import(dev, dma_buf);
>>   }
>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/amd-gfx/attachments/20170908/4c162a7d/attachment-0001.html>


More information about the amd-gfx mailing list