Skip to content

Commit b32233a

Browse files
committed
drm/vmwgfx: Fix prime import/export
vmwgfx never supported prime import of external buffers. Furthermore the driver exposes two different objects to userspace: vmw_surface's and gem buffers but prime import/export only worked with vmw_surfaces. Because gem buffers are used through the dumb_buffer interface this meant that the driver created buffers couldn't have been prime exported or imported. Fix prime import/export. Makes IGT's kms_prime pass. Signed-off-by: Zack Rusin <[email protected]> Fixes: 8afa13a ("drm/vmwgfx: Implement DRIVER_GEM") Cc: <[email protected]> # v6.6+ Reviewed-by: Martin Krastev <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent b6976f3 commit b32233a

File tree

8 files changed

+117
-22
lines changed

8 files changed

+117
-22
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_blit.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
456456
.no_wait_gpu = false
457457
};
458458
u32 j, initial_line = dst_offset / dst_stride;
459-
struct vmw_bo_blit_line_data d;
459+
struct vmw_bo_blit_line_data d = {0};
460460
int ret = 0;
461+
struct page **dst_pages = NULL;
462+
struct page **src_pages = NULL;
461463

462464
/* Buffer objects need to be either pinned or reserved: */
463465
if (!(dst->pin_count))
@@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
477479
return ret;
478480
}
479481

482+
if (!src->ttm->pages && src->ttm->sg) {
483+
src_pages = kvmalloc_array(src->ttm->num_pages,
484+
sizeof(struct page *), GFP_KERNEL);
485+
if (!src_pages)
486+
return -ENOMEM;
487+
ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages,
488+
src->ttm->num_pages);
489+
if (ret)
490+
goto out;
491+
}
492+
if (!dst->ttm->pages && dst->ttm->sg) {
493+
dst_pages = kvmalloc_array(dst->ttm->num_pages,
494+
sizeof(struct page *), GFP_KERNEL);
495+
if (!dst_pages) {
496+
ret = -ENOMEM;
497+
goto out;
498+
}
499+
ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages,
500+
dst->ttm->num_pages);
501+
if (ret)
502+
goto out;
503+
}
504+
480505
d.mapped_dst = 0;
481506
d.mapped_src = 0;
482507
d.dst_addr = NULL;
483508
d.src_addr = NULL;
484-
d.dst_pages = dst->ttm->pages;
485-
d.src_pages = src->ttm->pages;
509+
d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages;
510+
d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages;
486511
d.dst_num_pages = PFN_UP(dst->resource->size);
487512
d.src_num_pages = PFN_UP(src->resource->size);
488513
d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL);
@@ -504,6 +529,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
504529
kunmap_atomic(d.src_addr);
505530
if (d.dst_addr)
506531
kunmap_atomic(d.dst_addr);
532+
if (src_pages)
533+
kvfree(src_pages);
534+
if (dst_pages)
535+
kvfree(dst_pages);
507536

508537
return ret;
509538
}

drivers/gpu/drm/vmwgfx/vmwgfx_bo.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
377377
{
378378
struct ttm_operation_ctx ctx = {
379379
.interruptible = params->bo_type != ttm_bo_type_kernel,
380-
.no_wait_gpu = false
380+
.no_wait_gpu = false,
381+
.resv = params->resv,
381382
};
382383
struct ttm_device *bdev = &dev_priv->bdev;
383384
struct drm_device *vdev = &dev_priv->drm;
@@ -394,8 +395,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
394395

395396
vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
396397
ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
397-
&vmw_bo->placement, 0, &ctx, NULL,
398-
NULL, destroy);
398+
&vmw_bo->placement, 0, &ctx,
399+
params->sg, params->resv, destroy);
399400
if (unlikely(ret))
400401
return ret;
401402

drivers/gpu/drm/vmwgfx/vmwgfx_bo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ struct vmw_bo_params {
5555
enum ttm_bo_type bo_type;
5656
size_t size;
5757
bool pin;
58+
struct dma_resv *resv;
59+
struct sg_table *sg;
5860
};
5961

