diff options
-rw-r--r-- | drivers/gpu/drm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_prime.c | 304 | ||||
-rw-r--r-- | include/drm/drm.h | 14 | ||||
-rw-r--r-- | include/drm/drmP.h | 62 |
8 files changed, 401 insertions, 2 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index cc1148837e24..e354bc0b052a 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -9,6 +9,7 @@ menuconfig DRM | |||
9 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU | 9 | depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU |
10 | select I2C | 10 | select I2C |
11 | select I2C_ALGOBIT | 11 | select I2C_ALGOBIT |
12 | select DMA_SHARED_BUFFER | ||
12 | help | 13 | help |
13 | Kernel-level support for the Direct Rendering Infrastructure (DRI) | 14 | Kernel-level support for the Direct Rendering Infrastructure (DRI) |
14 | introduced in XFree86 4.0. If you say Y here, you need to select | 15 | introduced in XFree86 4.0. If you say Y here, you need to select |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a858532806ae..c20da5bda355 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -12,7 +12,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ | |||
12 | drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ | 12 | drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ |
13 | drm_crtc.o drm_modes.o drm_edid.o \ | 13 | drm_crtc.o drm_modes.o drm_edid.o \ |
14 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ | 14 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ |
15 | drm_trace_points.o drm_global.o | 15 | drm_trace_points.o drm_global.o drm_prime.o |
16 | 16 | ||
17 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 17 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
18 | 18 | ||
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 0b65fbc8a630..6116e3b75393 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -136,6 +136,10 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
136 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), | 136 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), |
137 | 137 | ||
138 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 138 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
139 | |||
140 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED), | ||
141 | DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED), | ||
142 | |||
139 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 143 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
140 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 144 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
141 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 145 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 7348a3dab250..cdfbf27b2b3c 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -271,6 +271,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
271 | if (dev->driver->driver_features & DRIVER_GEM) | 271 | if (dev->driver->driver_features & DRIVER_GEM) |
272 | drm_gem_open(dev, priv); | 272 | drm_gem_open(dev, priv); |
273 | 273 | ||
274 | if (drm_core_check_feature(dev, DRIVER_PRIME)) | ||
275 | drm_prime_init_file_private(&priv->prime); | ||
276 | |||
274 | if (dev->driver->open) { | 277 | if (dev->driver->open) { |
275 | ret = dev->driver->open(dev, priv); | 278 | ret = dev->driver->open(dev, priv); |
276 | if (ret < 0) | 279 | if (ret < 0) |
@@ -571,6 +574,10 @@ int drm_release(struct inode *inode, struct file *filp) | |||
571 | 574 | ||
572 | if (dev->driver->postclose) | 575 | if (dev->driver->postclose) |
573 | dev->driver->postclose(dev, file_priv); | 576 | dev->driver->postclose(dev, file_priv); |
577 | |||
578 | if (drm_core_check_feature(dev, DRIVER_PRIME)) | ||
579 | drm_prime_destroy_file_private(&file_priv->prime); | ||
580 | |||
574 | kfree(file_priv); | 581 | kfree(file_priv); |
575 | 582 | ||
576 | /* ======================================================== | 583 | /* ======================================================== |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 0ef358e53245..83114b5e3cee 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/mman.h> | 35 | #include <linux/mman.h> |
36 | #include <linux/pagemap.h> | 36 | #include <linux/pagemap.h> |
37 | #include <linux/shmem_fs.h> | 37 | #include <linux/shmem_fs.h> |
38 | #include <linux/dma-buf.h> | ||
38 | #include "drmP.h" | 39 | #include "drmP.h" |
39 | 40 | ||
40 | /** @file drm_gem.c | 41 | /** @file drm_gem.c |
@@ -232,6 +233,10 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle) | |||
232 | idr_remove(&filp->object_idr, handle); | 233 | idr_remove(&filp->object_idr, handle); |
233 | spin_unlock(&filp->table_lock); | 234 | spin_unlock(&filp->table_lock); |
234 | 235 | ||
236 | if (obj->import_attach) | ||
237 | drm_prime_remove_imported_buf_handle(&filp->prime, | ||
238 | obj->import_attach->dmabuf); | ||
239 | |||
235 | if (dev->driver->gem_close_object) | 240 | if (dev->driver->gem_close_object) |
236 | dev->driver->gem_close_object(obj, filp); | 241 | dev->driver->gem_close_object(obj, filp); |
237 | drm_gem_object_handle_unreference_unlocked(obj); | 242 | drm_gem_object_handle_unreference_unlocked(obj); |
@@ -527,6 +532,10 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) | |||
527 | struct drm_gem_object *obj = ptr; | 532 | struct drm_gem_object *obj = ptr; |
528 | struct drm_device *dev = obj->dev; | 533 | struct drm_device *dev = obj->dev; |
529 | 534 | ||
535 | if (obj->import_attach) | ||
536 | drm_prime_remove_imported_buf_handle(&file_priv->prime, | ||
537 | obj->import_attach->dmabuf); | ||
538 | |||
530 | if (dev->driver->gem_close_object) | 539 | if (dev->driver->gem_close_object) |
531 | dev->driver->gem_close_object(obj, file_priv); | 540 | dev->driver->gem_close_object(obj, file_priv); |
532 | 541 | ||
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c new file mode 100644 index 000000000000..1bdf2b54eaf6 --- /dev/null +++ b/drivers/gpu/drm/drm_prime.c | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * Copyright © 2012 Red Hat | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Dave Airlie <airlied@redhat.com> | ||
25 | * Rob Clark <rob.clark@linaro.org> | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include <linux/export.h> | ||
30 | #include <linux/dma-buf.h> | ||
31 | #include "drmP.h" | ||
32 | |||
33 | /* | ||
34 | * DMA-BUF/GEM Object references and lifetime overview: | ||
35 | * | ||
36 | * On the export the dma_buf holds a reference to the exporting GEM | ||
37 | * object. It takes this reference in handle_to_fd_ioctl, when it | ||
38 | * first calls .prime_export and stores the exporting GEM object in | ||
39 | * the dma_buf priv. This reference is released when the dma_buf | ||
40 | * object goes away in the driver .release function. | ||
41 | * | ||
42 | * On the import the importing GEM object holds a reference to the | ||
43 | * dma_buf (which in turn holds a ref to the exporting GEM object). | ||
44 | * It takes that reference in the fd_to_handle ioctl. | ||
45 | * It calls dma_buf_get, creates an attachment to it and stores the | ||
46 | * attachment in the GEM object. When this attachment is destroyed | ||
47 | * when the imported object is destroyed, we remove the attachment | ||
48 | * and drop the reference to the dma_buf. | ||
49 | * | ||
50 | * Thus the chain of references always flows in one direction | ||
51 | * (avoiding loops): importing_gem -> dmabuf -> exporting_gem | ||
52 | * | ||
53 | * Self-importing: if userspace is using PRIME as a replacement for flink | ||
54 | * then it will get a fd->handle request for a GEM object that it created. | ||
55 | * Drivers should detect this situation and return back the gem object | ||
56 | * from the dma-buf private. | ||
57 | */ | ||
58 | |||
59 | struct drm_prime_member { | ||
60 | struct list_head entry; | ||
61 | struct dma_buf *dma_buf; | ||
62 | uint32_t handle; | ||
63 | }; | ||
64 | |||
65 | int drm_gem_prime_handle_to_fd(struct drm_device *dev, | ||
66 | struct drm_file *file_priv, uint32_t handle, uint32_t flags, | ||
67 | int *prime_fd) | ||
68 | { | ||
69 | struct drm_gem_object *obj; | ||
70 | void *buf; | ||
71 | |||
72 | obj = drm_gem_object_lookup(dev, file_priv, handle); | ||
73 | if (!obj) | ||
74 | return -ENOENT; | ||
75 | |||
76 | mutex_lock(&file_priv->prime.lock); | ||
77 | /* re-export the original imported object */ | ||
78 | if (obj->import_attach) { | ||
79 | get_dma_buf(obj->import_attach->dmabuf); | ||
80 | *prime_fd = dma_buf_fd(obj->import_attach->dmabuf, flags); | ||
81 | drm_gem_object_unreference_unlocked(obj); | ||
82 | mutex_unlock(&file_priv->prime.lock); | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | if (obj->export_dma_buf) { | ||
87 | get_dma_buf(obj->export_dma_buf); | ||
88 | *prime_fd = dma_buf_fd(obj->export_dma_buf, flags); | ||
89 | drm_gem_object_unreference_unlocked(obj); | ||
90 | } else { | ||
91 | buf = dev->driver->gem_prime_export(dev, obj, flags); | ||
92 | if (IS_ERR(buf)) { | ||
93 | /* normally the created dma-buf takes ownership of the ref, | ||
94 | * but if that fails then drop the ref | ||
95 | */ | ||
96 | drm_gem_object_unreference_unlocked(obj); | ||
97 | mutex_unlock(&file_priv->prime.lock); | ||
98 | return PTR_ERR(buf); | ||
99 | } | ||
100 | obj->export_dma_buf = buf; | ||
101 | *prime_fd = dma_buf_fd(buf, flags); | ||
102 | } | ||
103 | mutex_unlock(&file_priv->prime.lock); | ||
104 | return 0; | ||
105 | } | ||
106 | EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); | ||
107 | |||
108 | int drm_gem_prime_fd_to_handle(struct drm_device *dev, | ||
109 | struct drm_file *file_priv, int prime_fd, uint32_t *handle) | ||
110 | { | ||
111 | struct dma_buf *dma_buf; | ||
112 | struct drm_gem_object *obj; | ||
113 | int ret; | ||
114 | |||
115 | dma_buf = dma_buf_get(prime_fd); | ||
116 | if (IS_ERR(dma_buf)) | ||
117 | return PTR_ERR(dma_buf); | ||
118 | |||
119 | mutex_lock(&file_priv->prime.lock); | ||
120 | |||
121 | ret = drm_prime_lookup_imported_buf_handle(&file_priv->prime, | ||
122 | dma_buf, handle); | ||
123 | if (!ret) { | ||
124 | ret = 0; | ||
125 | goto out_put; | ||
126 | } | ||
127 | |||
128 | /* never seen this one, need to import */ | ||
129 | obj = dev->driver->gem_prime_import(dev, dma_buf); | ||
130 | if (IS_ERR(obj)) { | ||
131 | ret = PTR_ERR(obj); | ||
132 | goto out_put; | ||
133 | } | ||
134 | |||
135 | ret = drm_gem_handle_create(file_priv, obj, handle); | ||
136 | drm_gem_object_unreference_unlocked(obj); | ||
137 | if (ret) | ||
138 | goto out_put; | ||
139 | |||
140 | ret = drm_prime_add_imported_buf_handle(&file_priv->prime, | ||
141 | dma_buf, *handle); | ||
142 | if (ret) | ||
143 | goto fail; | ||
144 | |||
145 | mutex_unlock(&file_priv->prime.lock); | ||
146 | return 0; | ||
147 | |||
148 | fail: | ||
149 | /* hmm, if driver attached, we are relying on the free-object path | ||
150 | * to detach.. which seems ok.. | ||
151 | */ | ||
152 | drm_gem_object_handle_unreference_unlocked(obj); | ||
153 | out_put: | ||
154 | dma_buf_put(dma_buf); | ||
155 | mutex_unlock(&file_priv->prime.lock); | ||
156 | return ret; | ||
157 | } | ||
158 | EXPORT_SYMBOL(drm_gem_prime_fd_to_handle); | ||
159 | |||
160 | int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, | ||
161 | struct drm_file *file_priv) | ||
162 | { | ||
163 | struct drm_prime_handle *args = data; | ||
164 | uint32_t flags; | ||
165 | |||
166 | if (!drm_core_check_feature(dev, DRIVER_PRIME)) | ||
167 | return -EINVAL; | ||
168 | |||
169 | if (!dev->driver->prime_handle_to_fd) | ||
170 | return -ENOSYS; | ||
171 | |||
172 | /* check flags are valid */ | ||
173 | if (args->flags & ~DRM_CLOEXEC) | ||
174 | return -EINVAL; | ||
175 | |||
176 | /* we only want to pass DRM_CLOEXEC which is == O_CLOEXEC */ | ||
177 | flags = args->flags & DRM_CLOEXEC; | ||
178 | |||
179 | return dev->driver->prime_handle_to_fd(dev, file_priv, | ||
180 | args->handle, flags, &args->fd); | ||
181 | } | ||
182 | |||
183 | int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, | ||
184 | struct drm_file *file_priv) | ||
185 | { | ||
186 | struct drm_prime_handle *args = data; | ||
187 | |||
188 | if (!drm_core_check_feature(dev, DRIVER_PRIME)) | ||
189 | return -EINVAL; | ||
190 | |||
191 | if (!dev->driver->prime_fd_to_handle) | ||
192 | return -ENOSYS; | ||
193 | |||
194 | return dev->driver->prime_fd_to_handle(dev, file_priv, | ||
195 | args->fd, &args->handle); | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * drm_prime_pages_to_sg | ||
200 | * | ||
201 | * this helper creates an sg table object from a set of pages | ||
202 | * the driver is responsible for mapping the pages into the | ||
203 | * importers address space | ||
204 | */ | ||
205 | struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages) | ||
206 | { | ||
207 | struct sg_table *sg = NULL; | ||
208 | struct scatterlist *iter; | ||
209 | int i; | ||
210 | int ret; | ||
211 | |||
212 | sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); | ||
213 | if (!sg) | ||
214 | goto out; | ||
215 | |||
216 | ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL); | ||
217 | if (ret) | ||
218 | goto out; | ||
219 | |||
220 | for_each_sg(sg->sgl, iter, nr_pages, i) | ||
221 | sg_set_page(iter, pages[i], PAGE_SIZE, 0); | ||
222 | |||
223 | return sg; | ||
224 | out: | ||
225 | kfree(sg); | ||
226 | return NULL; | ||
227 | } | ||
228 | EXPORT_SYMBOL(drm_prime_pages_to_sg); | ||
229 | |||
230 | /* helper function to cleanup a GEM/prime object */ | ||
231 | void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) | ||
232 | { | ||
233 | struct dma_buf_attachment *attach; | ||
234 | struct dma_buf *dma_buf; | ||
235 | attach = obj->import_attach; | ||
236 | if (sg) | ||
237 | dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); | ||
238 | dma_buf = attach->dmabuf; | ||
239 | dma_buf_detach(attach->dmabuf, attach); | ||
240 | /* remove the reference */ | ||
241 | dma_buf_put(dma_buf); | ||
242 | } | ||
243 | EXPORT_SYMBOL(drm_prime_gem_destroy); | ||
244 | |||
245 | void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) | ||
246 | { | ||
247 | INIT_LIST_HEAD(&prime_fpriv->head); | ||
248 | mutex_init(&prime_fpriv->lock); | ||
249 | } | ||
250 | EXPORT_SYMBOL(drm_prime_init_file_private); | ||
251 | |||
252 | void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) | ||
253 | { | ||
254 | struct drm_prime_member *member, *safe; | ||
255 | list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { | ||
256 | list_del(&member->entry); | ||
257 | kfree(member); | ||
258 | } | ||
259 | } | ||
260 | EXPORT_SYMBOL(drm_prime_destroy_file_private); | ||
261 | |||
262 | int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) | ||
263 | { | ||
264 | struct drm_prime_member *member; | ||
265 | |||
266 | member = kmalloc(sizeof(*member), GFP_KERNEL); | ||
267 | if (!member) | ||
268 | return -ENOMEM; | ||
269 | |||
270 | member->dma_buf = dma_buf; | ||
271 | member->handle = handle; | ||
272 | list_add(&member->entry, &prime_fpriv->head); | ||
273 | return 0; | ||
274 | } | ||
275 | EXPORT_SYMBOL(drm_prime_add_imported_buf_handle); | ||
276 | |||
277 | int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle) | ||
278 | { | ||
279 | struct drm_prime_member *member; | ||
280 | |||
281 | list_for_each_entry(member, &prime_fpriv->head, entry) { | ||
282 | if (member->dma_buf == dma_buf) { | ||
283 | *handle = member->handle; | ||
284 | return 0; | ||
285 | } | ||
286 | } | ||
287 | return -ENOENT; | ||
288 | } | ||
289 | EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle); | ||
290 | |||
291 | void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) | ||
292 | { | ||
293 | struct drm_prime_member *member, *safe; | ||
294 | |||
295 | mutex_lock(&prime_fpriv->lock); | ||
296 | list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { | ||
297 | if (member->dma_buf == dma_buf) { | ||
298 | list_del(&member->entry); | ||
299 | kfree(member); | ||
300 | } | ||
301 | } | ||
302 | mutex_unlock(&prime_fpriv->lock); | ||
303 | } | ||
304 | EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle); | ||
diff --git a/include/drm/drm.h b/include/drm/drm.h index 34a7b89fd006..64ff02d5b730 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h | |||
@@ -617,6 +617,17 @@ struct drm_get_cap { | |||
617 | __u64 value; | 617 | __u64 value; |
618 | }; | 618 | }; |
619 | 619 | ||
620 | #define DRM_CLOEXEC O_CLOEXEC | ||
621 | struct drm_prime_handle { | ||
622 | __u32 handle; | ||
623 | |||
624 | /** Flags.. only applicable for handle->fd */ | ||
625 | __u32 flags; | ||
626 | |||
627 | /** Returned dmabuf file descriptor */ | ||
628 | __s32 fd; | ||
629 | }; | ||
630 | |||
620 | #include "drm_mode.h" | 631 | #include "drm_mode.h" |
621 | 632 | ||
622 | #define DRM_IOCTL_BASE 'd' | 633 | #define DRM_IOCTL_BASE 'd' |
@@ -673,7 +684,8 @@ struct drm_get_cap { | |||
673 | #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) | 684 | #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) |
674 | #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) | 685 | #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) |
675 | 686 | ||
676 | #define DRM_IOCTL_GEM_PRIME_OPEN DRM_IOWR(0x2e, struct drm_gem_open) | 687 | #define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) |
688 | #define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) | ||
677 | 689 | ||
678 | #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) | 690 | #define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) |
679 | #define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) | 691 | #define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 574bd1c81ebd..dd731043fecd 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -91,6 +91,7 @@ struct drm_device; | |||
91 | #define DRM_UT_CORE 0x01 | 91 | #define DRM_UT_CORE 0x01 |
92 | #define DRM_UT_DRIVER 0x02 | 92 | #define DRM_UT_DRIVER 0x02 |
93 | #define DRM_UT_KMS 0x04 | 93 | #define DRM_UT_KMS 0x04 |
94 | #define DRM_UT_PRIME 0x08 | ||
94 | /* | 95 | /* |
95 | * Three debug levels are defined. | 96 | * Three debug levels are defined. |
96 | * drm_core, drm_driver, drm_kms | 97 | * drm_core, drm_driver, drm_kms |
@@ -150,6 +151,7 @@ int drm_err(const char *func, const char *format, ...); | |||
150 | #define DRIVER_IRQ_VBL2 0x800 | 151 | #define DRIVER_IRQ_VBL2 0x800 |
151 | #define DRIVER_GEM 0x1000 | 152 | #define DRIVER_GEM 0x1000 |
152 | #define DRIVER_MODESET 0x2000 | 153 | #define DRIVER_MODESET 0x2000 |
154 | #define DRIVER_PRIME 0x4000 | ||
153 | 155 | ||
154 | #define DRIVER_BUS_PCI 0x1 | 156 | #define DRIVER_BUS_PCI 0x1 |
155 | #define DRIVER_BUS_PLATFORM 0x2 | 157 | #define DRIVER_BUS_PLATFORM 0x2 |
@@ -215,6 +217,11 @@ int drm_err(const char *func, const char *format, ...); | |||
215 | drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME, \ | 217 | drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME, \ |
216 | __func__, fmt, ##args); \ | 218 | __func__, fmt, ##args); \ |
217 | } while (0) | 219 | } while (0) |
220 | #define DRM_DEBUG_PRIME(fmt, args...) \ | ||
221 | do { \ | ||
222 | drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME, \ | ||
223 | __func__, fmt, ##args); \ | ||
224 | } while (0) | ||
218 | #define DRM_LOG(fmt, args...) \ | 225 | #define DRM_LOG(fmt, args...) \ |
219 | do { \ | 226 | do { \ |
220 | drm_ut_debug_printk(DRM_UT_CORE, NULL, \ | 227 | drm_ut_debug_printk(DRM_UT_CORE, NULL, \ |
@@ -238,6 +245,7 @@ int drm_err(const char *func, const char *format, ...); | |||
238 | #else | 245 | #else |
239 | #define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0) | 246 | #define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0) |
240 | #define DRM_DEBUG_KMS(fmt, args...) do { } while (0) | 247 | #define DRM_DEBUG_KMS(fmt, args...) do { } while (0) |
248 | #define DRM_DEBUG_PRIME(fmt, args...) do { } while (0) | ||
241 | #define DRM_DEBUG(fmt, arg...) do { } while (0) | 249 | #define DRM_DEBUG(fmt, arg...) do { } while (0) |
242 | #define DRM_LOG(fmt, arg...) do { } while (0) | 250 | #define DRM_LOG(fmt, arg...) do { } while (0) |
243 | #define DRM_LOG_KMS(fmt, args...) do { } while (0) | 251 | #define DRM_LOG_KMS(fmt, args...) do { } while (0) |
@@ -410,6 +418,12 @@ struct drm_pending_event { | |||
410 | void (*destroy)(struct drm_pending_event *event); | 418 | void (*destroy)(struct drm_pending_event *event); |
411 | }; | 419 | }; |
412 | 420 | ||
421 | /* initial implementaton using a linked list - todo hashtab */ | ||
422 | struct drm_prime_file_private { | ||
423 | struct list_head head; | ||
424 | struct mutex lock; | ||
425 | }; | ||
426 | |||
413 | /** File private data */ | 427 | /** File private data */ |
414 | struct drm_file { | 428 | struct drm_file { |
415 | int authenticated; | 429 | int authenticated; |
@@ -437,6 +451,8 @@ struct drm_file { | |||
437 | wait_queue_head_t event_wait; | 451 | wait_queue_head_t event_wait; |
438 | struct list_head event_list; | 452 | struct list_head event_list; |
439 | int event_space; | 453 | int event_space; |
454 | |||
455 | struct drm_prime_file_private prime; | ||
440 | }; | 456 | }; |
441 | 457 | ||
442 | /** Wait queue */ | 458 | /** Wait queue */ |
@@ -652,6 +668,12 @@ struct drm_gem_object { | |||
652 | uint32_t pending_write_domain; | 668 | uint32_t pending_write_domain; |
653 | 669 | ||
654 | void *driver_private; | 670 | void *driver_private; |
671 | |||
672 | /* dma buf exported from this GEM object */ | ||
673 | struct dma_buf *export_dma_buf; | ||
674 | |||
675 | /* dma buf attachment backing this object */ | ||
676 | struct dma_buf_attachment *import_attach; | ||
655 | }; | 677 | }; |
656 | 678 | ||
657 | #include "drm_crtc.h" | 679 | #include "drm_crtc.h" |
@@ -890,6 +912,20 @@ struct drm_driver { | |||
890 | int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); | 912 | int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); |
891 | void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); | 913 | void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); |
892 | 914 | ||
915 | /* prime: */ | ||
916 | /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */ | ||
917 | int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, | ||
918 | uint32_t handle, uint32_t flags, int *prime_fd); | ||
919 | /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */ | ||
920 | int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, | ||
921 | int prime_fd, uint32_t *handle); | ||
922 | /* export GEM -> dmabuf */ | ||
923 | struct dma_buf * (*gem_prime_export)(struct drm_device *dev, | ||
924 | struct drm_gem_object *obj, int flags); | ||
925 | /* import dmabuf -> GEM */ | ||
926 | struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, | ||
927 | struct dma_buf *dma_buf); | ||
928 | |||
893 | /* vga arb irq handler */ | 929 | /* vga arb irq handler */ |
894 | void (*vgaarb_irq)(struct drm_device *dev, bool state); | 930 | void (*vgaarb_irq)(struct drm_device *dev, bool state); |
895 | 931 | ||
@@ -1509,6 +1545,32 @@ extern int drm_vblank_info(struct seq_file *m, void *data); | |||
1509 | extern int drm_clients_info(struct seq_file *m, void* data); | 1545 | extern int drm_clients_info(struct seq_file *m, void* data); |
1510 | extern int drm_gem_name_info(struct seq_file *m, void *data); | 1546 | extern int drm_gem_name_info(struct seq_file *m, void *data); |
1511 | 1547 | ||
1548 | |||
1549 | extern int drm_gem_prime_handle_to_fd(struct drm_device *dev, | ||
1550 | struct drm_file *file_priv, uint32_t handle, uint32_t flags, | ||
1551 | int *prime_fd); | ||
1552 | extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, | ||
1553 | struct drm_file *file_priv, int prime_fd, uint32_t *handle); | ||
1554 | |||
1555 | extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, | ||
1556 | struct drm_file *file_priv); | ||
1557 | extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, | ||
1558 | struct drm_file *file_priv); | ||
1559 | |||
1560 | extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages); | ||
1561 | extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); | ||
1562 | |||
1563 | |||
1564 | void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv); | ||
1565 | void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv); | ||
1566 | int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle); | ||
1567 | int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle); | ||
1568 | void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf); | ||
1569 | |||
1570 | int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj); | ||
1571 | int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf, | ||
1572 | struct drm_gem_object **obj); | ||
1573 | |||
1512 | #if DRM_DEBUG_CODE | 1574 | #if DRM_DEBUG_CODE |
1513 | extern int drm_vma_info(struct seq_file *m, void *data); | 1575 | extern int drm_vma_info(struct seq_file *m, void *data); |
1514 | #endif | 1576 | #endif |