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: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/337948/
This commit is contained in:
Родитель
6e6db2722c
Коммит
a39414716c
|
@ -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
|
||||
* implementation
|
||||
* @dev: DRM device
|
||||
* @attach: DMA-buf attachment
|
||||
* @sg: Scatter/gather table
|
||||
* amdgpu_dma_buf_create_obj - create BO for DMA-buf import
|
||||
*
|
||||
* Imports shared DMA buffer memory exported by another device.
|
||||
* @dev: DRM device
|
||||
* @dma_buf: DMA-buf
|
||||
*
|
||||
* Creates an empty SG BO for DMA-buf import.
|
||||
*
|
||||
* Returns:
|
||||
* A new GEM BO of the given DRM device, representing the memory
|
||||
* described by the given DMA-buf attachment and scatter/gather table.
|
||||
*/
|
||||
struct drm_gem_object *
|
||||
amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
struct dma_buf_attachment *attach,
|
||||
struct sg_table *sg)
|
||||
static struct drm_gem_object *
|
||||
amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
|
||||
{
|
||||
struct dma_resv *resv = attach->dmabuf->resv;
|
||||
struct dma_resv *resv = dma_buf->resv;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_bo *bo;
|
||||
struct amdgpu_bo_param bp;
|
||||
int ret;
|
||||
|
||||
memset(&bp, 0, sizeof(bp));
|
||||
bp.size = attach->dmabuf->size;
|
||||
bp.size = dma_buf->size;
|
||||
bp.byte_align = PAGE_SIZE;
|
||||
bp.domain = AMDGPU_GEM_DOMAIN_CPU;
|
||||
bp.flags = 0;
|
||||
|
@ -405,11 +402,9 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
bo->tbo.sg = sg;
|
||||
bo->tbo.ttm->sg = sg;
|
||||
bo->allowed_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;
|
||||
|
||||
dma_resv_unlock(resv);
|
||||
|
@ -425,15 +420,15 @@ error:
|
|||
* @dev: DRM device
|
||||
* @dma_buf: Shared DMA buffer
|
||||
*
|
||||
* The main work is done by the &drm_gem_prime_import helper, which in turn
|
||||
* uses &amdgpu_gem_prime_import_sg_table.
|
||||
* Import a dma_buf into a the driver and potentially create a new GEM object.
|
||||
*
|
||||
* Returns:
|
||||
* GEM BO representing the shared DMA buffer for the given device.
|
||||
*/
|
||||
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;
|
||||
|
||||
if (dma_buf->ops == &amdgpu_dmabuf_ops) {
|
||||
|
@ -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 @@
|
|||
|
||||
#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,
|
||||
int flags);
|
||||
struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
|
||||
|
|
|
@ -1445,7 +1445,6 @@ static struct drm_driver kms_driver = {
|
|||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_export = amdgpu_gem_prime_export,
|
||||
.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_vunmap = amdgpu_gem_prime_vunmap,
|
||||
.gem_prime_mmap = amdgpu_gem_prime_mmap,
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/swiotlb.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <drm/ttm/ttm_bo_api.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,
|
|||
*/
|
||||
struct amdgpu_ttm_tt {
|
||||
struct ttm_dma_tt ttm;
|
||||
struct drm_gem_object *gobj;
|
||||
u64 offset;
|
||||
uint64_t userptr;
|
||||
struct task_struct *usertask;
|
||||
|
@ -1227,6 +1229,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
|
|||
return NULL;
|
||||
}
|
||||
gtt->ttm.ttm.func = &amdgpu_backend_func;
|
||||
gtt->gobj = &bo->base;
|
||||
|
||||
/* allocate space for the uninitialized page entries */
|
||||
if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) {
|
||||
|
@ -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_ttm_tt *gtt = (void *)ttm;
|
||||
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
|
||||
|
||||
/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
|
||||
if (gtt && gtt->userptr) {
|
||||
|
@ -1260,7 +1262,19 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
|
|||
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,
|
||||
gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
|
@ -1287,9 +1301,8 @@ static int amdgpu_ttm_tt_populate(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;
|
||||
bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
|
||||
struct amdgpu_device *adev;
|
||||
|
||||
if (gtt && gtt->userptr) {
|
||||
amdgpu_ttm_tt_set_user_pages(ttm, NULL);
|
||||
|
@ -1298,7 +1311,16 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
|
|||
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;
|
||||
|
||||
adev = amdgpu_ttm_adev(ttm->bdev);
|
||||
|
|
Загрузка…
Ссылка в новой задаче