18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright © 2012 Red Hat
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next
128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
138c2ecf20Sopenharmony_ci * Software.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
218c2ecf20Sopenharmony_ci * IN THE SOFTWARE.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Authors:
248c2ecf20Sopenharmony_ci *      Dave Airlie <airlied@redhat.com>
258c2ecf20Sopenharmony_ci *      Rob Clark <rob.clark@linaro.org>
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include <linux/export.h>
308c2ecf20Sopenharmony_ci#include <linux/dma-buf.h>
318c2ecf20Sopenharmony_ci#include <linux/rbtree.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include <drm/drm.h>
348c2ecf20Sopenharmony_ci#include <drm/drm_drv.h>
358c2ecf20Sopenharmony_ci#include <drm/drm_file.h>
368c2ecf20Sopenharmony_ci#include <drm/drm_framebuffer.h>
378c2ecf20Sopenharmony_ci#include <drm/drm_gem.h>
388c2ecf20Sopenharmony_ci#include <drm/drm_prime.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#include "drm_internal.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/**
438c2ecf20Sopenharmony_ci * DOC: overview and lifetime rules
448c2ecf20Sopenharmony_ci *
458c2ecf20Sopenharmony_ci * Similar to GEM global names, PRIME file descriptors are also used to share
468c2ecf20Sopenharmony_ci * buffer objects across processes. They offer additional security: as file
478c2ecf20Sopenharmony_ci * descriptors must be explicitly sent over UNIX domain sockets to be shared
488c2ecf20Sopenharmony_ci * between applications, they can't be guessed like the globally unique GEM
498c2ecf20Sopenharmony_ci * names.
508c2ecf20Sopenharmony_ci *
518c2ecf20Sopenharmony_ci * Drivers that support the PRIME API implement the
528c2ecf20Sopenharmony_ci * &drm_driver.prime_handle_to_fd and &drm_driver.prime_fd_to_handle operations.
538c2ecf20Sopenharmony_ci * GEM based drivers must use drm_gem_prime_handle_to_fd() and
548c2ecf20Sopenharmony_ci * drm_gem_prime_fd_to_handle() to implement these. For GEM based drivers the
558c2ecf20Sopenharmony_ci * actual driver interfaces is provided through the &drm_gem_object_funcs.export
568c2ecf20Sopenharmony_ci * and &drm_driver.gem_prime_import hooks.
578c2ecf20Sopenharmony_ci *
588c2ecf20Sopenharmony_ci * &dma_buf_ops implementations for GEM drivers are all individually exported
598c2ecf20Sopenharmony_ci * for drivers which need to overwrite or reimplement some of them.
608c2ecf20Sopenharmony_ci *
618c2ecf20Sopenharmony_ci * Reference Counting for GEM Drivers
628c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
638c2ecf20Sopenharmony_ci *
648c2ecf20Sopenharmony_ci * On the export the &dma_buf holds a reference to the exported buffer object,
658c2ecf20Sopenharmony_ci * usually a &drm_gem_object. It takes this reference in the PRIME_HANDLE_TO_FD
668c2ecf20Sopenharmony_ci * IOCTL, when it first calls &drm_gem_object_funcs.export
678c2ecf20Sopenharmony_ci * and stores the exporting GEM object in the &dma_buf.priv field. This
688c2ecf20Sopenharmony_ci * reference needs to be released when the final reference to the &dma_buf
698c2ecf20Sopenharmony_ci * itself is dropped and its &dma_buf_ops.release function is called.  For
708c2ecf20Sopenharmony_ci * GEM-based drivers, the &dma_buf should be exported using
718c2ecf20Sopenharmony_ci * drm_gem_dmabuf_export() and then released by drm_gem_dmabuf_release().
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * Thus the chain of references always flows in one direction, avoiding loops:
748c2ecf20Sopenharmony_ci * importing GEM object -> dma-buf -> exported GEM bo. A further complication
758c2ecf20Sopenharmony_ci * are the lookup caches for import and export. These are required to guarantee
768c2ecf20Sopenharmony_ci * that any given object will always have only one uniqe userspace handle. This
778c2ecf20Sopenharmony_ci * is required to allow userspace to detect duplicated imports, since some GEM
788c2ecf20Sopenharmony_ci * drivers do fail command submissions if a given buffer object is listed more
798c2ecf20Sopenharmony_ci * than once. These import and export caches in &drm_prime_file_private only
808c2ecf20Sopenharmony_ci * retain a weak reference, which is cleaned up when the corresponding object is
818c2ecf20Sopenharmony_ci * released.
828c2ecf20Sopenharmony_ci *
838c2ecf20Sopenharmony_ci * Self-importing: If userspace is using PRIME as a replacement for flink then
848c2ecf20Sopenharmony_ci * it will get a fd->handle request for a GEM object that it created.  Drivers
858c2ecf20Sopenharmony_ci * should detect this situation and return back the underlying object from the
868c2ecf20Sopenharmony_ci * dma-buf private. For GEM based drivers this is handled in
878c2ecf20Sopenharmony_ci * drm_gem_prime_import() already.
888c2ecf20Sopenharmony_ci */
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistruct drm_prime_member {
918c2ecf20Sopenharmony_ci	struct dma_buf *dma_buf;
928c2ecf20Sopenharmony_ci	uint32_t handle;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	struct rb_node dmabuf_rb;
958c2ecf20Sopenharmony_ci	struct rb_node handle_rb;
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
998c2ecf20Sopenharmony_ci				    struct dma_buf *dma_buf, uint32_t handle)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	struct drm_prime_member *member;
1028c2ecf20Sopenharmony_ci	struct rb_node **p, *rb;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	member = kmalloc(sizeof(*member), GFP_KERNEL);
1058c2ecf20Sopenharmony_ci	if (!member)
1068c2ecf20Sopenharmony_ci		return -ENOMEM;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	get_dma_buf(dma_buf);
1098c2ecf20Sopenharmony_ci	member->dma_buf = dma_buf;
1108c2ecf20Sopenharmony_ci	member->handle = handle;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	rb = NULL;
1138c2ecf20Sopenharmony_ci	p = &prime_fpriv->dmabufs.rb_node;
1148c2ecf20Sopenharmony_ci	while (*p) {
1158c2ecf20Sopenharmony_ci		struct drm_prime_member *pos;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci		rb = *p;
1188c2ecf20Sopenharmony_ci		pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
1198c2ecf20Sopenharmony_ci		if (dma_buf > pos->dma_buf)
1208c2ecf20Sopenharmony_ci			p = &rb->rb_right;
1218c2ecf20Sopenharmony_ci		else
1228c2ecf20Sopenharmony_ci			p = &rb->rb_left;
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci	rb_link_node(&member->dmabuf_rb, rb, p);
1258c2ecf20Sopenharmony_ci	rb_insert_color(&member->dmabuf_rb, &prime_fpriv->dmabufs);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	rb = NULL;
1288c2ecf20Sopenharmony_ci	p = &prime_fpriv->handles.rb_node;
1298c2ecf20Sopenharmony_ci	while (*p) {
1308c2ecf20Sopenharmony_ci		struct drm_prime_member *pos;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci		rb = *p;
1338c2ecf20Sopenharmony_ci		pos = rb_entry(rb, struct drm_prime_member, handle_rb);
1348c2ecf20Sopenharmony_ci		if (handle > pos->handle)
1358c2ecf20Sopenharmony_ci			p = &rb->rb_right;
1368c2ecf20Sopenharmony_ci		else
1378c2ecf20Sopenharmony_ci			p = &rb->rb_left;
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci	rb_link_node(&member->handle_rb, rb, p);
1408c2ecf20Sopenharmony_ci	rb_insert_color(&member->handle_rb, &prime_fpriv->handles);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	return 0;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic struct dma_buf *drm_prime_lookup_buf_by_handle(struct drm_prime_file_private *prime_fpriv,
1468c2ecf20Sopenharmony_ci						      uint32_t handle)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct rb_node *rb;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	rb = prime_fpriv->handles.rb_node;
1518c2ecf20Sopenharmony_ci	while (rb) {
1528c2ecf20Sopenharmony_ci		struct drm_prime_member *member;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci		member = rb_entry(rb, struct drm_prime_member, handle_rb);
1558c2ecf20Sopenharmony_ci		if (member->handle == handle)
1568c2ecf20Sopenharmony_ci			return member->dma_buf;
1578c2ecf20Sopenharmony_ci		else if (member->handle < handle)
1588c2ecf20Sopenharmony_ci			rb = rb->rb_right;
1598c2ecf20Sopenharmony_ci		else
1608c2ecf20Sopenharmony_ci			rb = rb->rb_left;
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	return NULL;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv,
1678c2ecf20Sopenharmony_ci				       struct dma_buf *dma_buf,
1688c2ecf20Sopenharmony_ci				       uint32_t *handle)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	struct rb_node *rb;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	rb = prime_fpriv->dmabufs.rb_node;
1738c2ecf20Sopenharmony_ci	while (rb) {
1748c2ecf20Sopenharmony_ci		struct drm_prime_member *member;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci		member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
1778c2ecf20Sopenharmony_ci		if (member->dma_buf == dma_buf) {
1788c2ecf20Sopenharmony_ci			*handle = member->handle;
1798c2ecf20Sopenharmony_ci			return 0;
1808c2ecf20Sopenharmony_ci		} else if (member->dma_buf < dma_buf) {
1818c2ecf20Sopenharmony_ci			rb = rb->rb_right;
1828c2ecf20Sopenharmony_ci		} else {
1838c2ecf20Sopenharmony_ci			rb = rb->rb_left;
1848c2ecf20Sopenharmony_ci		}
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	return -ENOENT;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_civoid drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
1918c2ecf20Sopenharmony_ci				 uint32_t handle)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	struct rb_node *rb;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	mutex_lock(&prime_fpriv->lock);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	rb = prime_fpriv->handles.rb_node;
1988c2ecf20Sopenharmony_ci	while (rb) {
1998c2ecf20Sopenharmony_ci		struct drm_prime_member *member;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		member = rb_entry(rb, struct drm_prime_member, handle_rb);
2028c2ecf20Sopenharmony_ci		if (member->handle == handle) {
2038c2ecf20Sopenharmony_ci			rb_erase(&member->handle_rb, &prime_fpriv->handles);
2048c2ecf20Sopenharmony_ci			rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci			dma_buf_put(member->dma_buf);
2078c2ecf20Sopenharmony_ci			kfree(member);
2088c2ecf20Sopenharmony_ci			break;
2098c2ecf20Sopenharmony_ci		} else if (member->handle < handle) {
2108c2ecf20Sopenharmony_ci			rb = rb->rb_right;
2118c2ecf20Sopenharmony_ci		} else {
2128c2ecf20Sopenharmony_ci			rb = rb->rb_left;
2138c2ecf20Sopenharmony_ci		}
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	mutex_unlock(&prime_fpriv->lock);
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_civoid drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	mutex_init(&prime_fpriv->lock);
2228c2ecf20Sopenharmony_ci	prime_fpriv->dmabufs = RB_ROOT;
2238c2ecf20Sopenharmony_ci	prime_fpriv->handles = RB_ROOT;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_civoid drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	/* by now drm_gem_release should've made sure the list is empty */
2298c2ecf20Sopenharmony_ci	WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci/**
2338c2ecf20Sopenharmony_ci * drm_gem_dmabuf_export - &dma_buf export implementation for GEM
2348c2ecf20Sopenharmony_ci * @dev: parent device for the exported dmabuf
2358c2ecf20Sopenharmony_ci * @exp_info: the export information used by dma_buf_export()
2368c2ecf20Sopenharmony_ci *
2378c2ecf20Sopenharmony_ci * This wraps dma_buf_export() for use by generic GEM drivers that are using
2388c2ecf20Sopenharmony_ci * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take
2398c2ecf20Sopenharmony_ci * a reference to the &drm_device and the exported &drm_gem_object (stored in
2408c2ecf20Sopenharmony_ci * &dma_buf_export_info.priv) which is released by drm_gem_dmabuf_release().
2418c2ecf20Sopenharmony_ci *
2428c2ecf20Sopenharmony_ci * Returns the new dmabuf.
2438c2ecf20Sopenharmony_ci */
2448c2ecf20Sopenharmony_cistruct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
2458c2ecf20Sopenharmony_ci				      struct dma_buf_export_info *exp_info)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = exp_info->priv;
2488c2ecf20Sopenharmony_ci	struct dma_buf *dma_buf;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	dma_buf = dma_buf_export(exp_info);
2518c2ecf20Sopenharmony_ci	if (IS_ERR(dma_buf))
2528c2ecf20Sopenharmony_ci		return dma_buf;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	drm_dev_get(dev);
2558c2ecf20Sopenharmony_ci	drm_gem_object_get(obj);
2568c2ecf20Sopenharmony_ci	dma_buf->file->f_mapping = obj->dev->anon_inode->i_mapping;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return dma_buf;
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_dmabuf_export);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci/**
2638c2ecf20Sopenharmony_ci * drm_gem_dmabuf_release - &dma_buf release implementation for GEM
2648c2ecf20Sopenharmony_ci * @dma_buf: buffer to be released
2658c2ecf20Sopenharmony_ci *
2668c2ecf20Sopenharmony_ci * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers
2678c2ecf20Sopenharmony_ci * must use this in their &dma_buf_ops structure as the release callback.
2688c2ecf20Sopenharmony_ci * drm_gem_dmabuf_release() should be used in conjunction with
2698c2ecf20Sopenharmony_ci * drm_gem_dmabuf_export().
2708c2ecf20Sopenharmony_ci */
2718c2ecf20Sopenharmony_civoid drm_gem_dmabuf_release(struct dma_buf *dma_buf)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = dma_buf->priv;
2748c2ecf20Sopenharmony_ci	struct drm_device *dev = obj->dev;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/* drop the reference on the export fd holds */
2778c2ecf20Sopenharmony_ci	drm_gem_object_put(obj);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	drm_dev_put(dev);
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_dmabuf_release);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci/**
2848c2ecf20Sopenharmony_ci * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
2858c2ecf20Sopenharmony_ci * @dev: dev to export the buffer from
2868c2ecf20Sopenharmony_ci * @file_priv: drm file-private structure
2878c2ecf20Sopenharmony_ci * @prime_fd: fd id of the dma-buf which should be imported
2888c2ecf20Sopenharmony_ci * @handle: pointer to storage for the handle of the imported buffer object
2898c2ecf20Sopenharmony_ci *
2908c2ecf20Sopenharmony_ci * This is the PRIME import function which must be used mandatorily by GEM
2918c2ecf20Sopenharmony_ci * drivers to ensure correct lifetime management of the underlying GEM object.
2928c2ecf20Sopenharmony_ci * The actual importing of GEM object from the dma-buf is done through the
2938c2ecf20Sopenharmony_ci * &drm_driver.gem_prime_import driver callback.
2948c2ecf20Sopenharmony_ci *
2958c2ecf20Sopenharmony_ci * Returns 0 on success or a negative error code on failure.
2968c2ecf20Sopenharmony_ci */
2978c2ecf20Sopenharmony_ciint drm_gem_prime_fd_to_handle(struct drm_device *dev,
2988c2ecf20Sopenharmony_ci			       struct drm_file *file_priv, int prime_fd,
2998c2ecf20Sopenharmony_ci			       uint32_t *handle)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	struct dma_buf *dma_buf;
3028c2ecf20Sopenharmony_ci	struct drm_gem_object *obj;
3038c2ecf20Sopenharmony_ci	int ret;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	dma_buf = dma_buf_get(prime_fd);
3068c2ecf20Sopenharmony_ci	if (IS_ERR(dma_buf))
3078c2ecf20Sopenharmony_ci		return PTR_ERR(dma_buf);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	mutex_lock(&file_priv->prime.lock);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	ret = drm_prime_lookup_buf_handle(&file_priv->prime,
3128c2ecf20Sopenharmony_ci			dma_buf, handle);
3138c2ecf20Sopenharmony_ci	if (ret == 0)
3148c2ecf20Sopenharmony_ci		goto out_put;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	/* never seen this one, need to import */
3178c2ecf20Sopenharmony_ci	mutex_lock(&dev->object_name_lock);
3188c2ecf20Sopenharmony_ci	if (dev->driver->gem_prime_import)
3198c2ecf20Sopenharmony_ci		obj = dev->driver->gem_prime_import(dev, dma_buf);
3208c2ecf20Sopenharmony_ci	else
3218c2ecf20Sopenharmony_ci		obj = drm_gem_prime_import(dev, dma_buf);
3228c2ecf20Sopenharmony_ci	if (IS_ERR(obj)) {
3238c2ecf20Sopenharmony_ci		ret = PTR_ERR(obj);
3248c2ecf20Sopenharmony_ci		goto out_unlock;
3258c2ecf20Sopenharmony_ci	}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	if (obj->dma_buf) {
3288c2ecf20Sopenharmony_ci		WARN_ON(obj->dma_buf != dma_buf);
3298c2ecf20Sopenharmony_ci	} else {
3308c2ecf20Sopenharmony_ci		obj->dma_buf = dma_buf;
3318c2ecf20Sopenharmony_ci		get_dma_buf(dma_buf);
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	/* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
3358c2ecf20Sopenharmony_ci	ret = drm_gem_handle_create_tail(file_priv, obj, handle);
3368c2ecf20Sopenharmony_ci	drm_gem_object_put(obj);
3378c2ecf20Sopenharmony_ci	if (ret)
3388c2ecf20Sopenharmony_ci		goto out_put;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	ret = drm_prime_add_buf_handle(&file_priv->prime,
3418c2ecf20Sopenharmony_ci			dma_buf, *handle);
3428c2ecf20Sopenharmony_ci	mutex_unlock(&file_priv->prime.lock);
3438c2ecf20Sopenharmony_ci	if (ret)
3448c2ecf20Sopenharmony_ci		goto fail;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	dma_buf_put(dma_buf);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	return 0;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cifail:
3518c2ecf20Sopenharmony_ci	/* hmm, if driver attached, we are relying on the free-object path
3528c2ecf20Sopenharmony_ci	 * to detach.. which seems ok..
3538c2ecf20Sopenharmony_ci	 */
3548c2ecf20Sopenharmony_ci	drm_gem_handle_delete(file_priv, *handle);
3558c2ecf20Sopenharmony_ci	dma_buf_put(dma_buf);
3568c2ecf20Sopenharmony_ci	return ret;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ciout_unlock:
3598c2ecf20Sopenharmony_ci	mutex_unlock(&dev->object_name_lock);
3608c2ecf20Sopenharmony_ciout_put:
3618c2ecf20Sopenharmony_ci	mutex_unlock(&file_priv->prime.lock);
3628c2ecf20Sopenharmony_ci	dma_buf_put(dma_buf);
3638c2ecf20Sopenharmony_ci	return ret;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ciint drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
3688c2ecf20Sopenharmony_ci				 struct drm_file *file_priv)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	struct drm_prime_handle *args = data;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	if (!dev->driver->prime_fd_to_handle)
3738c2ecf20Sopenharmony_ci		return -ENOSYS;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	return dev->driver->prime_fd_to_handle(dev, file_priv,
3768c2ecf20Sopenharmony_ci			args->fd, &args->handle);
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic struct dma_buf *export_and_register_object(struct drm_device *dev,
3808c2ecf20Sopenharmony_ci						  struct drm_gem_object *obj,
3818c2ecf20Sopenharmony_ci						  uint32_t flags)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	struct dma_buf *dmabuf;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	/* prevent races with concurrent gem_close. */
3868c2ecf20Sopenharmony_ci	if (obj->handle_count == 0) {
3878c2ecf20Sopenharmony_ci		dmabuf = ERR_PTR(-ENOENT);
3888c2ecf20Sopenharmony_ci		return dmabuf;
3898c2ecf20Sopenharmony_ci	}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	if (obj->funcs && obj->funcs->export)
3928c2ecf20Sopenharmony_ci		dmabuf = obj->funcs->export(obj, flags);
3938c2ecf20Sopenharmony_ci	else if (dev->driver->gem_prime_export)
3948c2ecf20Sopenharmony_ci		dmabuf = dev->driver->gem_prime_export(obj, flags);
3958c2ecf20Sopenharmony_ci	else
3968c2ecf20Sopenharmony_ci		dmabuf = drm_gem_prime_export(obj, flags);
3978c2ecf20Sopenharmony_ci	if (IS_ERR(dmabuf)) {
3988c2ecf20Sopenharmony_ci		/* normally the created dma-buf takes ownership of the ref,
3998c2ecf20Sopenharmony_ci		 * but if that fails then drop the ref
4008c2ecf20Sopenharmony_ci		 */
4018c2ecf20Sopenharmony_ci		return dmabuf;
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	/*
4058c2ecf20Sopenharmony_ci	 * Note that callers do not need to clean up the export cache
4068c2ecf20Sopenharmony_ci	 * since the check for obj->handle_count guarantees that someone
4078c2ecf20Sopenharmony_ci	 * will clean it up.
4088c2ecf20Sopenharmony_ci	 */
4098c2ecf20Sopenharmony_ci	obj->dma_buf = dmabuf;
4108c2ecf20Sopenharmony_ci	get_dma_buf(obj->dma_buf);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	return dmabuf;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci/**
4168c2ecf20Sopenharmony_ci * drm_gem_prime_handle_to_fd - PRIME export function for GEM drivers
4178c2ecf20Sopenharmony_ci * @dev: dev to export the buffer from
4188c2ecf20Sopenharmony_ci * @file_priv: drm file-private structure
4198c2ecf20Sopenharmony_ci * @handle: buffer handle to export
4208c2ecf20Sopenharmony_ci * @flags: flags like DRM_CLOEXEC
4218c2ecf20Sopenharmony_ci * @prime_fd: pointer to storage for the fd id of the create dma-buf
4228c2ecf20Sopenharmony_ci *
4238c2ecf20Sopenharmony_ci * This is the PRIME export function which must be used mandatorily by GEM
4248c2ecf20Sopenharmony_ci * drivers to ensure correct lifetime management of the underlying GEM object.
4258c2ecf20Sopenharmony_ci * The actual exporting from GEM object to a dma-buf is done through the
4268c2ecf20Sopenharmony_ci * &drm_driver.gem_prime_export driver callback.
4278c2ecf20Sopenharmony_ci */
4288c2ecf20Sopenharmony_ciint drm_gem_prime_handle_to_fd(struct drm_device *dev,
4298c2ecf20Sopenharmony_ci			       struct drm_file *file_priv, uint32_t handle,
4308c2ecf20Sopenharmony_ci			       uint32_t flags,
4318c2ecf20Sopenharmony_ci			       int *prime_fd)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	struct drm_gem_object *obj;
4348c2ecf20Sopenharmony_ci	int ret = 0;
4358c2ecf20Sopenharmony_ci	struct dma_buf *dmabuf;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	mutex_lock(&file_priv->prime.lock);
4388c2ecf20Sopenharmony_ci	obj = drm_gem_object_lookup(file_priv, handle);
4398c2ecf20Sopenharmony_ci	if (!obj)  {
4408c2ecf20Sopenharmony_ci		ret = -ENOENT;
4418c2ecf20Sopenharmony_ci		goto out_unlock;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	dmabuf = drm_prime_lookup_buf_by_handle(&file_priv->prime, handle);
4458c2ecf20Sopenharmony_ci	if (dmabuf) {
4468c2ecf20Sopenharmony_ci		get_dma_buf(dmabuf);
4478c2ecf20Sopenharmony_ci		goto out_have_handle;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	mutex_lock(&dev->object_name_lock);
4518c2ecf20Sopenharmony_ci	/* re-export the original imported object */
4528c2ecf20Sopenharmony_ci	if (obj->import_attach) {
4538c2ecf20Sopenharmony_ci		dmabuf = obj->import_attach->dmabuf;
4548c2ecf20Sopenharmony_ci		get_dma_buf(dmabuf);
4558c2ecf20Sopenharmony_ci		goto out_have_obj;
4568c2ecf20Sopenharmony_ci	}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	if (obj->dma_buf) {
4598c2ecf20Sopenharmony_ci		get_dma_buf(obj->dma_buf);
4608c2ecf20Sopenharmony_ci		dmabuf = obj->dma_buf;
4618c2ecf20Sopenharmony_ci		goto out_have_obj;
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	dmabuf = export_and_register_object(dev, obj, flags);
4658c2ecf20Sopenharmony_ci	if (IS_ERR(dmabuf)) {
4668c2ecf20Sopenharmony_ci		/* normally the created dma-buf takes ownership of the ref,
4678c2ecf20Sopenharmony_ci		 * but if that fails then drop the ref
4688c2ecf20Sopenharmony_ci		 */
4698c2ecf20Sopenharmony_ci		ret = PTR_ERR(dmabuf);
4708c2ecf20Sopenharmony_ci		mutex_unlock(&dev->object_name_lock);
4718c2ecf20Sopenharmony_ci		goto out;
4728c2ecf20Sopenharmony_ci	}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ciout_have_obj:
4758c2ecf20Sopenharmony_ci	/*
4768c2ecf20Sopenharmony_ci	 * If we've exported this buffer then cheat and add it to the import list
4778c2ecf20Sopenharmony_ci	 * so we get the correct handle back. We must do this under the
4788c2ecf20Sopenharmony_ci	 * protection of dev->object_name_lock to ensure that a racing gem close
4798c2ecf20Sopenharmony_ci	 * ioctl doesn't miss to remove this buffer handle from the cache.
4808c2ecf20Sopenharmony_ci	 */
4818c2ecf20Sopenharmony_ci	ret = drm_prime_add_buf_handle(&file_priv->prime,
4828c2ecf20Sopenharmony_ci				       dmabuf, handle);
4838c2ecf20Sopenharmony_ci	mutex_unlock(&dev->object_name_lock);
4848c2ecf20Sopenharmony_ci	if (ret)
4858c2ecf20Sopenharmony_ci		goto fail_put_dmabuf;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ciout_have_handle:
4888c2ecf20Sopenharmony_ci	ret = dma_buf_fd(dmabuf, flags);
4898c2ecf20Sopenharmony_ci	/*
4908c2ecf20Sopenharmony_ci	 * We must _not_ remove the buffer from the handle cache since the newly
4918c2ecf20Sopenharmony_ci	 * created dma buf is already linked in the global obj->dma_buf pointer,
4928c2ecf20Sopenharmony_ci	 * and that is invariant as long as a userspace gem handle exists.
4938c2ecf20Sopenharmony_ci	 * Closing the handle will clean out the cache anyway, so we don't leak.
4948c2ecf20Sopenharmony_ci	 */
4958c2ecf20Sopenharmony_ci	if (ret < 0) {
4968c2ecf20Sopenharmony_ci		goto fail_put_dmabuf;
4978c2ecf20Sopenharmony_ci	} else {
4988c2ecf20Sopenharmony_ci		*prime_fd = ret;
4998c2ecf20Sopenharmony_ci		ret = 0;
5008c2ecf20Sopenharmony_ci	}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	goto out;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_cifail_put_dmabuf:
5058c2ecf20Sopenharmony_ci	dma_buf_put(dmabuf);
5068c2ecf20Sopenharmony_ciout:
5078c2ecf20Sopenharmony_ci	drm_gem_object_put(obj);
5088c2ecf20Sopenharmony_ciout_unlock:
5098c2ecf20Sopenharmony_ci	mutex_unlock(&file_priv->prime.lock);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	return ret;
5128c2ecf20Sopenharmony_ci}
5138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ciint drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
5168c2ecf20Sopenharmony_ci				 struct drm_file *file_priv)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	struct drm_prime_handle *args = data;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	if (!dev->driver->prime_handle_to_fd)
5218c2ecf20Sopenharmony_ci		return -ENOSYS;
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	/* check flags are valid */
5248c2ecf20Sopenharmony_ci	if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR))
5258c2ecf20Sopenharmony_ci		return -EINVAL;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	return dev->driver->prime_handle_to_fd(dev, file_priv,
5288c2ecf20Sopenharmony_ci			args->handle, args->flags, &args->fd);
5298c2ecf20Sopenharmony_ci}
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci/**
5328c2ecf20Sopenharmony_ci * DOC: PRIME Helpers
5338c2ecf20Sopenharmony_ci *
5348c2ecf20Sopenharmony_ci * Drivers can implement &drm_gem_object_funcs.export and
5358c2ecf20Sopenharmony_ci * &drm_driver.gem_prime_import in terms of simpler APIs by using the helper
5368c2ecf20Sopenharmony_ci * functions drm_gem_prime_export() and drm_gem_prime_import(). These functions
5378c2ecf20Sopenharmony_ci * implement dma-buf support in terms of some lower-level helpers, which are
5388c2ecf20Sopenharmony_ci * again exported for drivers to use individually:
5398c2ecf20Sopenharmony_ci *
5408c2ecf20Sopenharmony_ci * Exporting buffers
5418c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~
5428c2ecf20Sopenharmony_ci *
5438c2ecf20Sopenharmony_ci * Optional pinning of buffers is handled at dma-buf attach and detach time in
5448c2ecf20Sopenharmony_ci * drm_gem_map_attach() and drm_gem_map_detach(). Backing storage itself is
5458c2ecf20Sopenharmony_ci * handled by drm_gem_map_dma_buf() and drm_gem_unmap_dma_buf(), which relies on
5468c2ecf20Sopenharmony_ci * &drm_gem_object_funcs.get_sg_table.
5478c2ecf20Sopenharmony_ci *
5488c2ecf20Sopenharmony_ci * For kernel-internal access there's drm_gem_dmabuf_vmap() and
5498c2ecf20Sopenharmony_ci * drm_gem_dmabuf_vunmap(). Userspace mmap support is provided by
5508c2ecf20Sopenharmony_ci * drm_gem_dmabuf_mmap().
5518c2ecf20Sopenharmony_ci *
5528c2ecf20Sopenharmony_ci * Note that these export helpers can only be used if the underlying backing
5538c2ecf20Sopenharmony_ci * storage is fully coherent and either permanently pinned, or it is safe to pin
5548c2ecf20Sopenharmony_ci * it indefinitely.
5558c2ecf20Sopenharmony_ci *
5568c2ecf20Sopenharmony_ci * FIXME: The underlying helper functions are named rather inconsistently.
5578c2ecf20Sopenharmony_ci *
5588c2ecf20Sopenharmony_ci * Exporting buffers
5598c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~
5608c2ecf20Sopenharmony_ci *
5618c2ecf20Sopenharmony_ci * Importing dma-bufs using drm_gem_prime_import() relies on
5628c2ecf20Sopenharmony_ci * &drm_driver.gem_prime_import_sg_table.
5638c2ecf20Sopenharmony_ci *
5648c2ecf20Sopenharmony_ci * Note that similarly to the export helpers this permanently pins the
5658c2ecf20Sopenharmony_ci * underlying backing storage. Which is ok for scanout, but is not the best
5668c2ecf20Sopenharmony_ci * option for sharing lots of buffers for rendering.
5678c2ecf20Sopenharmony_ci */
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci/**
5708c2ecf20Sopenharmony_ci * drm_gem_map_attach - dma_buf attach implementation for GEM
5718c2ecf20Sopenharmony_ci * @dma_buf: buffer to attach device to
5728c2ecf20Sopenharmony_ci * @attach: buffer attachment data
5738c2ecf20Sopenharmony_ci *
5748c2ecf20Sopenharmony_ci * Calls &drm_gem_object_funcs.pin for device specific handling. This can be
5758c2ecf20Sopenharmony_ci * used as the &dma_buf_ops.attach callback. Must be used together with
5768c2ecf20Sopenharmony_ci * drm_gem_map_detach().
5778c2ecf20Sopenharmony_ci *
5788c2ecf20Sopenharmony_ci * Returns 0 on success, negative error code on failure.
5798c2ecf20Sopenharmony_ci */
5808c2ecf20Sopenharmony_ciint drm_gem_map_attach(struct dma_buf *dma_buf,
5818c2ecf20Sopenharmony_ci		       struct dma_buf_attachment *attach)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = dma_buf->priv;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	return drm_gem_pin(obj);
5868c2ecf20Sopenharmony_ci}
5878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_map_attach);
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci/**
5908c2ecf20Sopenharmony_ci * drm_gem_map_detach - dma_buf detach implementation for GEM
5918c2ecf20Sopenharmony_ci * @dma_buf: buffer to detach from
5928c2ecf20Sopenharmony_ci * @attach: attachment to be detached
5938c2ecf20Sopenharmony_ci *
5948c2ecf20Sopenharmony_ci * Calls &drm_gem_object_funcs.pin for device specific handling.  Cleans up
5958c2ecf20Sopenharmony_ci * &dma_buf_attachment from drm_gem_map_attach(). This can be used as the
5968c2ecf20Sopenharmony_ci * &dma_buf_ops.detach callback.
5978c2ecf20Sopenharmony_ci */
5988c2ecf20Sopenharmony_civoid drm_gem_map_detach(struct dma_buf *dma_buf,
5998c2ecf20Sopenharmony_ci			struct dma_buf_attachment *attach)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = dma_buf->priv;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	drm_gem_unpin(obj);
6048c2ecf20Sopenharmony_ci}
6058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_map_detach);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci/**
6088c2ecf20Sopenharmony_ci * drm_gem_map_dma_buf - map_dma_buf implementation for GEM
6098c2ecf20Sopenharmony_ci * @attach: attachment whose scatterlist is to be returned
6108c2ecf20Sopenharmony_ci * @dir: direction of DMA transfer
6118c2ecf20Sopenharmony_ci *
6128c2ecf20Sopenharmony_ci * Calls &drm_gem_object_funcs.get_sg_table and then maps the scatterlist. This
6138c2ecf20Sopenharmony_ci * can be used as the &dma_buf_ops.map_dma_buf callback. Should be used together
6148c2ecf20Sopenharmony_ci * with drm_gem_unmap_dma_buf().
6158c2ecf20Sopenharmony_ci *
6168c2ecf20Sopenharmony_ci * Returns:sg_table containing the scatterlist to be returned; returns ERR_PTR
6178c2ecf20Sopenharmony_ci * on error. May return -EINTR if it is interrupted by a signal.
6188c2ecf20Sopenharmony_ci */
6198c2ecf20Sopenharmony_cistruct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
6208c2ecf20Sopenharmony_ci				     enum dma_data_direction dir)
6218c2ecf20Sopenharmony_ci{
6228c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = attach->dmabuf->priv;
6238c2ecf20Sopenharmony_ci	struct sg_table *sgt;
6248c2ecf20Sopenharmony_ci	int ret;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	if (WARN_ON(dir == DMA_NONE))
6278c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (obj->funcs)
6308c2ecf20Sopenharmony_ci		sgt = obj->funcs->get_sg_table(obj);
6318c2ecf20Sopenharmony_ci	else
6328c2ecf20Sopenharmony_ci		sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	ret = dma_map_sgtable(attach->dev, sgt, dir,
6358c2ecf20Sopenharmony_ci			      DMA_ATTR_SKIP_CPU_SYNC);
6368c2ecf20Sopenharmony_ci	if (ret) {
6378c2ecf20Sopenharmony_ci		sg_free_table(sgt);
6388c2ecf20Sopenharmony_ci		kfree(sgt);
6398c2ecf20Sopenharmony_ci		sgt = ERR_PTR(ret);
6408c2ecf20Sopenharmony_ci	}
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	return sgt;
6438c2ecf20Sopenharmony_ci}
6448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_map_dma_buf);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci/**
6478c2ecf20Sopenharmony_ci * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM
6488c2ecf20Sopenharmony_ci * @attach: attachment to unmap buffer from
6498c2ecf20Sopenharmony_ci * @sgt: scatterlist info of the buffer to unmap
6508c2ecf20Sopenharmony_ci * @dir: direction of DMA transfer
6518c2ecf20Sopenharmony_ci *
6528c2ecf20Sopenharmony_ci * This can be used as the &dma_buf_ops.unmap_dma_buf callback.
6538c2ecf20Sopenharmony_ci */
6548c2ecf20Sopenharmony_civoid drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
6558c2ecf20Sopenharmony_ci			   struct sg_table *sgt,
6568c2ecf20Sopenharmony_ci			   enum dma_data_direction dir)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	if (!sgt)
6598c2ecf20Sopenharmony_ci		return;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	dma_unmap_sgtable(attach->dev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC);
6628c2ecf20Sopenharmony_ci	sg_free_table(sgt);
6638c2ecf20Sopenharmony_ci	kfree(sgt);
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_unmap_dma_buf);
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci/**
6688c2ecf20Sopenharmony_ci * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM
6698c2ecf20Sopenharmony_ci * @dma_buf: buffer to be mapped
6708c2ecf20Sopenharmony_ci *
6718c2ecf20Sopenharmony_ci * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap
6728c2ecf20Sopenharmony_ci * callback. Calls into &drm_gem_object_funcs.vmap for device specific handling.
6738c2ecf20Sopenharmony_ci *
6748c2ecf20Sopenharmony_ci * Returns the kernel virtual address or NULL on failure.
6758c2ecf20Sopenharmony_ci */
6768c2ecf20Sopenharmony_civoid *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
6778c2ecf20Sopenharmony_ci{
6788c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = dma_buf->priv;
6798c2ecf20Sopenharmony_ci	void *vaddr;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	vaddr = drm_gem_vmap(obj);
6828c2ecf20Sopenharmony_ci	if (IS_ERR(vaddr))
6838c2ecf20Sopenharmony_ci		vaddr = NULL;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	return vaddr;
6868c2ecf20Sopenharmony_ci}
6878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_dmabuf_vmap);
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci/**
6908c2ecf20Sopenharmony_ci * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM
6918c2ecf20Sopenharmony_ci * @dma_buf: buffer to be unmapped
6928c2ecf20Sopenharmony_ci * @vaddr: the virtual address of the buffer
6938c2ecf20Sopenharmony_ci *
6948c2ecf20Sopenharmony_ci * Releases a kernel virtual mapping. This can be used as the
6958c2ecf20Sopenharmony_ci * &dma_buf_ops.vunmap callback. Calls into &drm_gem_object_funcs.vunmap for device specific handling.
6968c2ecf20Sopenharmony_ci */
6978c2ecf20Sopenharmony_civoid drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
6988c2ecf20Sopenharmony_ci{
6998c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = dma_buf->priv;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	drm_gem_vunmap(obj, vaddr);
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci/**
7068c2ecf20Sopenharmony_ci * drm_gem_prime_mmap - PRIME mmap function for GEM drivers
7078c2ecf20Sopenharmony_ci * @obj: GEM object
7088c2ecf20Sopenharmony_ci * @vma: Virtual address range
7098c2ecf20Sopenharmony_ci *
7108c2ecf20Sopenharmony_ci * This function sets up a userspace mapping for PRIME exported buffers using
7118c2ecf20Sopenharmony_ci * the same codepath that is used for regular GEM buffer mapping on the DRM fd.
7128c2ecf20Sopenharmony_ci * The fake GEM offset is added to vma->vm_pgoff and &drm_driver->fops->mmap is
7138c2ecf20Sopenharmony_ci * called to set up the mapping.
7148c2ecf20Sopenharmony_ci *
7158c2ecf20Sopenharmony_ci * Drivers can use this as their &drm_driver.gem_prime_mmap callback.
7168c2ecf20Sopenharmony_ci */
7178c2ecf20Sopenharmony_ciint drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
7188c2ecf20Sopenharmony_ci{
7198c2ecf20Sopenharmony_ci	struct drm_file *priv;
7208c2ecf20Sopenharmony_ci	struct file *fil;
7218c2ecf20Sopenharmony_ci	int ret;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	/* Add the fake offset */
7248c2ecf20Sopenharmony_ci	vma->vm_pgoff += drm_vma_node_start(&obj->vma_node);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	if (obj->funcs && obj->funcs->mmap) {
7278c2ecf20Sopenharmony_ci		ret = obj->funcs->mmap(obj, vma);
7288c2ecf20Sopenharmony_ci		if (ret)
7298c2ecf20Sopenharmony_ci			return ret;
7308c2ecf20Sopenharmony_ci		vma->vm_private_data = obj;
7318c2ecf20Sopenharmony_ci		drm_gem_object_get(obj);
7328c2ecf20Sopenharmony_ci		return 0;
7338c2ecf20Sopenharmony_ci	}
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
7368c2ecf20Sopenharmony_ci	fil = kzalloc(sizeof(*fil), GFP_KERNEL);
7378c2ecf20Sopenharmony_ci	if (!priv || !fil) {
7388c2ecf20Sopenharmony_ci		ret = -ENOMEM;
7398c2ecf20Sopenharmony_ci		goto out;
7408c2ecf20Sopenharmony_ci	}
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	/* Used by drm_gem_mmap() to lookup the GEM object */
7438c2ecf20Sopenharmony_ci	priv->minor = obj->dev->primary;
7448c2ecf20Sopenharmony_ci	fil->private_data = priv;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	ret = drm_vma_node_allow(&obj->vma_node, priv);
7478c2ecf20Sopenharmony_ci	if (ret)
7488c2ecf20Sopenharmony_ci		goto out;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	ret = obj->dev->driver->fops->mmap(fil, vma);
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	drm_vma_node_revoke(&obj->vma_node, priv);
7538c2ecf20Sopenharmony_ciout:
7548c2ecf20Sopenharmony_ci	kfree(priv);
7558c2ecf20Sopenharmony_ci	kfree(fil);
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	return ret;
7588c2ecf20Sopenharmony_ci}
7598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_prime_mmap);
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci/**
7628c2ecf20Sopenharmony_ci * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM
7638c2ecf20Sopenharmony_ci * @dma_buf: buffer to be mapped
7648c2ecf20Sopenharmony_ci * @vma: virtual address range
7658c2ecf20Sopenharmony_ci *
7668c2ecf20Sopenharmony_ci * Provides memory mapping for the buffer. This can be used as the
7678c2ecf20Sopenharmony_ci * &dma_buf_ops.mmap callback. It just forwards to &drm_driver.gem_prime_mmap,
7688c2ecf20Sopenharmony_ci * which should be set to drm_gem_prime_mmap().
7698c2ecf20Sopenharmony_ci *
7708c2ecf20Sopenharmony_ci * FIXME: There's really no point to this wrapper, drivers which need anything
7718c2ecf20Sopenharmony_ci * else but drm_gem_prime_mmap can roll their own &dma_buf_ops.mmap callback.
7728c2ecf20Sopenharmony_ci *
7738c2ecf20Sopenharmony_ci * Returns 0 on success or a negative error code on failure.
7748c2ecf20Sopenharmony_ci */
7758c2ecf20Sopenharmony_ciint drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
7768c2ecf20Sopenharmony_ci{
7778c2ecf20Sopenharmony_ci	struct drm_gem_object *obj = dma_buf->priv;
7788c2ecf20Sopenharmony_ci	struct drm_device *dev = obj->dev;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	if (!dev->driver->gem_prime_mmap)
7818c2ecf20Sopenharmony_ci		return -ENOSYS;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	return dev->driver->gem_prime_mmap(obj, vma);
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_dmabuf_mmap);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_cistatic const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
7888c2ecf20Sopenharmony_ci	.cache_sgt_mapping = true,
7898c2ecf20Sopenharmony_ci	.attach = drm_gem_map_attach,
7908c2ecf20Sopenharmony_ci	.detach = drm_gem_map_detach,
7918c2ecf20Sopenharmony_ci	.map_dma_buf = drm_gem_map_dma_buf,
7928c2ecf20Sopenharmony_ci	.unmap_dma_buf = drm_gem_unmap_dma_buf,
7938c2ecf20Sopenharmony_ci	.release = drm_gem_dmabuf_release,
7948c2ecf20Sopenharmony_ci	.mmap = drm_gem_dmabuf_mmap,
7958c2ecf20Sopenharmony_ci	.vmap = drm_gem_dmabuf_vmap,
7968c2ecf20Sopenharmony_ci	.vunmap = drm_gem_dmabuf_vunmap,
7978c2ecf20Sopenharmony_ci};
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci/**
8008c2ecf20Sopenharmony_ci * drm_prime_pages_to_sg - converts a page array into an sg list
8018c2ecf20Sopenharmony_ci * @dev: DRM device
8028c2ecf20Sopenharmony_ci * @pages: pointer to the array of page pointers to convert
8038c2ecf20Sopenharmony_ci * @nr_pages: length of the page vector
8048c2ecf20Sopenharmony_ci *
8058c2ecf20Sopenharmony_ci * This helper creates an sg table object from a set of pages
8068c2ecf20Sopenharmony_ci * the driver is responsible for mapping the pages into the
8078c2ecf20Sopenharmony_ci * importers address space for use with dma_buf itself.
8088c2ecf20Sopenharmony_ci *
8098c2ecf20Sopenharmony_ci * This is useful for implementing &drm_gem_object_funcs.get_sg_table.
8108c2ecf20Sopenharmony_ci */
8118c2ecf20Sopenharmony_cistruct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
8128c2ecf20Sopenharmony_ci				       struct page **pages, unsigned int nr_pages)
8138c2ecf20Sopenharmony_ci{
8148c2ecf20Sopenharmony_ci	struct sg_table *sg;
8158c2ecf20Sopenharmony_ci	struct scatterlist *sge;
8168c2ecf20Sopenharmony_ci	size_t max_segment = 0;
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
8198c2ecf20Sopenharmony_ci	if (!sg)
8208c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	if (dev)
8238c2ecf20Sopenharmony_ci		max_segment = dma_max_mapping_size(dev->dev);
8248c2ecf20Sopenharmony_ci	if (max_segment == 0 || max_segment > SCATTERLIST_MAX_SEGMENT)
8258c2ecf20Sopenharmony_ci		max_segment = SCATTERLIST_MAX_SEGMENT;
8268c2ecf20Sopenharmony_ci	sge = __sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
8278c2ecf20Sopenharmony_ci					  nr_pages << PAGE_SHIFT,
8288c2ecf20Sopenharmony_ci					  max_segment,
8298c2ecf20Sopenharmony_ci					  NULL, 0, GFP_KERNEL);
8308c2ecf20Sopenharmony_ci	if (IS_ERR(sge)) {
8318c2ecf20Sopenharmony_ci		kfree(sg);
8328c2ecf20Sopenharmony_ci		sg = ERR_CAST(sge);
8338c2ecf20Sopenharmony_ci	}
8348c2ecf20Sopenharmony_ci	return sg;
8358c2ecf20Sopenharmony_ci}
8368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_prime_pages_to_sg);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci/**
8398c2ecf20Sopenharmony_ci * drm_prime_get_contiguous_size - returns the contiguous size of the buffer
8408c2ecf20Sopenharmony_ci * @sgt: sg_table describing the buffer to check
8418c2ecf20Sopenharmony_ci *
8428c2ecf20Sopenharmony_ci * This helper calculates the contiguous size in the DMA address space
8438c2ecf20Sopenharmony_ci * of the the buffer described by the provided sg_table.
8448c2ecf20Sopenharmony_ci *
8458c2ecf20Sopenharmony_ci * This is useful for implementing
8468c2ecf20Sopenharmony_ci * &drm_gem_object_funcs.gem_prime_import_sg_table.
8478c2ecf20Sopenharmony_ci */
8488c2ecf20Sopenharmony_ciunsigned long drm_prime_get_contiguous_size(struct sg_table *sgt)
8498c2ecf20Sopenharmony_ci{
8508c2ecf20Sopenharmony_ci	dma_addr_t expected = sg_dma_address(sgt->sgl);
8518c2ecf20Sopenharmony_ci	struct scatterlist *sg;
8528c2ecf20Sopenharmony_ci	unsigned long size = 0;
8538c2ecf20Sopenharmony_ci	int i;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	for_each_sgtable_dma_sg(sgt, sg, i) {
8568c2ecf20Sopenharmony_ci		unsigned int len = sg_dma_len(sg);
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci		if (!len)
8598c2ecf20Sopenharmony_ci			break;
8608c2ecf20Sopenharmony_ci		if (sg_dma_address(sg) != expected)
8618c2ecf20Sopenharmony_ci			break;
8628c2ecf20Sopenharmony_ci		expected += len;
8638c2ecf20Sopenharmony_ci		size += len;
8648c2ecf20Sopenharmony_ci	}
8658c2ecf20Sopenharmony_ci	return size;
8668c2ecf20Sopenharmony_ci}
8678c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_prime_get_contiguous_size);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci/**
8708c2ecf20Sopenharmony_ci * drm_gem_prime_export - helper library implementation of the export callback
8718c2ecf20Sopenharmony_ci * @obj: GEM object to export
8728c2ecf20Sopenharmony_ci * @flags: flags like DRM_CLOEXEC and DRM_RDWR
8738c2ecf20Sopenharmony_ci *
8748c2ecf20Sopenharmony_ci * This is the implementation of the &drm_gem_object_funcs.export functions for GEM drivers
8758c2ecf20Sopenharmony_ci * using the PRIME helpers. It is used as the default in
8768c2ecf20Sopenharmony_ci * drm_gem_prime_handle_to_fd().
8778c2ecf20Sopenharmony_ci */
8788c2ecf20Sopenharmony_cistruct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
8798c2ecf20Sopenharmony_ci				     int flags)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	struct drm_device *dev = obj->dev;
8828c2ecf20Sopenharmony_ci	struct dma_buf_export_info exp_info = {
8838c2ecf20Sopenharmony_ci		.exp_name = KBUILD_MODNAME, /* white lie for debug */
8848c2ecf20Sopenharmony_ci		.owner = dev->driver->fops->owner,
8858c2ecf20Sopenharmony_ci		.ops = &drm_gem_prime_dmabuf_ops,
8868c2ecf20Sopenharmony_ci		.size = obj->size,
8878c2ecf20Sopenharmony_ci		.flags = flags,
8888c2ecf20Sopenharmony_ci		.priv = obj,
8898c2ecf20Sopenharmony_ci		.resv = obj->resv,
8908c2ecf20Sopenharmony_ci	};
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	return drm_gem_dmabuf_export(dev, &exp_info);
8938c2ecf20Sopenharmony_ci}
8948c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_prime_export);
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci/**
8978c2ecf20Sopenharmony_ci * drm_gem_prime_import_dev - core implementation of the import callback
8988c2ecf20Sopenharmony_ci * @dev: drm_device to import into
8998c2ecf20Sopenharmony_ci * @dma_buf: dma-buf object to import
9008c2ecf20Sopenharmony_ci * @attach_dev: struct device to dma_buf attach
9018c2ecf20Sopenharmony_ci *
9028c2ecf20Sopenharmony_ci * This is the core of drm_gem_prime_import(). It's designed to be called by
9038c2ecf20Sopenharmony_ci * drivers who want to use a different device structure than &drm_device.dev for
9048c2ecf20Sopenharmony_ci * attaching via dma_buf. This function calls
9058c2ecf20Sopenharmony_ci * &drm_driver.gem_prime_import_sg_table internally.
9068c2ecf20Sopenharmony_ci *
9078c2ecf20Sopenharmony_ci * Drivers must arrange to call drm_prime_gem_destroy() from their
9088c2ecf20Sopenharmony_ci * &drm_gem_object_funcs.free hook when using this function.
9098c2ecf20Sopenharmony_ci */
9108c2ecf20Sopenharmony_cistruct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
9118c2ecf20Sopenharmony_ci					    struct dma_buf *dma_buf,
9128c2ecf20Sopenharmony_ci					    struct device *attach_dev)
9138c2ecf20Sopenharmony_ci{
9148c2ecf20Sopenharmony_ci	struct dma_buf_attachment *attach;
9158c2ecf20Sopenharmony_ci	struct sg_table *sgt;
9168c2ecf20Sopenharmony_ci	struct drm_gem_object *obj;
9178c2ecf20Sopenharmony_ci	int ret;
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	if (dma_buf->ops == &drm_gem_prime_dmabuf_ops) {
9208c2ecf20Sopenharmony_ci		obj = dma_buf->priv;
9218c2ecf20Sopenharmony_ci		if (obj->dev == dev) {
9228c2ecf20Sopenharmony_ci			/*
9238c2ecf20Sopenharmony_ci			 * Importing dmabuf exported from out own gem increases
9248c2ecf20Sopenharmony_ci			 * refcount on gem itself instead of f_count of dmabuf.
9258c2ecf20Sopenharmony_ci			 */
9268c2ecf20Sopenharmony_ci			drm_gem_object_get(obj);
9278c2ecf20Sopenharmony_ci			return obj;
9288c2ecf20Sopenharmony_ci		}
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	if (!dev->driver->gem_prime_import_sg_table)
9328c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	attach = dma_buf_attach(dma_buf, attach_dev);
9358c2ecf20Sopenharmony_ci	if (IS_ERR(attach))
9368c2ecf20Sopenharmony_ci		return ERR_CAST(attach);
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	get_dma_buf(dma_buf);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
9418c2ecf20Sopenharmony_ci	if (IS_ERR(sgt)) {
9428c2ecf20Sopenharmony_ci		ret = PTR_ERR(sgt);
9438c2ecf20Sopenharmony_ci		goto fail_detach;
9448c2ecf20Sopenharmony_ci	}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	obj = dev->driver->gem_prime_import_sg_table(dev, attach, sgt);
9478c2ecf20Sopenharmony_ci	if (IS_ERR(obj)) {
9488c2ecf20Sopenharmony_ci		ret = PTR_ERR(obj);
9498c2ecf20Sopenharmony_ci		goto fail_unmap;
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	obj->import_attach = attach;
9538c2ecf20Sopenharmony_ci	obj->resv = dma_buf->resv;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	return obj;
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_cifail_unmap:
9588c2ecf20Sopenharmony_ci	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
9598c2ecf20Sopenharmony_cifail_detach:
9608c2ecf20Sopenharmony_ci	dma_buf_detach(dma_buf, attach);
9618c2ecf20Sopenharmony_ci	dma_buf_put(dma_buf);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	return ERR_PTR(ret);
9648c2ecf20Sopenharmony_ci}
9658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_prime_import_dev);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci/**
9688c2ecf20Sopenharmony_ci * drm_gem_prime_import - helper library implementation of the import callback
9698c2ecf20Sopenharmony_ci * @dev: drm_device to import into
9708c2ecf20Sopenharmony_ci * @dma_buf: dma-buf object to import
9718c2ecf20Sopenharmony_ci *
9728c2ecf20Sopenharmony_ci * This is the implementation of the gem_prime_import functions for GEM drivers
9738c2ecf20Sopenharmony_ci * using the PRIME helpers. Drivers can use this as their
9748c2ecf20Sopenharmony_ci * &drm_driver.gem_prime_import implementation. It is used as the default
9758c2ecf20Sopenharmony_ci * implementation in drm_gem_prime_fd_to_handle().
9768c2ecf20Sopenharmony_ci *
9778c2ecf20Sopenharmony_ci * Drivers must arrange to call drm_prime_gem_destroy() from their
9788c2ecf20Sopenharmony_ci * &drm_gem_object_funcs.free hook when using this function.
9798c2ecf20Sopenharmony_ci */
9808c2ecf20Sopenharmony_cistruct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
9818c2ecf20Sopenharmony_ci					    struct dma_buf *dma_buf)
9828c2ecf20Sopenharmony_ci{
9838c2ecf20Sopenharmony_ci	return drm_gem_prime_import_dev(dev, dma_buf, dev->dev);
9848c2ecf20Sopenharmony_ci}
9858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_gem_prime_import);
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci/**
9888c2ecf20Sopenharmony_ci * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
9898c2ecf20Sopenharmony_ci * @sgt: scatter-gather table to convert
9908c2ecf20Sopenharmony_ci * @pages: optional array of page pointers to store the page array in
9918c2ecf20Sopenharmony_ci * @addrs: optional array to store the dma bus address of each page
9928c2ecf20Sopenharmony_ci * @max_entries: size of both the passed-in arrays
9938c2ecf20Sopenharmony_ci *
9948c2ecf20Sopenharmony_ci * Exports an sg table into an array of pages and addresses. This is currently
9958c2ecf20Sopenharmony_ci * required by the TTM driver in order to do correct fault handling.
9968c2ecf20Sopenharmony_ci *
9978c2ecf20Sopenharmony_ci * Drivers can use this in their &drm_driver.gem_prime_import_sg_table
9988c2ecf20Sopenharmony_ci * implementation.
9998c2ecf20Sopenharmony_ci */
10008c2ecf20Sopenharmony_ciint drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
10018c2ecf20Sopenharmony_ci				     dma_addr_t *addrs, int max_entries)
10028c2ecf20Sopenharmony_ci{
10038c2ecf20Sopenharmony_ci	struct sg_dma_page_iter dma_iter;
10048c2ecf20Sopenharmony_ci	struct sg_page_iter page_iter;
10058c2ecf20Sopenharmony_ci	struct page **p = pages;
10068c2ecf20Sopenharmony_ci	dma_addr_t *a = addrs;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	if (pages) {
10098c2ecf20Sopenharmony_ci		for_each_sgtable_page(sgt, &page_iter, 0) {
10108c2ecf20Sopenharmony_ci			if (WARN_ON(p - pages >= max_entries))
10118c2ecf20Sopenharmony_ci				return -1;
10128c2ecf20Sopenharmony_ci			*p++ = sg_page_iter_page(&page_iter);
10138c2ecf20Sopenharmony_ci		}
10148c2ecf20Sopenharmony_ci	}
10158c2ecf20Sopenharmony_ci	if (addrs) {
10168c2ecf20Sopenharmony_ci		for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
10178c2ecf20Sopenharmony_ci			if (WARN_ON(a - addrs >= max_entries))
10188c2ecf20Sopenharmony_ci				return -1;
10198c2ecf20Sopenharmony_ci			*a++ = sg_page_iter_dma_address(&dma_iter);
10208c2ecf20Sopenharmony_ci		}
10218c2ecf20Sopenharmony_ci	}
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	return 0;
10248c2ecf20Sopenharmony_ci}
10258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci/**
10288c2ecf20Sopenharmony_ci * drm_prime_gem_destroy - helper to clean up a PRIME-imported GEM object
10298c2ecf20Sopenharmony_ci * @obj: GEM object which was created from a dma-buf
10308c2ecf20Sopenharmony_ci * @sg: the sg-table which was pinned at import time
10318c2ecf20Sopenharmony_ci *
10328c2ecf20Sopenharmony_ci * This is the cleanup functions which GEM drivers need to call when they use
10338c2ecf20Sopenharmony_ci * drm_gem_prime_import() or drm_gem_prime_import_dev() to import dma-bufs.
10348c2ecf20Sopenharmony_ci */
10358c2ecf20Sopenharmony_civoid drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
10368c2ecf20Sopenharmony_ci{
10378c2ecf20Sopenharmony_ci	struct dma_buf_attachment *attach;
10388c2ecf20Sopenharmony_ci	struct dma_buf *dma_buf;
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	attach = obj->import_attach;
10418c2ecf20Sopenharmony_ci	if (sg)
10428c2ecf20Sopenharmony_ci		dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
10438c2ecf20Sopenharmony_ci	dma_buf = attach->dmabuf;
10448c2ecf20Sopenharmony_ci	dma_buf_detach(attach->dmabuf, attach);
10458c2ecf20Sopenharmony_ci	/* remove the reference */
10468c2ecf20Sopenharmony_ci	dma_buf_put(dma_buf);
10478c2ecf20Sopenharmony_ci}
10488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(drm_prime_gem_destroy);
1049