From patchwork Sat Nov 10 14:56:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Noralf_Tr=C3=B8nnes?= X-Patchwork-Id: 10677221 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 60A4013AD for ; Sat, 10 Nov 2018 14:57:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 505A92C897 for ; Sat, 10 Nov 2018 14:57:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 450F42CA4F; Sat, 10 Nov 2018 14:57:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CEB9B2C897 for ; Sat, 10 Nov 2018 14:57:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C9DA36E0C3; Sat, 10 Nov 2018 14:57:22 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from smtp.domeneshop.no (smtp.domeneshop.no [IPv6:2a01:5b40:0:3005::1]) by gabe.freedesktop.org (Postfix) with ESMTPS id 98DFC6E0C3; Sat, 10 Nov 2018 14:57:20 +0000 (UTC) Received: from 211.81-166-168.customer.lyse.net ([81.166.168.211]:42860 helo=localhost.localdomain) by smtp.domeneshop.no with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.84_2) (envelope-from ) id 1gLUhK-00006h-N7; Sat, 10 Nov 2018 15:57:18 +0100 From: =?utf-8?q?Noralf_Tr=C3=B8nnes?= To: dri-devel@lists.freedesktop.org Date: Sat, 10 Nov 2018 15:56:46 +0100 Message-Id: <20181110145647.17580-5-noralf@tronnes.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20181110145647.17580-1-noralf@tronnes.org> References: <20181110145647.17580-1-noralf@tronnes.org> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 4/5] drm/cma-helper: Add DRM_GEM_CMA_VMAP_DRIVER_OPS X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: david@lechnology.com, intel-gfx@lists.freedesktop.org, =?utf-8?q?Noralf_?= =?utf-8?q?Tr=C3=B8nnes?= , sam@ravnborg.org, christian.koenig@amd.com Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Eric Anholt --- drivers/gpu/drm/drm_gem_cma_helper.c | 86 ++++++++++++++++++++++++++++++++++++ include/drm/drm_gem_cma_helper.h | 24 ++++++++++ 2 files changed, 110 insertions(+) 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, * * This function frees the backing memory of the CMA GEM object, cleans up the * GEM object state and frees the memory used to store the object itself. + * If the buffer is imported and the virtual address is set, it is released. * Drivers using the CMA helpers should set this as their * &drm_driver.gem_free_object_unlocked callback. */ @@ -189,6 +190,8 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, cma_obj->vaddr, cma_obj->paddr); } else if (gem_obj->import_attach) { + if (cma_obj->vaddr) + dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr); drm_prime_gem_destroy(gem_obj, cma_obj->sgt); } @@ -575,3 +578,86 @@ void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr) /* Nothing to do */ } EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vunmap); + +static const struct drm_gem_object_funcs drm_cma_gem_default_funcs = { + .free = drm_gem_cma_free_object, + .print_info = drm_gem_cma_print_info, + .get_sg_table = drm_gem_cma_prime_get_sg_table, + .vmap = drm_gem_cma_prime_vmap, + .vm_ops = &drm_gem_cma_vm_ops, +}; + +/** + * drm_cma_gem_create_object_default_funcs - Create a CMA GEM object with a + * default function table + * @dev: DRM device + * @size: Size of the object to allocate + * + * This sets the GEM object functions to the default CMA helper functions. + * This function can be used as the &drm_driver.gem_create_object callback. + * + * Returns: + * A pointer to a allocated GEM object or an error pointer on failure. + */ +struct drm_gem_object * +drm_cma_gem_create_object_default_funcs(struct drm_device *dev, size_t size) +{ + struct drm_gem_cma_object *cma_obj; + + cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); + if (!cma_obj) + return NULL; + + cma_obj->base.funcs = &drm_cma_gem_default_funcs; + + return &cma_obj->base; +} +EXPORT_SYMBOL(drm_cma_gem_create_object_default_funcs); + +/** + * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's + * scatter/gather table and get the virtual address of the buffer + * @dev: DRM device + * @attach: DMA-BUF attachment + * @sgt: Scatter/gather table of pinned pages + * + * This function imports a scatter/gather table using + * drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel + * virtual address. This ensures that a CMA GEM object always has its virtual + * address set. This address is released when the object is freed. + * + * This function can be used as the &drm_driver.gem_prime_import_sg_table + * callback. The DRM_GEM_CMA_VMAP_DRIVER_OPS() macro provides a shortcut to set + * the necessary DRM driver operations. + * + * Returns: + * A pointer to a newly created GEM object or an ERR_PTR-encoded negative + * error code on failure. + */ +struct drm_gem_object * +drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sgt) +{ + struct drm_gem_cma_object *cma_obj; + struct drm_gem_object *obj; + void *vaddr; + + vaddr = dma_buf_vmap(attach->dmabuf); + if (!vaddr) { + DRM_ERROR("Failed to vmap PRIME buffer\n"); + return ERR_PTR(-ENOMEM); + } + + obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt); + if (IS_ERR(obj)) { + dma_buf_vunmap(attach->dmabuf, vaddr); + return obj; + } + + cma_obj = to_drm_gem_cma_obj(obj); + cma_obj->vaddr = vaddr; + + return obj; +} +EXPORT_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, void *drm_gem_cma_prime_vmap(struct drm_gem_object *obj); void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr); +struct drm_gem_object * +drm_cma_gem_create_object_default_funcs(struct drm_device *dev, size_t size); + +/** + * DRM_GEM_CMA_VMAP_DRIVER_OPS - CMA GEM driver operations ensuring a virtual + * address on the buffer + * + * This macro provides a shortcut for setting the default GEM operations in the + * &drm_driver structure for drivers that need the virtual address also on + * imported buffers. + */ +#define DRM_GEM_CMA_VMAP_DRIVER_OPS \ + .gem_create_object = drm_cma_gem_create_object_default_funcs, \ + .dumb_create = drm_gem_cma_dumb_create, \ + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, \ + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, \ + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table_vmap, \ + .gem_prime_mmap = drm_gem_prime_mmap + +struct drm_gem_object * +drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *drm, + struct dma_buf_attachment *attach, + struct sg_table *sgt); + #endif /* __DRM_GEM_CMA_HELPER_H__ */