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