aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoralf Trønnes <noralf@tronnes.org>2018-11-10 09:56:46 -0500
committerNoralf Trønnes <noralf@tronnes.org>2018-11-20 08:57:25 -0500
commitb9068cde51eea189c2c3560a9a8ae83f7b213c9c (patch)
treea0fccbb4bbbdb067c68070e53d64844659b9f70e
parentb39b5394fabc79acbaafb26b777fd348c868bf7e (diff)
drm/cma-helper: Add DRM_GEM_CMA_VMAP_DRIVER_OPS
This adds functionality to the CMA helper which ensures that the kernel virtual address is set on the CMA GEM object also for imported buffers. The drivers have been audited to ensure that none set ->vaddr on imported buffers, making the conditional dma_buf_vunmap() call in drm_gem_cma_free_object() safe. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/20181110145647.17580-5-noralf@tronnes.org
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c86
-rw-r--r--include/drm/drm_gem_cma_helper.h24
2 files changed, 110 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index 1d2ced882b66..cc26625b4b33 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -176,6 +176,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
176 * 176 *
177 * This function frees the backing memory of the CMA GEM object, cleans up the 177 * This function frees the backing memory of the CMA GEM object, cleans up the
178 * GEM object state and frees the memory used to store the object itself. 178 * GEM object state and frees the memory used to store the object itself.
179 * If the buffer is imported and the virtual address is set, it is released.
179 * Drivers using the CMA helpers should set this as their 180 * Drivers using the CMA helpers should set this as their
180 * &drm_driver.gem_free_object_unlocked callback. 181 * &drm_driver.gem_free_object_unlocked callback.
181 */ 182 */
@@ -189,6 +190,8 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
189 dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, 190 dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
190 cma_obj->vaddr, cma_obj->paddr); 191 cma_obj->vaddr, cma_obj->paddr);
191 } else if (gem_obj->import_attach) { 192 } else if (gem_obj->import_attach) {
193 if (cma_obj->vaddr)
194 dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr);
192 drm_prime_gem_destroy(gem_obj, cma_obj->sgt); 195 drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
193 } 196 }
194 197
@@ -575,3 +578,86 @@ void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
575 /* Nothing to do */ 578 /* Nothing to do */
576} 579}
577EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vunmap); 580EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vunmap);
581
582static const struct drm_gem_object_funcs drm_cma_gem_default_funcs = {
583 .free = drm_gem_cma_free_object,
584 .print_info = drm_gem_cma_print_info,
585 .get_sg_table = drm_gem_cma_prime_get_sg_table,
586 .vmap = drm_gem_cma_prime_vmap,
587 .vm_ops = &drm_gem_cma_vm_ops,
588};
589
590/**
591 * drm_cma_gem_create_object_default_funcs - Create a CMA GEM object with a
592 * default function table
593 * @dev: DRM device
594 * @size: Size of the object to allocate
595 *
596 * This sets the GEM object functions to the default CMA helper functions.
597 * This function can be used as the &drm_driver.gem_create_object callback.
598 *
599 * Returns:
600 * A pointer to a allocated GEM object or an error pointer on failure.
601 */
602struct drm_gem_object *
603drm_cma_gem_create_object_default_funcs(struct drm_device *dev, size_t size)
604{
605 struct drm_gem_cma_object *cma_obj;
606
607 cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
608 if (!cma_obj)
609 return NULL;
610
611 cma_obj->base.funcs = &drm_cma_gem_default_funcs;
612
613 return &cma_obj->base;
614}
615EXPORT_SYMBOL(drm_cma_gem_create_object_default_funcs);
616
617/**
618 * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
619 * scatter/gather table and get the virtual address of the buffer
620 * @dev: DRM device
621 * @attach: DMA-BUF attachment
622 * @sgt: Scatter/gather table of pinned pages
623 *
624 * This function imports a scatter/gather table using
625 * drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel
626 * virtual address. This ensures that a CMA GEM object always has its virtual
627 * address set. This address is released when the object is freed.
628 *
629 * This function can be used as the &drm_driver.gem_prime_import_sg_table
630 * callback. The DRM_GEM_CMA_VMAP_DRIVER_OPS() macro provides a shortcut to set
631 * the necessary DRM driver operations.
632 *
633 * Returns:
634 * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
635 * error code on failure.
636 */
637struct drm_gem_object *
638drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev,
639 struct dma_buf_attachment *attach,
640 struct sg_table *sgt)
641{
642 struct drm_gem_cma_object *cma_obj;
643 struct drm_gem_object *obj;
644 void *vaddr;
645
646 vaddr = dma_buf_vmap(attach->dmabuf);
647 if (!vaddr) {
648 DRM_ERROR("Failed to vmap PRIME buffer\n");
649 return ERR_PTR(-ENOMEM);
650 }
651
652 obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
653 if (IS_ERR(obj)) {
654 dma_buf_vunmap(attach->dmabuf, vaddr);
655 return obj;
656 }
657
658 cma_obj = to_drm_gem_cma_obj(obj);
659 cma_obj->vaddr = vaddr;
660
661 return obj;
662}
663EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap);
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index 19777145cf8e..07c504940ba1 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -103,4 +103,28 @@ int drm_gem_cma_prime_mmap(struct drm_gem_object *obj,
103void *drm_gem_cma_prime_vmap(struct drm_gem_object *obj); 103void *drm_gem_cma_prime_vmap(struct drm_gem_object *obj);
104void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr); 104void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
105 105
106struct drm_gem_object *
107drm_cma_gem_create_object_default_funcs(struct drm_device *dev, size_t size);
108
109/**
110 * DRM_GEM_CMA_VMAP_DRIVER_OPS - CMA GEM driver operations ensuring a virtual
111 * address on the buffer
112 *
113 * This macro provides a shortcut for setting the default GEM operations in the
114 * &drm_driver structure for drivers that need the virtual address also on
115 * imported buffers.
116 */
117#define DRM_GEM_CMA_VMAP_DRIVER_OPS \
118 .gem_create_object = drm_cma_gem_create_object_default_funcs, \
119 .dumb_create = drm_gem_cma_dumb_create, \
120 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, \
121 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, \
122 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table_vmap, \
123 .gem_prime_mmap = drm_gem_prime_mmap
124
125struct drm_gem_object *
126drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *drm,
127 struct dma_buf_attachment *attach,
128 struct sg_table *sgt);
129
106#endif /* __DRM_GEM_CMA_HELPER_H__ */ 130#endif /* __DRM_GEM_CMA_HELPER_H__ */