xref: /dflybsd-src/sys/dev/drm/drm_prime.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
1565c8854SFrançois Tigeot /*
2565c8854SFrançois Tigeot  * Copyright © 2012 Red Hat
3565c8854SFrançois Tigeot  *
4565c8854SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5565c8854SFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6565c8854SFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7565c8854SFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8565c8854SFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9565c8854SFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10565c8854SFrançois Tigeot  *
11565c8854SFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12565c8854SFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13565c8854SFrançois Tigeot  * Software.
14565c8854SFrançois Tigeot  *
15565c8854SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16565c8854SFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17565c8854SFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18565c8854SFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19565c8854SFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20565c8854SFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21565c8854SFrançois Tigeot  * IN THE SOFTWARE.
22565c8854SFrançois Tigeot  *
23565c8854SFrançois Tigeot  * Authors:
24565c8854SFrançois Tigeot  *      Dave Airlie <airlied@redhat.com>
25565c8854SFrançois Tigeot  *      Rob Clark <rob.clark@linaro.org>
26565c8854SFrançois Tigeot  *
27565c8854SFrançois Tigeot  */
28565c8854SFrançois Tigeot 
29565c8854SFrançois Tigeot #include <linux/export.h>
30565c8854SFrançois Tigeot #include <linux/dma-buf.h>
311dedbd3bSFrançois Tigeot #include <linux/rbtree.h>
32a85cb24fSFrançois Tigeot #include <drm/drm_prime.h>
33565c8854SFrançois Tigeot #include <drm/drm_gem.h>
34a85cb24fSFrançois Tigeot #include <drm/drmP.h>
35565c8854SFrançois Tigeot 
36565c8854SFrançois Tigeot #include "drm_internal.h"
37565c8854SFrançois Tigeot 
38565c8854SFrançois Tigeot /*
39565c8854SFrançois Tigeot  * DMA-BUF/GEM Object references and lifetime overview:
40565c8854SFrançois Tigeot  *
41565c8854SFrançois Tigeot  * On the export the dma_buf holds a reference to the exporting GEM
42565c8854SFrançois Tigeot  * object. It takes this reference in handle_to_fd_ioctl, when it
43565c8854SFrançois Tigeot  * first calls .prime_export and stores the exporting GEM object in
44a85cb24fSFrançois Tigeot  * the dma_buf priv. This reference needs to be released when the
45a85cb24fSFrançois Tigeot  * final reference to the &dma_buf itself is dropped and its
46a85cb24fSFrançois Tigeot  * &dma_buf_ops.release function is called. For GEM-based drivers,
47a85cb24fSFrançois Tigeot  * the dma_buf should be exported using drm_gem_dmabuf_export() and
48a85cb24fSFrançois Tigeot  * then released by drm_gem_dmabuf_release().
49565c8854SFrançois Tigeot  *
50565c8854SFrançois Tigeot  * On the import the importing GEM object holds a reference to the
51565c8854SFrançois Tigeot  * dma_buf (which in turn holds a ref to the exporting GEM object).
52565c8854SFrançois Tigeot  * It takes that reference in the fd_to_handle ioctl.
53565c8854SFrançois Tigeot  * It calls dma_buf_get, creates an attachment to it and stores the
54565c8854SFrançois Tigeot  * attachment in the GEM object. When this attachment is destroyed
55565c8854SFrançois Tigeot  * when the imported object is destroyed, we remove the attachment
56565c8854SFrançois Tigeot  * and drop the reference to the dma_buf.
57565c8854SFrançois Tigeot  *
58a85cb24fSFrançois Tigeot  * When all the references to the &dma_buf are dropped, i.e. when
59a85cb24fSFrançois Tigeot  * userspace has closed both handles to the imported GEM object (through the
60a85cb24fSFrançois Tigeot  * FD_TO_HANDLE IOCTL) and closed the file descriptor of the exported
61a85cb24fSFrançois Tigeot  * (through the HANDLE_TO_FD IOCTL) dma_buf, and all kernel-internal references
62a85cb24fSFrançois Tigeot  * are also gone, then the dma_buf gets destroyed.  This can also happen as a
63a85cb24fSFrançois Tigeot  * part of the clean up procedure in the drm_release() function if userspace
64a85cb24fSFrançois Tigeot  * fails to properly clean up.  Note that both the kernel and userspace (by
65a85cb24fSFrançois Tigeot  * keeeping the PRIME file descriptors open) can hold references onto a
66a85cb24fSFrançois Tigeot  * &dma_buf.
67a85cb24fSFrançois Tigeot  *
68565c8854SFrançois Tigeot  * Thus the chain of references always flows in one direction
69565c8854SFrançois Tigeot  * (avoiding loops): importing_gem -> dmabuf -> exporting_gem
70565c8854SFrançois Tigeot  *
71565c8854SFrançois Tigeot  * Self-importing: if userspace is using PRIME as a replacement for flink
72565c8854SFrançois Tigeot  * then it will get a fd->handle request for a GEM object that it created.
73565c8854SFrançois Tigeot  * Drivers should detect this situation and return back the gem object
74565c8854SFrançois Tigeot  * from the dma-buf private.  Prime will do this automatically for drivers that
75565c8854SFrançois Tigeot  * use the drm_gem_prime_{import,export} helpers.
76565c8854SFrançois Tigeot  */
77565c8854SFrançois Tigeot 
78565c8854SFrançois Tigeot struct drm_prime_member {
79565c8854SFrançois Tigeot 	struct dma_buf *dma_buf;
80565c8854SFrançois Tigeot 	uint32_t handle;
811dedbd3bSFrançois Tigeot 
821dedbd3bSFrançois Tigeot 	struct rb_node dmabuf_rb;
831dedbd3bSFrançois Tigeot 	struct rb_node handle_rb;
84565c8854SFrançois Tigeot };
85565c8854SFrançois Tigeot 
86565c8854SFrançois Tigeot struct drm_prime_attachment {
87565c8854SFrançois Tigeot 	struct sg_table *sgt;
88565c8854SFrançois Tigeot 	enum dma_data_direction dir;
89565c8854SFrançois Tigeot };
90565c8854SFrançois Tigeot 
drm_prime_add_buf_handle(struct drm_prime_file_private * prime_fpriv,struct dma_buf * dma_buf,uint32_t handle)91565c8854SFrançois Tigeot static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
92565c8854SFrançois Tigeot 				    struct dma_buf *dma_buf, uint32_t handle)
93565c8854SFrançois Tigeot {
94565c8854SFrançois Tigeot 	struct drm_prime_member *member;
951dedbd3bSFrançois Tigeot 	struct rb_node **p, *rb;
96565c8854SFrançois Tigeot 
97*3f2dd94aSFrançois Tigeot 	member = kmalloc(sizeof(*member), M_DRM, GFP_KERNEL);
98565c8854SFrançois Tigeot 	if (!member)
99565c8854SFrançois Tigeot 		return -ENOMEM;
100565c8854SFrançois Tigeot 
101565c8854SFrançois Tigeot 	get_dma_buf(dma_buf);
102565c8854SFrançois Tigeot 	member->dma_buf = dma_buf;
103565c8854SFrançois Tigeot 	member->handle = handle;
1041dedbd3bSFrançois Tigeot 
1051dedbd3bSFrançois Tigeot 	rb = NULL;
1061dedbd3bSFrançois Tigeot 	p = &prime_fpriv->dmabufs.rb_node;
1071dedbd3bSFrançois Tigeot 	while (*p) {
1081dedbd3bSFrançois Tigeot 		struct drm_prime_member *pos;
1091dedbd3bSFrançois Tigeot 
1101dedbd3bSFrançois Tigeot 		rb = *p;
1111dedbd3bSFrançois Tigeot 		pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
1121dedbd3bSFrançois Tigeot 		if (dma_buf > pos->dma_buf)
1131dedbd3bSFrançois Tigeot 			p = &rb->rb_right;
1141dedbd3bSFrançois Tigeot 		else
1151dedbd3bSFrançois Tigeot 			p = &rb->rb_left;
1161dedbd3bSFrançois Tigeot 	}
1171dedbd3bSFrançois Tigeot 	rb_link_node(&member->dmabuf_rb, rb, p);
1181dedbd3bSFrançois Tigeot 	rb_insert_color(&member->dmabuf_rb, &prime_fpriv->dmabufs);
1191dedbd3bSFrançois Tigeot 
1201dedbd3bSFrançois Tigeot 	rb = NULL;
1211dedbd3bSFrançois Tigeot 	p = &prime_fpriv->handles.rb_node;
1221dedbd3bSFrançois Tigeot 	while (*p) {
1231dedbd3bSFrançois Tigeot 		struct drm_prime_member *pos;
1241dedbd3bSFrançois Tigeot 
1251dedbd3bSFrançois Tigeot 		rb = *p;
1261dedbd3bSFrançois Tigeot 		pos = rb_entry(rb, struct drm_prime_member, handle_rb);
1271dedbd3bSFrançois Tigeot 		if (handle > pos->handle)
1281dedbd3bSFrançois Tigeot 			p = &rb->rb_right;
1291dedbd3bSFrançois Tigeot 		else
1301dedbd3bSFrançois Tigeot 			p = &rb->rb_left;
1311dedbd3bSFrançois Tigeot 	}
1321dedbd3bSFrançois Tigeot 	rb_link_node(&member->handle_rb, rb, p);
1331dedbd3bSFrançois Tigeot 	rb_insert_color(&member->handle_rb, &prime_fpriv->handles);
1341dedbd3bSFrançois Tigeot 
135565c8854SFrançois Tigeot 	return 0;
136565c8854SFrançois Tigeot }
137565c8854SFrançois Tigeot 
drm_prime_lookup_buf_by_handle(struct drm_prime_file_private * prime_fpriv,uint32_t handle)138565c8854SFrançois Tigeot static struct dma_buf *drm_prime_lookup_buf_by_handle(struct drm_prime_file_private *prime_fpriv,
139565c8854SFrançois Tigeot 						      uint32_t handle)
140565c8854SFrançois Tigeot {
1411dedbd3bSFrançois Tigeot 	struct rb_node *rb;
1421dedbd3bSFrançois Tigeot 
1431dedbd3bSFrançois Tigeot 	rb = prime_fpriv->handles.rb_node;
1441dedbd3bSFrançois Tigeot 	while (rb) {
145565c8854SFrançois Tigeot 		struct drm_prime_member *member;
146565c8854SFrançois Tigeot 
1471dedbd3bSFrançois Tigeot 		member = rb_entry(rb, struct drm_prime_member, handle_rb);
148565c8854SFrançois Tigeot 		if (member->handle == handle)
149565c8854SFrançois Tigeot 			return member->dma_buf;
1501dedbd3bSFrançois Tigeot 		else if (member->handle < handle)
1511dedbd3bSFrançois Tigeot 			rb = rb->rb_right;
1521dedbd3bSFrançois Tigeot 		else
1531dedbd3bSFrançois Tigeot 			rb = rb->rb_left;
154565c8854SFrançois Tigeot 	}
155565c8854SFrançois Tigeot 
156565c8854SFrançois Tigeot 	return NULL;
157565c8854SFrançois Tigeot }
158565c8854SFrançois Tigeot 
drm_prime_lookup_buf_handle(struct drm_prime_file_private * prime_fpriv,struct dma_buf * dma_buf,uint32_t * handle)159565c8854SFrançois Tigeot static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv,
160565c8854SFrançois Tigeot 				       struct dma_buf *dma_buf,
161565c8854SFrançois Tigeot 				       uint32_t *handle)
162565c8854SFrançois Tigeot {
1631dedbd3bSFrançois Tigeot 	struct rb_node *rb;
1641dedbd3bSFrançois Tigeot 
1651dedbd3bSFrançois Tigeot 	rb = prime_fpriv->dmabufs.rb_node;
1661dedbd3bSFrançois Tigeot 	while (rb) {
167565c8854SFrançois Tigeot 		struct drm_prime_member *member;
168565c8854SFrançois Tigeot 
1691dedbd3bSFrançois Tigeot 		member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
170565c8854SFrançois Tigeot 		if (member->dma_buf == dma_buf) {
171565c8854SFrançois Tigeot 			*handle = member->handle;
172565c8854SFrançois Tigeot 			return 0;
1731dedbd3bSFrançois Tigeot 		} else if (member->dma_buf < dma_buf) {
1741dedbd3bSFrançois Tigeot 			rb = rb->rb_right;
1751dedbd3bSFrançois Tigeot 		} else {
1761dedbd3bSFrançois Tigeot 			rb = rb->rb_left;
177565c8854SFrançois Tigeot 		}
178565c8854SFrançois Tigeot 	}
1791dedbd3bSFrançois Tigeot 
180565c8854SFrançois Tigeot 	return -ENOENT;
181565c8854SFrançois Tigeot }
182565c8854SFrançois Tigeot 
drm_gem_map_attach(struct dma_buf * dma_buf,struct device * target_dev,struct dma_buf_attachment * attach)183565c8854SFrançois Tigeot static int drm_gem_map_attach(struct dma_buf *dma_buf,
184565c8854SFrançois Tigeot 			      struct device *target_dev,
185565c8854SFrançois Tigeot 			      struct dma_buf_attachment *attach)
186565c8854SFrançois Tigeot {
187565c8854SFrançois Tigeot 	struct drm_prime_attachment *prime_attach;
188565c8854SFrançois Tigeot 	struct drm_gem_object *obj = dma_buf->priv;
189565c8854SFrançois Tigeot 	struct drm_device *dev = obj->dev;
190565c8854SFrançois Tigeot 
191565c8854SFrançois Tigeot 	prime_attach = kzalloc(sizeof(*prime_attach), GFP_KERNEL);
192565c8854SFrançois Tigeot 	if (!prime_attach)
193565c8854SFrançois Tigeot 		return -ENOMEM;
194565c8854SFrançois Tigeot 
195565c8854SFrançois Tigeot 	prime_attach->dir = DMA_NONE;
196565c8854SFrançois Tigeot 	attach->priv = prime_attach;
197565c8854SFrançois Tigeot 
198565c8854SFrançois Tigeot 	if (!dev->driver->gem_prime_pin)
199565c8854SFrançois Tigeot 		return 0;
200565c8854SFrançois Tigeot 
201565c8854SFrançois Tigeot 	return dev->driver->gem_prime_pin(obj);
202565c8854SFrançois Tigeot }
203565c8854SFrançois Tigeot 
drm_gem_map_detach(struct dma_buf * dma_buf,struct dma_buf_attachment * attach)204565c8854SFrançois Tigeot static void drm_gem_map_detach(struct dma_buf *dma_buf,
205565c8854SFrançois Tigeot 			       struct dma_buf_attachment *attach)
206565c8854SFrançois Tigeot {
207565c8854SFrançois Tigeot 	struct drm_prime_attachment *prime_attach = attach->priv;
208565c8854SFrançois Tigeot 	struct drm_gem_object *obj = dma_buf->priv;
209565c8854SFrançois Tigeot 	struct drm_device *dev = obj->dev;
210565c8854SFrançois Tigeot 	struct sg_table *sgt;
211565c8854SFrançois Tigeot 
212565c8854SFrançois Tigeot 	if (dev->driver->gem_prime_unpin)
213565c8854SFrançois Tigeot 		dev->driver->gem_prime_unpin(obj);
214565c8854SFrançois Tigeot 
215565c8854SFrançois Tigeot 	if (!prime_attach)
216565c8854SFrançois Tigeot 		return;
217565c8854SFrançois Tigeot 
218565c8854SFrançois Tigeot 	sgt = prime_attach->sgt;
219565c8854SFrançois Tigeot 	if (sgt) {
220565c8854SFrançois Tigeot 		if (prime_attach->dir != DMA_NONE)
221565c8854SFrançois Tigeot 			dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,
222565c8854SFrançois Tigeot 					prime_attach->dir);
223565c8854SFrançois Tigeot 		sg_free_table(sgt);
224565c8854SFrançois Tigeot 	}
225565c8854SFrançois Tigeot 
226565c8854SFrançois Tigeot 	kfree(sgt);
227565c8854SFrançois Tigeot 	kfree(prime_attach);
228565c8854SFrançois Tigeot 	attach->priv = NULL;
229565c8854SFrançois Tigeot }
230565c8854SFrançois Tigeot 
drm_prime_remove_buf_handle_locked(struct drm_prime_file_private * prime_fpriv,struct dma_buf * dma_buf)231565c8854SFrançois Tigeot void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
232565c8854SFrançois Tigeot 					struct dma_buf *dma_buf)
233565c8854SFrançois Tigeot {
2341dedbd3bSFrançois Tigeot 	struct rb_node *rb;
235565c8854SFrançois Tigeot 
2361dedbd3bSFrançois Tigeot 	rb = prime_fpriv->dmabufs.rb_node;
2371dedbd3bSFrançois Tigeot 	while (rb) {
2381dedbd3bSFrançois Tigeot 		struct drm_prime_member *member;
2391dedbd3bSFrançois Tigeot 
2401dedbd3bSFrançois Tigeot 		member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
241565c8854SFrançois Tigeot 		if (member->dma_buf == dma_buf) {
2421dedbd3bSFrançois Tigeot 			rb_erase(&member->handle_rb, &prime_fpriv->handles);
2431dedbd3bSFrançois Tigeot 			rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
2441dedbd3bSFrançois Tigeot 
245565c8854SFrançois Tigeot 			dma_buf_put(dma_buf);
246565c8854SFrançois Tigeot 			kfree(member);
2471dedbd3bSFrançois Tigeot 			return;
2481dedbd3bSFrançois Tigeot 		} else if (member->dma_buf < dma_buf) {
2491dedbd3bSFrançois Tigeot 			rb = rb->rb_right;
2501dedbd3bSFrançois Tigeot 		} else {
2511dedbd3bSFrançois Tigeot 			rb = rb->rb_left;
252565c8854SFrançois Tigeot 		}
253565c8854SFrançois Tigeot 	}
254565c8854SFrançois Tigeot }
255565c8854SFrançois Tigeot 
drm_gem_map_dma_buf(struct dma_buf_attachment * attach,enum dma_data_direction dir)256565c8854SFrançois Tigeot static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
257565c8854SFrançois Tigeot 					    enum dma_data_direction dir)
258565c8854SFrançois Tigeot {
259565c8854SFrançois Tigeot 	struct drm_prime_attachment *prime_attach = attach->priv;
260565c8854SFrançois Tigeot 	struct drm_gem_object *obj = attach->dmabuf->priv;
261565c8854SFrançois Tigeot 	struct sg_table *sgt;
262565c8854SFrançois Tigeot 
263565c8854SFrançois Tigeot 	if (WARN_ON(dir == DMA_NONE || !prime_attach))
264565c8854SFrançois Tigeot 		return ERR_PTR(-EINVAL);
265565c8854SFrançois Tigeot 
266565c8854SFrançois Tigeot 	/* return the cached mapping when possible */
267565c8854SFrançois Tigeot 	if (prime_attach->dir == dir)
268565c8854SFrançois Tigeot 		return prime_attach->sgt;
269565c8854SFrançois Tigeot 
270565c8854SFrançois Tigeot 	/*
271565c8854SFrançois Tigeot 	 * two mappings with different directions for the same attachment are
272565c8854SFrançois Tigeot 	 * not allowed
273565c8854SFrançois Tigeot 	 */
274565c8854SFrançois Tigeot 	if (WARN_ON(prime_attach->dir != DMA_NONE))
275565c8854SFrançois Tigeot 		return ERR_PTR(-EBUSY);
276565c8854SFrançois Tigeot 
277565c8854SFrançois Tigeot 	sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
278565c8854SFrançois Tigeot 
279565c8854SFrançois Tigeot 	if (!IS_ERR(sgt)) {
280565c8854SFrançois Tigeot 		if (!dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir)) {
281565c8854SFrançois Tigeot 			sg_free_table(sgt);
282565c8854SFrançois Tigeot 			kfree(sgt);
283565c8854SFrançois Tigeot 			sgt = ERR_PTR(-ENOMEM);
284565c8854SFrançois Tigeot 		} else {
285565c8854SFrançois Tigeot 			prime_attach->sgt = sgt;
286565c8854SFrançois Tigeot 			prime_attach->dir = dir;
287565c8854SFrançois Tigeot 		}
288565c8854SFrançois Tigeot 	}
289565c8854SFrançois Tigeot 
290565c8854SFrançois Tigeot 	return sgt;
291565c8854SFrançois Tigeot }
292565c8854SFrançois Tigeot 
drm_gem_unmap_dma_buf(struct dma_buf_attachment * attach,struct sg_table * sgt,enum dma_data_direction dir)293565c8854SFrançois Tigeot static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
294565c8854SFrançois Tigeot 				  struct sg_table *sgt,
295565c8854SFrançois Tigeot 				  enum dma_data_direction dir)
296565c8854SFrançois Tigeot {
297565c8854SFrançois Tigeot 	/* nothing to be done here */
298565c8854SFrançois Tigeot }
299565c8854SFrançois Tigeot 
300565c8854SFrançois Tigeot /**
3011dedbd3bSFrançois Tigeot  * drm_gem_dmabuf_export - dma_buf export implementation for GEM
3021dedbd3bSFrançois Tigeot  * @dev: parent device for the exported dmabuf
3031dedbd3bSFrançois Tigeot  * @exp_info: the export information used by dma_buf_export()
3041dedbd3bSFrançois Tigeot  *
3051dedbd3bSFrançois Tigeot  * This wraps dma_buf_export() for use by generic GEM drivers that are using
3061dedbd3bSFrançois Tigeot  * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take
3074be47400SFrançois Tigeot  * a reference to the &drm_device and the exported &drm_gem_object (stored in
308a85cb24fSFrançois Tigeot  * &dma_buf_export_info.priv) which is released by drm_gem_dmabuf_release().
3091dedbd3bSFrançois Tigeot  *
3101dedbd3bSFrançois Tigeot  * Returns the new dmabuf.
3111dedbd3bSFrançois Tigeot  */
drm_gem_dmabuf_export(struct drm_device * dev,struct dma_buf_export_info * exp_info)3121dedbd3bSFrançois Tigeot struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
3131dedbd3bSFrançois Tigeot 				      struct dma_buf_export_info *exp_info)
3141dedbd3bSFrançois Tigeot {
3151dedbd3bSFrançois Tigeot 	struct dma_buf *dma_buf;
3161dedbd3bSFrançois Tigeot 
3171dedbd3bSFrançois Tigeot 	dma_buf = dma_buf_export(exp_info);
3184be47400SFrançois Tigeot 	if (IS_ERR(dma_buf))
3194be47400SFrançois Tigeot 		return dma_buf;
3204be47400SFrançois Tigeot 
321*3f2dd94aSFrançois Tigeot 	drm_dev_get(dev);
322a85cb24fSFrançois Tigeot 	drm_gem_object_get(exp_info->priv);
3231dedbd3bSFrançois Tigeot 
3241dedbd3bSFrançois Tigeot 	return dma_buf;
3251dedbd3bSFrançois Tigeot }
3261dedbd3bSFrançois Tigeot EXPORT_SYMBOL(drm_gem_dmabuf_export);
3271dedbd3bSFrançois Tigeot 
3281dedbd3bSFrançois Tigeot /**
329565c8854SFrançois Tigeot  * drm_gem_dmabuf_release - dma_buf release implementation for GEM
330565c8854SFrançois Tigeot  * @dma_buf: buffer to be released
331565c8854SFrançois Tigeot  *
332565c8854SFrançois Tigeot  * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers
333565c8854SFrançois Tigeot  * must use this in their dma_buf ops structure as the release callback.
3341dedbd3bSFrançois Tigeot  * drm_gem_dmabuf_release() should be used in conjunction with
3351dedbd3bSFrançois Tigeot  * drm_gem_dmabuf_export().
336565c8854SFrançois Tigeot  */
drm_gem_dmabuf_release(struct dma_buf * dma_buf)337565c8854SFrançois Tigeot void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
338565c8854SFrançois Tigeot {
339565c8854SFrançois Tigeot 	struct drm_gem_object *obj = dma_buf->priv;
3401dedbd3bSFrançois Tigeot 	struct drm_device *dev = obj->dev;
341565c8854SFrançois Tigeot 
342565c8854SFrançois Tigeot 	/* drop the reference on the export fd holds */
343a85cb24fSFrançois Tigeot 	drm_gem_object_put_unlocked(obj);
3441dedbd3bSFrançois Tigeot 
345*3f2dd94aSFrançois Tigeot 	drm_dev_put(dev);
346565c8854SFrançois Tigeot }
347565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_gem_dmabuf_release);
348565c8854SFrançois Tigeot 
drm_gem_dmabuf_vmap(struct dma_buf * dma_buf)349565c8854SFrançois Tigeot static void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
350565c8854SFrançois Tigeot {
351565c8854SFrançois Tigeot 	struct drm_gem_object *obj = dma_buf->priv;
352565c8854SFrançois Tigeot 	struct drm_device *dev = obj->dev;
353565c8854SFrançois Tigeot 
354565c8854SFrançois Tigeot 	return dev->driver->gem_prime_vmap(obj);
355565c8854SFrançois Tigeot }
356565c8854SFrançois Tigeot 
drm_gem_dmabuf_vunmap(struct dma_buf * dma_buf,void * vaddr)357565c8854SFrançois Tigeot static void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
358565c8854SFrançois Tigeot {
359565c8854SFrançois Tigeot 	struct drm_gem_object *obj = dma_buf->priv;
360565c8854SFrançois Tigeot 	struct drm_device *dev = obj->dev;
361565c8854SFrançois Tigeot 
362565c8854SFrançois Tigeot 	dev->driver->gem_prime_vunmap(obj, vaddr);
363565c8854SFrançois Tigeot }
364565c8854SFrançois Tigeot 
drm_gem_dmabuf_kmap_atomic(struct dma_buf * dma_buf,unsigned long page_num)365565c8854SFrançois Tigeot static void *drm_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
366565c8854SFrançois Tigeot 					unsigned long page_num)
367565c8854SFrançois Tigeot {
368565c8854SFrançois Tigeot 	return NULL;
369565c8854SFrançois Tigeot }
370565c8854SFrançois Tigeot 
drm_gem_dmabuf_kunmap_atomic(struct dma_buf * dma_buf,unsigned long page_num,void * addr)371565c8854SFrançois Tigeot static void drm_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
372565c8854SFrançois Tigeot 					 unsigned long page_num, void *addr)
373565c8854SFrançois Tigeot {
374565c8854SFrançois Tigeot 
375565c8854SFrançois Tigeot }
drm_gem_dmabuf_kmap(struct dma_buf * dma_buf,unsigned long page_num)376565c8854SFrançois Tigeot static void *drm_gem_dmabuf_kmap(struct dma_buf *dma_buf,
377565c8854SFrançois Tigeot 				 unsigned long page_num)
378565c8854SFrançois Tigeot {
379565c8854SFrançois Tigeot 	return NULL;
380565c8854SFrançois Tigeot }
381565c8854SFrançois Tigeot 
drm_gem_dmabuf_kunmap(struct dma_buf * dma_buf,unsigned long page_num,void * addr)382565c8854SFrançois Tigeot static void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
383565c8854SFrançois Tigeot 				  unsigned long page_num, void *addr)
384565c8854SFrançois Tigeot {
385565c8854SFrançois Tigeot 
386565c8854SFrançois Tigeot }
387565c8854SFrançois Tigeot 
drm_gem_dmabuf_mmap(struct dma_buf * dma_buf,struct vm_area_struct * vma)388565c8854SFrançois Tigeot static int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf,
389565c8854SFrançois Tigeot 			       struct vm_area_struct *vma)
390565c8854SFrançois Tigeot {
391565c8854SFrançois Tigeot 	struct drm_gem_object *obj = dma_buf->priv;
392565c8854SFrançois Tigeot 	struct drm_device *dev = obj->dev;
393565c8854SFrançois Tigeot 
394565c8854SFrançois Tigeot 	if (!dev->driver->gem_prime_mmap)
395565c8854SFrançois Tigeot 		return -ENOSYS;
396565c8854SFrançois Tigeot 
397565c8854SFrançois Tigeot 	return dev->driver->gem_prime_mmap(obj, vma);
398565c8854SFrançois Tigeot }
399565c8854SFrançois Tigeot 
400565c8854SFrançois Tigeot static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
401565c8854SFrançois Tigeot 	.attach = drm_gem_map_attach,
402565c8854SFrançois Tigeot 	.detach = drm_gem_map_detach,
403565c8854SFrançois Tigeot 	.map_dma_buf = drm_gem_map_dma_buf,
404565c8854SFrançois Tigeot 	.unmap_dma_buf = drm_gem_unmap_dma_buf,
405565c8854SFrançois Tigeot 	.release = drm_gem_dmabuf_release,
406a85cb24fSFrançois Tigeot 	.map = drm_gem_dmabuf_kmap,
407a85cb24fSFrançois Tigeot 	.map_atomic = drm_gem_dmabuf_kmap_atomic,
408a85cb24fSFrançois Tigeot 	.unmap = drm_gem_dmabuf_kunmap,
409a85cb24fSFrançois Tigeot 	.unmap_atomic = drm_gem_dmabuf_kunmap_atomic,
410565c8854SFrançois Tigeot 	.mmap = drm_gem_dmabuf_mmap,
411565c8854SFrançois Tigeot 	.vmap = drm_gem_dmabuf_vmap,
412565c8854SFrançois Tigeot 	.vunmap = drm_gem_dmabuf_vunmap,
413565c8854SFrançois Tigeot };
414565c8854SFrançois Tigeot 
415565c8854SFrançois Tigeot /**
416565c8854SFrançois Tigeot  * DOC: PRIME Helpers
417565c8854SFrançois Tigeot  *
418565c8854SFrançois Tigeot  * Drivers can implement @gem_prime_export and @gem_prime_import in terms of
419565c8854SFrançois Tigeot  * simpler APIs by using the helper functions @drm_gem_prime_export and
420565c8854SFrançois Tigeot  * @drm_gem_prime_import.  These functions implement dma-buf support in terms of
421565c8854SFrançois Tigeot  * six lower-level driver callbacks:
422565c8854SFrançois Tigeot  *
423565c8854SFrançois Tigeot  * Export callbacks:
424565c8854SFrançois Tigeot  *
425565c8854SFrançois Tigeot  *  * @gem_prime_pin (optional): prepare a GEM object for exporting
426565c8854SFrançois Tigeot  *  * @gem_prime_get_sg_table: provide a scatter/gather table of pinned pages
427565c8854SFrançois Tigeot  *  * @gem_prime_vmap: vmap a buffer exported by your driver
428565c8854SFrançois Tigeot  *  * @gem_prime_vunmap: vunmap a buffer exported by your driver
429565c8854SFrançois Tigeot  *  * @gem_prime_mmap (optional): mmap a buffer exported by your driver
430565c8854SFrançois Tigeot  *
431565c8854SFrançois Tigeot  * Import callback:
432565c8854SFrançois Tigeot  *
433565c8854SFrançois Tigeot  *  * @gem_prime_import_sg_table (import): produce a GEM object from another
434565c8854SFrançois Tigeot  *    driver's scatter/gather table
435565c8854SFrançois Tigeot  */
436565c8854SFrançois Tigeot 
437565c8854SFrançois Tigeot /**
438565c8854SFrançois Tigeot  * drm_gem_prime_export - helper library implementation of the export callback
439565c8854SFrançois Tigeot  * @dev: drm_device to export from
440565c8854SFrançois Tigeot  * @obj: GEM object to export
441565c8854SFrançois Tigeot  * @flags: flags like DRM_CLOEXEC and DRM_RDWR
442565c8854SFrançois Tigeot  *
443565c8854SFrançois Tigeot  * This is the implementation of the gem_prime_export functions for GEM drivers
444565c8854SFrançois Tigeot  * using the PRIME helpers.
445565c8854SFrançois Tigeot  */
drm_gem_prime_export(struct drm_device * dev,struct drm_gem_object * obj,int flags)446565c8854SFrançois Tigeot struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
4471dedbd3bSFrançois Tigeot 				     struct drm_gem_object *obj,
4481dedbd3bSFrançois Tigeot 				     int flags)
449565c8854SFrançois Tigeot {
4501dedbd3bSFrançois Tigeot 	struct dma_buf_export_info exp_info = {
4511dedbd3bSFrançois Tigeot #if 0
4521dedbd3bSFrançois Tigeot 		.exp_name = KBUILD_MODNAME, /* white lie for debug */
4531dedbd3bSFrançois Tigeot 		.owner = dev->driver->fops->owner,
4541dedbd3bSFrançois Tigeot #endif
4551dedbd3bSFrançois Tigeot 		.ops = &drm_gem_prime_dmabuf_ops,
4561dedbd3bSFrançois Tigeot 		.size = obj->size,
4571dedbd3bSFrançois Tigeot 		.flags = flags,
4581dedbd3bSFrançois Tigeot 		.priv = obj,
4591dedbd3bSFrançois Tigeot 	};
460565c8854SFrançois Tigeot 
461565c8854SFrançois Tigeot 	if (dev->driver->gem_prime_res_obj)
462565c8854SFrançois Tigeot 		exp_info.resv = dev->driver->gem_prime_res_obj(obj);
463565c8854SFrançois Tigeot 
4641dedbd3bSFrançois Tigeot 	return drm_gem_dmabuf_export(dev, &exp_info);
465565c8854SFrançois Tigeot }
466565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_gem_prime_export);
467565c8854SFrançois Tigeot 
export_and_register_object(struct drm_device * dev,struct drm_gem_object * obj,uint32_t flags)468565c8854SFrançois Tigeot static struct dma_buf *export_and_register_object(struct drm_device *dev,
469565c8854SFrançois Tigeot 						  struct drm_gem_object *obj,
470565c8854SFrançois Tigeot 						  uint32_t flags)
471565c8854SFrançois Tigeot {
472565c8854SFrançois Tigeot 	struct dma_buf *dmabuf;
473565c8854SFrançois Tigeot 
474565c8854SFrançois Tigeot 	/* prevent races with concurrent gem_close. */
475565c8854SFrançois Tigeot 	if (obj->handle_count == 0) {
476565c8854SFrançois Tigeot 		dmabuf = ERR_PTR(-ENOENT);
477565c8854SFrançois Tigeot 		return dmabuf;
478565c8854SFrançois Tigeot 	}
479565c8854SFrançois Tigeot 
480565c8854SFrançois Tigeot 	dmabuf = dev->driver->gem_prime_export(dev, obj, flags);
481565c8854SFrançois Tigeot 	if (IS_ERR(dmabuf)) {
482565c8854SFrançois Tigeot 		/* normally the created dma-buf takes ownership of the ref,
483565c8854SFrançois Tigeot 		 * but if that fails then drop the ref
484565c8854SFrançois Tigeot 		 */
485565c8854SFrançois Tigeot 		return dmabuf;
486565c8854SFrançois Tigeot 	}
487565c8854SFrançois Tigeot 
488565c8854SFrançois Tigeot 	/*
489565c8854SFrançois Tigeot 	 * Note that callers do not need to clean up the export cache
490565c8854SFrançois Tigeot 	 * since the check for obj->handle_count guarantees that someone
491565c8854SFrançois Tigeot 	 * will clean it up.
492565c8854SFrançois Tigeot 	 */
493565c8854SFrançois Tigeot 	obj->dma_buf = dmabuf;
494565c8854SFrançois Tigeot 	get_dma_buf(obj->dma_buf);
495565c8854SFrançois Tigeot 
496565c8854SFrançois Tigeot 	return dmabuf;
497565c8854SFrançois Tigeot }
498565c8854SFrançois Tigeot 
499565c8854SFrançois Tigeot /**
500565c8854SFrançois Tigeot  * drm_gem_prime_handle_to_fd - PRIME export function for GEM drivers
501565c8854SFrançois Tigeot  * @dev: dev to export the buffer from
502565c8854SFrançois Tigeot  * @file_priv: drm file-private structure
503565c8854SFrançois Tigeot  * @handle: buffer handle to export
504565c8854SFrançois Tigeot  * @flags: flags like DRM_CLOEXEC
505565c8854SFrançois Tigeot  * @prime_fd: pointer to storage for the fd id of the create dma-buf
506565c8854SFrançois Tigeot  *
507565c8854SFrançois Tigeot  * This is the PRIME export function which must be used mandatorily by GEM
508565c8854SFrançois Tigeot  * drivers to ensure correct lifetime management of the underlying GEM object.
509565c8854SFrançois Tigeot  * The actual exporting from GEM object to a dma-buf is done through the
510565c8854SFrançois Tigeot  * gem_prime_export driver callback.
511565c8854SFrançois Tigeot  */
drm_gem_prime_handle_to_fd(struct drm_device * dev,struct drm_file * file_priv,uint32_t handle,uint32_t flags,int * prime_fd)512565c8854SFrançois Tigeot int drm_gem_prime_handle_to_fd(struct drm_device *dev,
513565c8854SFrançois Tigeot 			       struct drm_file *file_priv, uint32_t handle,
514565c8854SFrançois Tigeot 			       uint32_t flags,
515565c8854SFrançois Tigeot 			       int *prime_fd)
516565c8854SFrançois Tigeot {
517565c8854SFrançois Tigeot 	struct drm_gem_object *obj;
518565c8854SFrançois Tigeot 	int ret = 0;
519565c8854SFrançois Tigeot 	struct dma_buf *dmabuf;
520565c8854SFrançois Tigeot 
521565c8854SFrançois Tigeot 	mutex_lock(&file_priv->prime.lock);
522565c8854SFrançois Tigeot 	obj = drm_gem_object_lookup(file_priv, handle);
523565c8854SFrançois Tigeot 	if (!obj)  {
524565c8854SFrançois Tigeot 		ret = -ENOENT;
525565c8854SFrançois Tigeot 		goto out_unlock;
526565c8854SFrançois Tigeot 	}
527565c8854SFrançois Tigeot 
528565c8854SFrançois Tigeot 	dmabuf = drm_prime_lookup_buf_by_handle(&file_priv->prime, handle);
529565c8854SFrançois Tigeot 	if (dmabuf) {
530565c8854SFrançois Tigeot 		get_dma_buf(dmabuf);
531565c8854SFrançois Tigeot 		goto out_have_handle;
532565c8854SFrançois Tigeot 	}
533565c8854SFrançois Tigeot 
534565c8854SFrançois Tigeot 	mutex_lock(&dev->object_name_lock);
535565c8854SFrançois Tigeot 	/* re-export the original imported object */
536565c8854SFrançois Tigeot 	if (obj->import_attach) {
537565c8854SFrançois Tigeot 		dmabuf = obj->import_attach->dmabuf;
538565c8854SFrançois Tigeot 		get_dma_buf(dmabuf);
539565c8854SFrançois Tigeot 		goto out_have_obj;
540565c8854SFrançois Tigeot 	}
541565c8854SFrançois Tigeot 
542565c8854SFrançois Tigeot 	if (obj->dma_buf) {
543565c8854SFrançois Tigeot 		get_dma_buf(obj->dma_buf);
544565c8854SFrançois Tigeot 		dmabuf = obj->dma_buf;
545565c8854SFrançois Tigeot 		goto out_have_obj;
546565c8854SFrançois Tigeot 	}
547565c8854SFrançois Tigeot 
548565c8854SFrançois Tigeot 	dmabuf = export_and_register_object(dev, obj, flags);
549565c8854SFrançois Tigeot 	if (IS_ERR(dmabuf)) {
550565c8854SFrançois Tigeot 		/* normally the created dma-buf takes ownership of the ref,
551565c8854SFrançois Tigeot 		 * but if that fails then drop the ref
552565c8854SFrançois Tigeot 		 */
553565c8854SFrançois Tigeot 		ret = PTR_ERR(dmabuf);
554565c8854SFrançois Tigeot 		mutex_unlock(&dev->object_name_lock);
555565c8854SFrançois Tigeot 		goto out;
556565c8854SFrançois Tigeot 	}
557565c8854SFrançois Tigeot 
558565c8854SFrançois Tigeot out_have_obj:
559565c8854SFrançois Tigeot 	/*
560565c8854SFrançois Tigeot 	 * If we've exported this buffer then cheat and add it to the import list
561565c8854SFrançois Tigeot 	 * so we get the correct handle back. We must do this under the
562565c8854SFrançois Tigeot 	 * protection of dev->object_name_lock to ensure that a racing gem close
563565c8854SFrançois Tigeot 	 * ioctl doesn't miss to remove this buffer handle from the cache.
564565c8854SFrançois Tigeot 	 */
565565c8854SFrançois Tigeot 	ret = drm_prime_add_buf_handle(&file_priv->prime,
566565c8854SFrançois Tigeot 				       dmabuf, handle);
567565c8854SFrançois Tigeot 	mutex_unlock(&dev->object_name_lock);
568565c8854SFrançois Tigeot 	if (ret)
569565c8854SFrançois Tigeot 		goto fail_put_dmabuf;
570565c8854SFrançois Tigeot 
571565c8854SFrançois Tigeot out_have_handle:
572565c8854SFrançois Tigeot 	ret = dma_buf_fd(dmabuf, flags);
573565c8854SFrançois Tigeot 	/*
574565c8854SFrançois Tigeot 	 * We must _not_ remove the buffer from the handle cache since the newly
575565c8854SFrançois Tigeot 	 * created dma buf is already linked in the global obj->dma_buf pointer,
576565c8854SFrançois Tigeot 	 * and that is invariant as long as a userspace gem handle exists.
577565c8854SFrançois Tigeot 	 * Closing the handle will clean out the cache anyway, so we don't leak.
578565c8854SFrançois Tigeot 	 */
579565c8854SFrançois Tigeot 	if (ret < 0) {
580565c8854SFrançois Tigeot 		goto fail_put_dmabuf;
581565c8854SFrançois Tigeot 	} else {
582565c8854SFrançois Tigeot 		*prime_fd = ret;
583565c8854SFrançois Tigeot 		ret = 0;
584565c8854SFrançois Tigeot 	}
585565c8854SFrançois Tigeot 
586565c8854SFrançois Tigeot 	goto out;
587565c8854SFrançois Tigeot 
588565c8854SFrançois Tigeot fail_put_dmabuf:
589565c8854SFrançois Tigeot 	dma_buf_put(dmabuf);
590565c8854SFrançois Tigeot out:
591a85cb24fSFrançois Tigeot 	drm_gem_object_put_unlocked(obj);
592565c8854SFrançois Tigeot out_unlock:
593565c8854SFrançois Tigeot 	mutex_unlock(&file_priv->prime.lock);
594565c8854SFrançois Tigeot 
595565c8854SFrançois Tigeot 	return ret;
596565c8854SFrançois Tigeot }
597565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
598565c8854SFrançois Tigeot 
599565c8854SFrançois Tigeot /**
600*3f2dd94aSFrançois Tigeot  * drm_gem_prime_import_dev - core implementation of the import callback
601565c8854SFrançois Tigeot  * @dev: drm_device to import into
602565c8854SFrançois Tigeot  * @dma_buf: dma-buf object to import
603*3f2dd94aSFrançois Tigeot  * @attach_dev: struct device to dma_buf attach
604565c8854SFrançois Tigeot  *
605*3f2dd94aSFrançois Tigeot  * This is the core of drm_gem_prime_import. It's designed to be called by
606*3f2dd94aSFrançois Tigeot  * drivers who want to use a different device structure than dev->dev for
607*3f2dd94aSFrançois Tigeot  * attaching via dma_buf.
608565c8854SFrançois Tigeot  */
drm_gem_prime_import_dev(struct drm_device * dev,struct dma_buf * dma_buf,struct device * attach_dev)609*3f2dd94aSFrançois Tigeot struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
610*3f2dd94aSFrançois Tigeot 					    struct dma_buf *dma_buf,
611*3f2dd94aSFrançois Tigeot 					    struct device *attach_dev)
612565c8854SFrançois Tigeot {
613565c8854SFrançois Tigeot 	struct dma_buf_attachment *attach;
614565c8854SFrançois Tigeot 	struct sg_table *sgt;
615565c8854SFrançois Tigeot 	struct drm_gem_object *obj;
616565c8854SFrançois Tigeot 	int ret;
617565c8854SFrançois Tigeot 
618565c8854SFrançois Tigeot 	if (dma_buf->ops == &drm_gem_prime_dmabuf_ops) {
619565c8854SFrançois Tigeot 		obj = dma_buf->priv;
620565c8854SFrançois Tigeot 		if (obj->dev == dev) {
621565c8854SFrançois Tigeot 			/*
622565c8854SFrançois Tigeot 			 * Importing dmabuf exported from out own gem increases
623565c8854SFrançois Tigeot 			 * refcount on gem itself instead of f_count of dmabuf.
624565c8854SFrançois Tigeot 			 */
625a85cb24fSFrançois Tigeot 			drm_gem_object_get(obj);
626565c8854SFrançois Tigeot 			return obj;
627565c8854SFrançois Tigeot 		}
628565c8854SFrançois Tigeot 	}
629565c8854SFrançois Tigeot 
630565c8854SFrançois Tigeot 	if (!dev->driver->gem_prime_import_sg_table)
631565c8854SFrançois Tigeot 		return ERR_PTR(-EINVAL);
632565c8854SFrançois Tigeot 
633*3f2dd94aSFrançois Tigeot 	attach = dma_buf_attach(dma_buf, attach_dev);
634565c8854SFrançois Tigeot 	if (IS_ERR(attach))
635565c8854SFrançois Tigeot 		return ERR_CAST(attach);
636565c8854SFrançois Tigeot 
637565c8854SFrançois Tigeot 	get_dma_buf(dma_buf);
638565c8854SFrançois Tigeot 
639565c8854SFrançois Tigeot 	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
640565c8854SFrançois Tigeot 	if (IS_ERR(sgt)) {
641565c8854SFrançois Tigeot 		ret = PTR_ERR(sgt);
642565c8854SFrançois Tigeot 		goto fail_detach;
643565c8854SFrançois Tigeot 	}
644565c8854SFrançois Tigeot 
645565c8854SFrançois Tigeot 	obj = dev->driver->gem_prime_import_sg_table(dev, attach, sgt);
646565c8854SFrançois Tigeot 	if (IS_ERR(obj)) {
647565c8854SFrançois Tigeot 		ret = PTR_ERR(obj);
648565c8854SFrançois Tigeot 		goto fail_unmap;
649565c8854SFrançois Tigeot 	}
650565c8854SFrançois Tigeot 
651565c8854SFrançois Tigeot 	obj->import_attach = attach;
652565c8854SFrançois Tigeot 
653565c8854SFrançois Tigeot 	return obj;
654565c8854SFrançois Tigeot 
655565c8854SFrançois Tigeot fail_unmap:
656565c8854SFrançois Tigeot 	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
657565c8854SFrançois Tigeot fail_detach:
658565c8854SFrançois Tigeot 	dma_buf_detach(dma_buf, attach);
659565c8854SFrançois Tigeot 	dma_buf_put(dma_buf);
660565c8854SFrançois Tigeot 
661565c8854SFrançois Tigeot 	return ERR_PTR(ret);
662*3f2dd94aSFrançois Tigeot }
663*3f2dd94aSFrançois Tigeot EXPORT_SYMBOL(drm_gem_prime_import_dev);
664*3f2dd94aSFrançois Tigeot 
665*3f2dd94aSFrançois Tigeot /**
666*3f2dd94aSFrançois Tigeot  * drm_gem_prime_import - helper library implementation of the import callback
667*3f2dd94aSFrançois Tigeot  * @dev: drm_device to import into
668*3f2dd94aSFrançois Tigeot  * @dma_buf: dma-buf object to import
669*3f2dd94aSFrançois Tigeot  *
670*3f2dd94aSFrançois Tigeot  * This is the implementation of the gem_prime_import functions for GEM drivers
671*3f2dd94aSFrançois Tigeot  * using the PRIME helpers.
672*3f2dd94aSFrançois Tigeot  */
drm_gem_prime_import(struct drm_device * dev,struct dma_buf * dma_buf)673*3f2dd94aSFrançois Tigeot struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
674*3f2dd94aSFrançois Tigeot 					    struct dma_buf *dma_buf)
675*3f2dd94aSFrançois Tigeot {
676*3f2dd94aSFrançois Tigeot 	return drm_gem_prime_import_dev(dev, dma_buf, dev->dev);
677565c8854SFrançois Tigeot }
678565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_gem_prime_import);
679565c8854SFrançois Tigeot 
680565c8854SFrançois Tigeot /**
681565c8854SFrançois Tigeot  * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
682565c8854SFrançois Tigeot  * @dev: dev to export the buffer from
683565c8854SFrançois Tigeot  * @file_priv: drm file-private structure
684565c8854SFrançois Tigeot  * @prime_fd: fd id of the dma-buf which should be imported
685565c8854SFrançois Tigeot  * @handle: pointer to storage for the handle of the imported buffer object
686565c8854SFrançois Tigeot  *
687565c8854SFrançois Tigeot  * This is the PRIME import function which must be used mandatorily by GEM
688565c8854SFrançois Tigeot  * drivers to ensure correct lifetime management of the underlying GEM object.
689565c8854SFrançois Tigeot  * The actual importing of GEM object from the dma-buf is done through the
690565c8854SFrançois Tigeot  * gem_import_export driver callback.
691565c8854SFrançois Tigeot  */
drm_gem_prime_fd_to_handle(struct drm_device * dev,struct drm_file * file_priv,int prime_fd,uint32_t * handle)692565c8854SFrançois Tigeot int drm_gem_prime_fd_to_handle(struct drm_device *dev,
693565c8854SFrançois Tigeot 			       struct drm_file *file_priv, int prime_fd,
694565c8854SFrançois Tigeot 			       uint32_t *handle)
695565c8854SFrançois Tigeot {
696565c8854SFrançois Tigeot 	struct dma_buf *dma_buf;
697565c8854SFrançois Tigeot 	struct drm_gem_object *obj;
698565c8854SFrançois Tigeot 	int ret;
699565c8854SFrançois Tigeot 
700565c8854SFrançois Tigeot 	dma_buf = dma_buf_get(prime_fd);
701565c8854SFrançois Tigeot 	if (IS_ERR(dma_buf))
702565c8854SFrançois Tigeot 		return PTR_ERR(dma_buf);
703565c8854SFrançois Tigeot 
704565c8854SFrançois Tigeot 	mutex_lock(&file_priv->prime.lock);
705565c8854SFrançois Tigeot 
706565c8854SFrançois Tigeot 	ret = drm_prime_lookup_buf_handle(&file_priv->prime,
707565c8854SFrançois Tigeot 			dma_buf, handle);
708565c8854SFrançois Tigeot 	if (ret == 0)
709565c8854SFrançois Tigeot 		goto out_put;
710565c8854SFrançois Tigeot 
711565c8854SFrançois Tigeot 	/* never seen this one, need to import */
712565c8854SFrançois Tigeot 	mutex_lock(&dev->object_name_lock);
713565c8854SFrançois Tigeot 	obj = dev->driver->gem_prime_import(dev, dma_buf);
714565c8854SFrançois Tigeot 	if (IS_ERR(obj)) {
715565c8854SFrançois Tigeot 		ret = PTR_ERR(obj);
716565c8854SFrançois Tigeot 		goto out_unlock;
717565c8854SFrançois Tigeot 	}
718565c8854SFrançois Tigeot 
719565c8854SFrançois Tigeot 	if (obj->dma_buf) {
720565c8854SFrançois Tigeot 		WARN_ON(obj->dma_buf != dma_buf);
721565c8854SFrançois Tigeot 	} else {
722565c8854SFrançois Tigeot 		obj->dma_buf = dma_buf;
723565c8854SFrançois Tigeot 		get_dma_buf(dma_buf);
724565c8854SFrançois Tigeot 	}
725565c8854SFrançois Tigeot 
7261dedbd3bSFrançois Tigeot 	/* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
727565c8854SFrançois Tigeot 	ret = drm_gem_handle_create_tail(file_priv, obj, handle);
728a85cb24fSFrançois Tigeot 	drm_gem_object_put_unlocked(obj);
729565c8854SFrançois Tigeot 	if (ret)
730565c8854SFrançois Tigeot 		goto out_put;
731565c8854SFrançois Tigeot 
732565c8854SFrançois Tigeot 	ret = drm_prime_add_buf_handle(&file_priv->prime,
733565c8854SFrançois Tigeot 			dma_buf, *handle);
7341dedbd3bSFrançois Tigeot 	mutex_unlock(&file_priv->prime.lock);
735565c8854SFrançois Tigeot 	if (ret)
736565c8854SFrançois Tigeot 		goto fail;
737565c8854SFrançois Tigeot 
738565c8854SFrançois Tigeot 	dma_buf_put(dma_buf);
739565c8854SFrançois Tigeot 
740565c8854SFrançois Tigeot 	return 0;
741565c8854SFrançois Tigeot 
742565c8854SFrançois Tigeot fail:
743565c8854SFrançois Tigeot 	/* hmm, if driver attached, we are relying on the free-object path
744565c8854SFrançois Tigeot 	 * to detach.. which seems ok..
745565c8854SFrançois Tigeot 	 */
746565c8854SFrançois Tigeot 	drm_gem_handle_delete(file_priv, *handle);
7471dedbd3bSFrançois Tigeot 	dma_buf_put(dma_buf);
7481dedbd3bSFrançois Tigeot 	return ret;
7491dedbd3bSFrançois Tigeot 
750565c8854SFrançois Tigeot out_unlock:
751565c8854SFrançois Tigeot 	mutex_unlock(&dev->object_name_lock);
752565c8854SFrançois Tigeot out_put:
753565c8854SFrançois Tigeot 	mutex_unlock(&file_priv->prime.lock);
7541dedbd3bSFrançois Tigeot 	dma_buf_put(dma_buf);
755565c8854SFrançois Tigeot 	return ret;
756565c8854SFrançois Tigeot }
757565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
758565c8854SFrançois Tigeot 
drm_prime_handle_to_fd_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)759565c8854SFrançois Tigeot int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
760565c8854SFrançois Tigeot 				 struct drm_file *file_priv)
761565c8854SFrançois Tigeot {
762565c8854SFrançois Tigeot 	struct drm_prime_handle *args = data;
763565c8854SFrançois Tigeot 
764565c8854SFrançois Tigeot 	if (!drm_core_check_feature(dev, DRIVER_PRIME))
765565c8854SFrançois Tigeot 		return -EINVAL;
766565c8854SFrançois Tigeot 
767565c8854SFrançois Tigeot 	if (!dev->driver->prime_handle_to_fd)
768565c8854SFrançois Tigeot 		return -ENOSYS;
769565c8854SFrançois Tigeot 
770565c8854SFrançois Tigeot 	/* check flags are valid */
771565c8854SFrançois Tigeot 	if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR))
772565c8854SFrançois Tigeot 		return -EINVAL;
773565c8854SFrançois Tigeot 
774565c8854SFrançois Tigeot 	return dev->driver->prime_handle_to_fd(dev, file_priv,
775565c8854SFrançois Tigeot 			args->handle, args->flags, &args->fd);
776565c8854SFrançois Tigeot }
777565c8854SFrançois Tigeot 
drm_prime_fd_to_handle_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)778565c8854SFrançois Tigeot int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
779565c8854SFrançois Tigeot 				 struct drm_file *file_priv)
780565c8854SFrançois Tigeot {
781565c8854SFrançois Tigeot 	struct drm_prime_handle *args = data;
782565c8854SFrançois Tigeot 
783565c8854SFrançois Tigeot 	if (!drm_core_check_feature(dev, DRIVER_PRIME))
784565c8854SFrançois Tigeot 		return -EINVAL;
785565c8854SFrançois Tigeot 
786565c8854SFrançois Tigeot 	if (!dev->driver->prime_fd_to_handle)
787565c8854SFrançois Tigeot 		return -ENOSYS;
788565c8854SFrançois Tigeot 
789565c8854SFrançois Tigeot 	return dev->driver->prime_fd_to_handle(dev, file_priv,
790565c8854SFrançois Tigeot 			args->fd, &args->handle);
791565c8854SFrançois Tigeot }
792565c8854SFrançois Tigeot 
793565c8854SFrançois Tigeot /**
794565c8854SFrançois Tigeot  * drm_prime_pages_to_sg - converts a page array into an sg list
795565c8854SFrançois Tigeot  * @pages: pointer to the array of page pointers to convert
796565c8854SFrançois Tigeot  * @nr_pages: length of the page vector
797565c8854SFrançois Tigeot  *
798565c8854SFrançois Tigeot  * This helper creates an sg table object from a set of pages
799565c8854SFrançois Tigeot  * the driver is responsible for mapping the pages into the
800565c8854SFrançois Tigeot  * importers address space for use with dma_buf itself.
801565c8854SFrançois Tigeot  */
drm_prime_pages_to_sg(struct page ** pages,unsigned int nr_pages)802565c8854SFrançois Tigeot struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages)
803565c8854SFrançois Tigeot {
804565c8854SFrançois Tigeot 	struct sg_table *sg = NULL;
805565c8854SFrançois Tigeot 	int ret;
806565c8854SFrançois Tigeot 
807*3f2dd94aSFrançois Tigeot 	sg = kmalloc(sizeof(struct sg_table), M_DRM, GFP_KERNEL);
808565c8854SFrançois Tigeot 	if (!sg) {
809565c8854SFrançois Tigeot 		ret = -ENOMEM;
810565c8854SFrançois Tigeot 		goto out;
811565c8854SFrançois Tigeot 	}
812565c8854SFrançois Tigeot 
813565c8854SFrançois Tigeot 	ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
814565c8854SFrançois Tigeot 				nr_pages << PAGE_SHIFT, GFP_KERNEL);
815565c8854SFrançois Tigeot 	if (ret)
816565c8854SFrançois Tigeot 		goto out;
817565c8854SFrançois Tigeot 
818565c8854SFrançois Tigeot 	return sg;
819565c8854SFrançois Tigeot out:
820565c8854SFrançois Tigeot 	kfree(sg);
821565c8854SFrançois Tigeot 	return ERR_PTR(ret);
822565c8854SFrançois Tigeot }
823565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_prime_pages_to_sg);
824565c8854SFrançois Tigeot 
825565c8854SFrançois Tigeot /**
826565c8854SFrançois Tigeot  * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
827565c8854SFrançois Tigeot  * @sgt: scatter-gather table to convert
828565c8854SFrançois Tigeot  * @pages: array of page pointers to store the page array in
829565c8854SFrançois Tigeot  * @addrs: optional array to store the dma bus address of each page
830565c8854SFrançois Tigeot  * @max_pages: size of both the passed-in arrays
831565c8854SFrançois Tigeot  *
832565c8854SFrançois Tigeot  * Exports an sg table into an array of pages and addresses. This is currently
833565c8854SFrançois Tigeot  * required by the TTM driver in order to do correct fault handling.
834565c8854SFrançois Tigeot  */
drm_prime_sg_to_page_addr_arrays(struct sg_table * sgt,struct page ** pages,dma_addr_t * addrs,int max_pages)835565c8854SFrançois Tigeot int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
836565c8854SFrançois Tigeot 				     dma_addr_t *addrs, int max_pages)
837565c8854SFrançois Tigeot {
838565c8854SFrançois Tigeot 	unsigned count;
839565c8854SFrançois Tigeot 	struct scatterlist *sg;
840565c8854SFrançois Tigeot 	struct page *page;
841565c8854SFrançois Tigeot 	u32 len;
842565c8854SFrançois Tigeot 	int pg_index;
843565c8854SFrançois Tigeot 	dma_addr_t addr;
844565c8854SFrançois Tigeot 
845565c8854SFrançois Tigeot 	pg_index = 0;
846565c8854SFrançois Tigeot 	for_each_sg(sgt->sgl, sg, sgt->nents, count) {
847565c8854SFrançois Tigeot 		len = sg->length;
848565c8854SFrançois Tigeot 		page = sg_page(sg);
849565c8854SFrançois Tigeot 		addr = sg_dma_address(sg);
850565c8854SFrançois Tigeot 
851565c8854SFrançois Tigeot 		while (len > 0) {
852565c8854SFrançois Tigeot 			if (WARN_ON(pg_index >= max_pages))
853565c8854SFrançois Tigeot 				return -1;
854565c8854SFrançois Tigeot 			pages[pg_index] = page;
855565c8854SFrançois Tigeot 			if (addrs)
856565c8854SFrançois Tigeot 				addrs[pg_index] = addr;
857565c8854SFrançois Tigeot 
858565c8854SFrançois Tigeot 			page++;
859565c8854SFrançois Tigeot 			addr += PAGE_SIZE;
860565c8854SFrançois Tigeot 			len -= PAGE_SIZE;
861565c8854SFrançois Tigeot 			pg_index++;
862565c8854SFrançois Tigeot 		}
863565c8854SFrançois Tigeot 	}
864565c8854SFrançois Tigeot 	return 0;
865565c8854SFrançois Tigeot }
866565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
867565c8854SFrançois Tigeot 
868565c8854SFrançois Tigeot /**
869565c8854SFrançois Tigeot  * drm_prime_gem_destroy - helper to clean up a PRIME-imported GEM object
870565c8854SFrançois Tigeot  * @obj: GEM object which was created from a dma-buf
871565c8854SFrançois Tigeot  * @sg: the sg-table which was pinned at import time
872565c8854SFrançois Tigeot  *
873565c8854SFrançois Tigeot  * This is the cleanup functions which GEM drivers need to call when they use
874565c8854SFrançois Tigeot  * @drm_gem_prime_import to import dma-bufs.
875565c8854SFrançois Tigeot  */
drm_prime_gem_destroy(struct drm_gem_object * obj,struct sg_table * sg)876565c8854SFrançois Tigeot void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
877565c8854SFrançois Tigeot {
878565c8854SFrançois Tigeot 	struct dma_buf_attachment *attach;
879565c8854SFrançois Tigeot 	struct dma_buf *dma_buf;
880565c8854SFrançois Tigeot 	attach = obj->import_attach;
881565c8854SFrançois Tigeot 	if (sg)
882565c8854SFrançois Tigeot 		dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
883565c8854SFrançois Tigeot 	dma_buf = attach->dmabuf;
884565c8854SFrançois Tigeot 	dma_buf_detach(attach->dmabuf, attach);
885565c8854SFrançois Tigeot 	/* remove the reference */
886565c8854SFrançois Tigeot 	dma_buf_put(dma_buf);
887565c8854SFrançois Tigeot }
888565c8854SFrançois Tigeot EXPORT_SYMBOL(drm_prime_gem_destroy);
889565c8854SFrançois Tigeot 
drm_prime_init_file_private(struct drm_prime_file_private * prime_fpriv)890565c8854SFrançois Tigeot void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
891565c8854SFrançois Tigeot {
892565c8854SFrançois Tigeot 	lockinit(&prime_fpriv->lock, "drmpfpl", 0, LK_CANRECURSE);
8931dedbd3bSFrançois Tigeot 	prime_fpriv->dmabufs = LINUX_RB_ROOT;
8941dedbd3bSFrançois Tigeot 	prime_fpriv->handles = LINUX_RB_ROOT;
895565c8854SFrançois Tigeot }
896565c8854SFrançois Tigeot 
drm_prime_destroy_file_private(struct drm_prime_file_private * prime_fpriv)897565c8854SFrançois Tigeot void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
898565c8854SFrançois Tigeot {
899565c8854SFrançois Tigeot 	/* by now drm_gem_release should've made sure the list is empty */
9001dedbd3bSFrançois Tigeot 	WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
901565c8854SFrançois Tigeot }
902