6062
/**

drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,7 @@ static const struct drm_driver driver = {
16281628

16291629
.prime_fd_to_handle = vmw_prime_fd_to_handle,
16301630
.prime_handle_to_fd = vmw_prime_handle_to_fd,
1631+
.gem_prime_import_sg_table = vmw_prime_import_sg_table,
16311632

16321633
.fops = &vmwgfx_driver_fops,
16331634
.name = VMWGFX_DRIVER_NAME,

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
11301130
struct drm_file *file_priv,
11311131
uint32_t handle, uint32_t flags,
11321132
int *prime_fd);
1133+
struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
1134+
struct dma_buf_attachment *attach,
1135+
struct sg_table *table);
11331136

11341137
/*
11351138
* MemoryOBject management - vmwgfx_mob.c

drivers/gpu/drm/vmwgfx/vmwgfx_gem.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,38 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv,
149149
return ret;
150150
}
151151

152+
struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
153+
struct dma_buf_attachment *attach,
154+
struct sg_table *table)
155+
{
156+
int ret;
157+
struct vmw_private *dev_priv = vmw_priv(dev);
158+
struct drm_gem_object *gem = NULL;
159+
struct vmw_bo *vbo;
160+
struct vmw_bo_params params = {
161+
.domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM,
162+
.busy_domain = VMW_BO_DOMAIN_SYS,
163+
.bo_type = ttm_bo_type_sg,
164+
.size = attach->dmabuf->size,
165+
.pin = false,
166+
.resv = attach->dmabuf->resv,
167+
.sg = table,
168+
169+
};
170+
171+
dma_resv_lock(params.resv, NULL);
172+
173+
ret = vmw_bo_create(dev_priv, &params, &vbo);
174+
if (ret != 0)
175+
goto out_no_bo;
176+
177+
vbo->tbo.base.funcs = &vmw_gem_object_funcs;
178+
179+
gem = &vbo->tbo.base;
180+
out_no_bo:
181+
dma_resv_unlock(params.resv);
182+
return gem;
183+
}
152184

153185
int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
154186
struct drm_file *filp)

drivers/gpu/drm/vmwgfx/vmwgfx_prime.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,12 @@ int vmw_prime_fd_to_handle(struct drm_device *dev,
7575
int fd, u32 *handle)
7676
{
7777
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
78+
int ret = ttm_prime_fd_to_handle(tfile, fd, handle);
7879

79-
return ttm_prime_fd_to_handle(tfile, fd, handle);
80+
if (ret)
81+
ret = drm_gem_prime_fd_to_handle(dev, file_priv, fd, handle);
82+
83+
return ret;
8084
}
8185

8286
int vmw_prime_handle_to_fd(struct drm_device *dev,
@@ -85,5 +89,12 @@ int vmw_prime_handle_to_fd(struct drm_device *dev,
8589
int *prime_fd)
8690
{
8791
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
88-
return ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
92+
int ret;
93+
94+
if (handle > VMWGFX_NUM_MOB)
95+
ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
96+
else
97+
ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
98+
99+
return ret;
89100
}

drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
188188
switch (dev_priv->map_mode) {
189189
case vmw_dma_map_bind:
190190
case vmw_dma_map_populate:
191-
vsgt->sgt = &vmw_tt->sgt;
192-
ret = sg_alloc_table_from_pages_segment(
193-
&vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0,
194-
(unsigned long)vsgt->num_pages << PAGE_SHIFT,
195-
dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL);
196-
if (ret)
197-
goto out_sg_alloc_fail;
191+
if (vmw_tt->dma_ttm.page_flags & TTM_TT_FLAG_EXTERNAL) {
192+
vsgt->sgt = vmw_tt->dma_ttm.sg;
193+
} else {
194+
vsgt->sgt = &vmw_tt->sgt;
195+
ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt,
196+
vsgt->pages, vsgt->num_pages, 0,
197+
(unsigned long)vsgt->num_pages << PAGE_SHIFT,
198+
dma_get_max_seg_size(dev_priv->drm.dev),
199+
GFP_KERNEL);
200+
if (ret)
201+
goto out_sg_alloc_fail;
202+
}
198203

199204
ret = vmw_ttm_map_for_dma(vmw_tt);
200205
if (unlikely(ret != 0))
@@ -209,8 +214,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
209214
return 0;
210215

211216
out_map_fail:
212-
sg_free_table(vmw_tt->vsgt.sgt);
213-
vmw_tt->vsgt.sgt = NULL;
217+
drm_warn(&dev_priv->drm, "VSG table map failed!");
218+
sg_free_table(vsgt->sgt);
219+
vsgt->sgt = NULL;
214220
out_sg_alloc_fail:
215221
return ret;
216222
}
@@ -356,22 +362,28 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
356362
static int vmw_ttm_populate(struct ttm_device *bdev,
357363
struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
358364
{
359-
int ret;
365+
bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
360366

361-
/* TODO: maybe completely drop this ? */
362367
if (ttm_tt_is_populated(ttm))
363368
return 0;
364369

365-
ret = ttm_pool_alloc(&bdev->pool, ttm, ctx);
370+
if (external && ttm->sg)
371+
return drm_prime_sg_to_dma_addr_array(ttm->sg,
372+
ttm->dma_address,
373+
ttm->num_pages);
366374

367-
return ret;
375+
return ttm_pool_alloc(&bdev->pool, ttm, ctx);
368376
}
369377

370378
static void vmw_ttm_unpopulate(struct ttm_device *bdev,
371379
struct ttm_tt *ttm)
372380
{
373381
struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,
374382
dma_ttm);
383+
bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
384+
385+
if (external)
386+
return;
375387

376388
vmw_ttm_unbind(bdev, ttm);
377389

@@ -390,6 +402,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
390402
{
391403
struct vmw_ttm_tt *vmw_be;
392404
int ret;
405+
bool external = bo->type == ttm_bo_type_sg;
393406

394407
vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL);
395408
if (!vmw_be)
@@ -398,7 +411,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
398411
vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev);
399412
vmw_be->mob = NULL;
400413

401-
if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
414+
if (external)
415+
page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE;
416+
417+
if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external)
402418
ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags,
403419
ttm_cached);
404420
else

0 commit comments

Comments
 (0)