Commit a3941471 authored by Christian König's avatar Christian König

drm/amdgpu: add independent DMA-buf import v9

Instead of relying on the DRM functions just implement our own import
functions. This prepares support for taking care of unpinned DMA-buf.

v2: enable for all exporters, not just amdgpu, fix invalidation
    handling, lock reservation object while setting callback
v3: change to new dma_buf attach interface
v4: split out from unpinned DMA-buf work
v5: rebased and cleanup on new DMA-buf interface
v6: squash with invalidation callback change,
    stop using _(map|unmap)_locked
v7: drop invalidations when the BO is already in system domain
v8: rebase on new DMA-buf patch and drop move notification
v9: cleanup comments
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/337948/
parent 6e6db272
...@@ -370,31 +370,28 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj, ...@@ -370,31 +370,28 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
} }
/** /**
* amdgpu_gem_prime_import_sg_table - &drm_driver.gem_prime_import_sg_table * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
* implementation *
* @dev: DRM device * @dev: DRM device
* @attach: DMA-buf attachment * @dma_buf: DMA-buf
* @sg: Scatter/gather table
* *
* Imports shared DMA buffer memory exported by another device. * Creates an empty SG BO for DMA-buf import.
* *
* Returns: * Returns:
* A new GEM BO of the given DRM device, representing the memory * A new GEM BO of the given DRM device, representing the memory
* described by the given DMA-buf attachment and scatter/gather table. * described by the given DMA-buf attachment and scatter/gather table.
*/ */
struct drm_gem_object * static struct drm_gem_object *
amdgpu_gem_prime_import_sg_table(struct drm_device *dev, amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
struct dma_buf_attachment *attach,
struct sg_table *sg)
{ {
struct dma_resv *resv = attach->dmabuf->resv; struct dma_resv *resv = dma_buf->resv;
struct amdgpu_device *adev = dev->dev_private; struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_bo *bo; struct amdgpu_bo *bo;
struct amdgpu_bo_param bp; struct amdgpu_bo_param bp;
int ret; int ret;
memset(&bp, 0, sizeof(bp)); memset(&bp, 0, sizeof(bp));
bp.size = attach->dmabuf->size; bp.size = dma_buf->size;
bp.byte_align = PAGE_SIZE; bp.byte_align = PAGE_SIZE;
bp.domain = AMDGPU_GEM_DOMAIN_CPU; bp.domain = AMDGPU_GEM_DOMAIN_CPU;
bp.flags = 0; bp.flags = 0;
...@@ -405,11 +402,9 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, ...@@ -405,11 +402,9 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
if (ret) if (ret)
goto error; goto error;
bo->tbo.sg = sg;
bo->tbo.ttm->sg = sg;
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT; bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT; bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
if (attach->dmabuf->ops != &amdgpu_dmabuf_ops) if (dma_buf->ops != &amdgpu_dmabuf_ops)
bo->prime_shared_count = 1; bo->prime_shared_count = 1;
dma_resv_unlock(resv); dma_resv_unlock(resv);
...@@ -425,15 +420,15 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, ...@@ -425,15 +420,15 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
* @dev: DRM device * @dev: DRM device
* @dma_buf: Shared DMA buffer * @dma_buf: Shared DMA buffer
* *
* The main work is done by the &drm_gem_prime_import helper, which in turn * Import a dma_buf into a the driver and potentially create a new GEM object.
* uses &amdgpu_gem_prime_import_sg_table.
* *
* Returns: * Returns:
* GEM BO representing the shared DMA buffer for the given device. * GEM BO representing the shared DMA buffer for the given device.
*/ */
struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf) struct dma_buf *dma_buf)
{ {
struct dma_buf_attachment *attach;
struct drm_gem_object *obj; struct drm_gem_object *obj;
if (dma_buf->ops == &amdgpu_dmabuf_ops) { if (dma_buf->ops == &amdgpu_dmabuf_ops) {
...@@ -448,5 +443,17 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, ...@@ -448,5 +443,17 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
} }
} }
return drm_gem_prime_import(dev, dma_buf); obj = amdgpu_dma_buf_create_obj(dev, dma_buf);
if (IS_ERR(obj))
return obj;
attach = dma_buf_dynamic_attach(dma_buf, dev->dev, true);
if (IS_ERR(attach)) {
drm_gem_object_put(obj);
return ERR_CAST(attach);
}
get_dma_buf(dma_buf);
obj->import_attach = attach;
return obj;
} }
...@@ -25,10 +25,6 @@ ...@@ -25,10 +25,6 @@
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
struct drm_gem_object *
amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach,
struct sg_table *sg);
struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj, struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
int flags); int flags);
struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
......
...@@ -1445,7 +1445,6 @@ static struct drm_driver kms_driver = { ...@@ -1445,7 +1445,6 @@ static struct drm_driver kms_driver = {
.prime_fd_to_handle = drm_gem_prime_fd_to_handle, .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = amdgpu_gem_prime_export, .gem_prime_export = amdgpu_gem_prime_export,
.gem_prime_import = amdgpu_gem_prime_import, .gem_prime_import = amdgpu_gem_prime_import,
.gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table,
.gem_prime_vmap = amdgpu_gem_prime_vmap, .gem_prime_vmap = amdgpu_gem_prime_vmap,
.gem_prime_vunmap = amdgpu_gem_prime_vunmap, .gem_prime_vunmap = amdgpu_gem_prime_vunmap,
.gem_prime_mmap = amdgpu_gem_prime_mmap, .gem_prime_mmap = amdgpu_gem_prime_mmap,
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/swiotlb.h> #include <linux/swiotlb.h>
#include <linux/dma-buf.h>
#include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_api.h>
#include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_bo_driver.h>
...@@ -763,6 +764,7 @@ static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo, ...@@ -763,6 +764,7 @@ static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
*/ */
struct amdgpu_ttm_tt { struct amdgpu_ttm_tt {
struct ttm_dma_tt ttm; struct ttm_dma_tt ttm;
struct drm_gem_object *gobj;
u64 offset; u64 offset;
uint64_t userptr; uint64_t userptr;
struct task_struct *usertask; struct task_struct *usertask;
...@@ -1227,6 +1229,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, ...@@ -1227,6 +1229,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
return NULL; return NULL;
} }
gtt->ttm.ttm.func = &amdgpu_backend_func; gtt->ttm.ttm.func = &amdgpu_backend_func;
gtt->gobj = &bo->base;
/* allocate space for the uninitialized page entries */ /* allocate space for the uninitialized page entries */
if (ttm_sg_tt_init(&gtt->ttm, bo, page_flags)) { if (ttm_sg_tt_init(&gtt->ttm, bo, page_flags)) {
...@@ -1247,7 +1250,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, ...@@ -1247,7 +1250,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
{ {
struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm; struct amdgpu_ttm_tt *gtt = (void *)ttm;
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */ /* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
if (gtt && gtt->userptr) { if (gtt && gtt->userptr) {
...@@ -1260,7 +1262,19 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, ...@@ -1260,7 +1262,19 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
return 0; return 0;
} }
if (slave && ttm->sg) { if (ttm->page_flags & TTM_PAGE_FLAG_SG) {
if (!ttm->sg) {
struct dma_buf_attachment *attach;
struct sg_table *sgt;
attach = gtt->gobj->import_attach;
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt))
return PTR_ERR(sgt);
ttm->sg = sgt;
}
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
gtt->ttm.dma_address, gtt->ttm.dma_address,
ttm->num_pages); ttm->num_pages);
...@@ -1287,9 +1301,8 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, ...@@ -1287,9 +1301,8 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
*/ */
static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
{ {
struct amdgpu_device *adev;
struct amdgpu_ttm_tt *gtt = (void *)ttm; struct amdgpu_ttm_tt *gtt = (void *)ttm;
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); struct amdgpu_device *adev;
if (gtt && gtt->userptr) { if (gtt && gtt->userptr) {
amdgpu_ttm_tt_set_user_pages(ttm, NULL); amdgpu_ttm_tt_set_user_pages(ttm, NULL);
...@@ -1298,7 +1311,16 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) ...@@ -1298,7 +1311,16 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
return; return;
} }
if (slave) if (ttm->sg && gtt->gobj->import_attach) {
struct dma_buf_attachment *attach;
attach = gtt->gobj->import_attach;
dma_buf_unmap_attachment(attach, ttm->sg, DMA_BIDIRECTIONAL);
ttm->sg = NULL;
return;
}
if (ttm->page_flags & TTM_PAGE_FLAG_SG)
return; return;
adev = amdgpu_ttm_adev(ttm->bdev); adev = amdgpu_ttm_adev(ttm->bdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment