aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-08 17:05:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-08 17:05:09 -0500
commit8e369672af8700299ab372bad9397f230b1d591a (patch)
tree8676cfdb7f8c1ac5ee124aef050d541d70f876d0
parent6950d76c531671ec389e36183311826597951ac6 (diff)
parenta125a3945c950caef001f22055bf201a36568533 (diff)
Merge branch 'dma-buf-merge' of git://people.freedesktop.org/~airlied/linux
* 'dma-buf-merge' of git://people.freedesktop.org/~airlied/linux: dma-buf: mark EXPERIMENTAL for 1st release. dma-buf: Documentation for buffer sharing framework dma-buf: Introduce dma buffer sharing mechanism
-rw-r--r--Documentation/dma-buf-sharing.txt224
-rw-r--r--drivers/base/Kconfig11
-rw-r--r--drivers/base/Makefile1
-rw-r--r--drivers/base/dma-buf.c291
-rw-r--r--include/linux/dma-buf.h176
5 files changed, 703 insertions, 0 deletions
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt
new file mode 100644
index 00000000000..510eab32f39
--- /dev/null
+++ b/Documentation/dma-buf-sharing.txt
@@ -0,0 +1,224 @@
1 DMA Buffer Sharing API Guide
2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4 Sumit Semwal
5 <sumit dot semwal at linaro dot org>
6 <sumit dot semwal at ti dot com>
7
8This document serves as a guide to device-driver writers on what is the dma-buf
9buffer sharing API, how to use it for exporting and using shared buffers.
10
11Any device driver which wishes to be a part of DMA buffer sharing, can do so as
12either the 'exporter' of buffers, or the 'user' of buffers.
13
14Say a driver A wants to use buffers created by driver B, then we call B as the
15exporter, and A as buffer-user.
16
17The exporter
18- implements and manages operations[1] for the buffer
19- allows other users to share the buffer by using dma_buf sharing APIs,
20- manages the details of buffer allocation,
21- decides about the actual backing storage where this allocation happens,
22- takes care of any migration of scatterlist - for all (shared) users of this
23 buffer,
24
25The buffer-user
26- is one of (many) sharing users of the buffer.
27- doesn't need to worry about how the buffer is allocated, or where.
28- needs a mechanism to get access to the scatterlist that makes up this buffer
29 in memory, mapped into its own address space, so it can access the same area
30 of memory.
31
32*IMPORTANT*: [see https://lkml.org/lkml/2011/12/20/211 for more details]
33For this first version, A buffer shared using the dma_buf sharing API:
34- *may* be exported to user space using "mmap" *ONLY* by exporter, outside of
35 this framework.
36- may be used *ONLY* by importers that do not need CPU access to the buffer.
37
38The dma_buf buffer sharing API usage contains the following steps:
39
401. Exporter announces that it wishes to export a buffer
412. Userspace gets the file descriptor associated with the exported buffer, and
42 passes it around to potential buffer-users based on use case
433. Each buffer-user 'connects' itself to the buffer
444. When needed, buffer-user requests access to the buffer from exporter
455. When finished with its use, the buffer-user notifies end-of-DMA to exporter
466. when buffer-user is done using this buffer completely, it 'disconnects'
47 itself from the buffer.
48
49
501. Exporter's announcement of buffer export
51
52 The buffer exporter announces its wish to export a buffer. In this, it
53 connects its own private buffer data, provides implementation for operations
54 that can be performed on the exported dma_buf, and flags for the file
55 associated with this buffer.
56
57 Interface:
58 struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
59 size_t size, int flags)
60
61 If this succeeds, dma_buf_export allocates a dma_buf structure, and returns a
62 pointer to the same. It also associates an anonymous file with this buffer,
63 so it can be exported. On failure to allocate the dma_buf object, it returns
64 NULL.
65
662. Userspace gets a handle to pass around to potential buffer-users
67
68 Userspace entity requests for a file-descriptor (fd) which is a handle to the
69 anonymous file associated with the buffer. It can then share the fd with other
70 drivers and/or processes.
71
72 Interface:
73 int dma_buf_fd(struct dma_buf *dmabuf)
74
75 This API installs an fd for the anonymous file associated with this buffer;
76 returns either 'fd', or error.
77
783. Each buffer-user 'connects' itself to the buffer
79
80 Each buffer-user now gets a reference to the buffer, using the fd passed to
81 it.
82
83 Interface:
84 struct dma_buf *dma_buf_get(int fd)
85
86 This API will return a reference to the dma_buf, and increment refcount for
87 it.
88
89 After this, the buffer-user needs to attach its device with the buffer, which
90 helps the exporter to know of device buffer constraints.
91
92 Interface:
93 struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
94 struct device *dev)
95
96 This API returns reference to an attachment structure, which is then used
97 for scatterlist operations. It will optionally call the 'attach' dma_buf
98 operation, if provided by the exporter.
99
100 The dma-buf sharing framework does the bookkeeping bits related to managing
101 the list of all attachments to a buffer.
102
103Until this stage, the buffer-exporter has the option to choose not to actually
104allocate the backing storage for this buffer, but wait for the first buffer-user
105to request use of buffer for allocation.
106
107
1084. When needed, buffer-user requests access to the buffer
109
110 Whenever a buffer-user wants to use the buffer for any DMA, it asks for
111 access to the buffer using dma_buf_map_attachment API. At least one attach to
112 the buffer must have happened before map_dma_buf can be called.
113
114 Interface:
115 struct sg_table * dma_buf_map_attachment(struct dma_buf_attachment *,
116 enum dma_data_direction);
117
118 This is a wrapper to dma_buf->ops->map_dma_buf operation, which hides the
119 "dma_buf->ops->" indirection from the users of this interface.
120
121 In struct dma_buf_ops, map_dma_buf is defined as
122 struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,
123 enum dma_data_direction);
124
125 It is one of the buffer operations that must be implemented by the exporter.
126 It should return the sg_table containing scatterlist for this buffer, mapped
127 into caller's address space.
128
129 If this is being called for the first time, the exporter can now choose to
130 scan through the list of attachments for this buffer, collate the requirements
131 of the attached devices, and choose an appropriate backing storage for the
132 buffer.
133
134 Based on enum dma_data_direction, it might be possible to have multiple users
135 accessing at the same time (for reading, maybe), or any other kind of sharing
136 that the exporter might wish to make available to buffer-users.
137
138 map_dma_buf() operation can return -EINTR if it is interrupted by a signal.
139
140
1415. When finished, the buffer-user notifies end-of-DMA to exporter
142
143 Once the DMA for the current buffer-user is over, it signals 'end-of-DMA' to
144 the exporter using the dma_buf_unmap_attachment API.
145
146 Interface:
147 void dma_buf_unmap_attachment(struct dma_buf_attachment *,
148 struct sg_table *);
149
150 This is a wrapper to dma_buf->ops->unmap_dma_buf() operation, which hides the
151 "dma_buf->ops->" indirection from the users of this interface.
152
153 In struct dma_buf_ops, unmap_dma_buf is defined as
154 void (*unmap_dma_buf)(struct dma_buf_attachment *, struct sg_table *);
155
156 unmap_dma_buf signifies the end-of-DMA for the attachment provided. Like
157 map_dma_buf, this API also must be implemented by the exporter.
158
159
1606. when buffer-user is done using this buffer, it 'disconnects' itself from the
161 buffer.
162
163 After the buffer-user has no more interest in using this buffer, it should
164 disconnect itself from the buffer:
165
166 - it first detaches itself from the buffer.
167
168 Interface:
169 void dma_buf_detach(struct dma_buf *dmabuf,
170 struct dma_buf_attachment *dmabuf_attach);
171
172 This API removes the attachment from the list in dmabuf, and optionally calls
173 dma_buf->ops->detach(), if provided by exporter, for any housekeeping bits.
174
175 - Then, the buffer-user returns the buffer reference to exporter.
176
177 Interface:
178 void dma_buf_put(struct dma_buf *dmabuf);
179
180 This API then reduces the refcount for this buffer.
181
182 If, as a result of this call, the refcount becomes 0, the 'release' file
183 operation related to this fd is called. It calls the dmabuf->ops->release()
184 operation in turn, and frees the memory allocated for dmabuf when exported.
185
186NOTES:
187- Importance of attach-detach and {map,unmap}_dma_buf operation pairs
188 The attach-detach calls allow the exporter to figure out backing-storage
189 constraints for the currently-interested devices. This allows preferential
190 allocation, and/or migration of pages across different types of storage
191 available, if possible.
192
193 Bracketing of DMA access with {map,unmap}_dma_buf operations is essential
194 to allow just-in-time backing of storage, and migration mid-way through a
195 use-case.
196
197- Migration of backing storage if needed
198 If after
199 - at least one map_dma_buf has happened,
200 - and the backing storage has been allocated for this buffer,
201 another new buffer-user intends to attach itself to this buffer, it might
202 be allowed, if possible for the exporter.
203
204 In case it is allowed by the exporter:
205 if the new buffer-user has stricter 'backing-storage constraints', and the
206 exporter can handle these constraints, the exporter can just stall on the
207 map_dma_buf until all outstanding access is completed (as signalled by
208 unmap_dma_buf).
209 Once all users have finished accessing and have unmapped this buffer, the
210 exporter could potentially move the buffer to the stricter backing-storage,
211 and then allow further {map,unmap}_dma_buf operations from any buffer-user
212 from the migrated backing-storage.
213
214 If the exporter cannot fulfil the backing-storage constraints of the new
215 buffer-user device as requested, dma_buf_attach() would return an error to
216 denote non-compatibility of the new buffer-sharing request with the current
217 buffer.
218
219 If the exporter chooses not to allow an attach() operation once a
220 map_dma_buf() API has been called, it simply returns an error.
221
222References:
223[1] struct dma_buf_ops in include/linux/dma-buf.h
224[2] All interfaces mentioned above defined in include/linux/dma-buf.h
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 21cf46f4524..e95c67edb2c 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -174,4 +174,15 @@ config SYS_HYPERVISOR
174 174
175source "drivers/base/regmap/Kconfig" 175source "drivers/base/regmap/Kconfig"
176 176
177config DMA_SHARED_BUFFER
178 bool "Buffer framework to be shared between drivers"
179 default n
180 select ANON_INODES
181 depends on EXPERIMENTAL
182 help
183 This option enables the framework for buffer-sharing between
184 multiple drivers. A buffer is associated with a file using driver
185 APIs extension; the file's descriptor can then be passed on to other
186 driver.
187
177endmenu 188endmenu
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 1334d893b56..2c8272dd93c 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
9obj-y += power/ 9obj-y += power/
10obj-$(CONFIG_HAS_DMA) += dma-mapping.o 10obj-$(CONFIG_HAS_DMA) += dma-mapping.o
11obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o 11obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
12obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o
12obj-$(CONFIG_ISA) += isa.o 13obj-$(CONFIG_ISA) += isa.o
13obj-$(CONFIG_FW_LOADER) += firmware_class.o 14obj-$(CONFIG_FW_LOADER) += firmware_class.o
14obj-$(CONFIG_NUMA) += node.o 15obj-$(CONFIG_NUMA) += node.o
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
new file mode 100644
index 00000000000..e38ad243b4b
--- /dev/null
+++ b/drivers/base/dma-buf.c
@@ -0,0 +1,291 @@
1/*
2 * Framework for buffer objects that can be shared across devices/subsystems.
3 *
4 * Copyright(C) 2011 Linaro Limited. All rights reserved.
5 * Author: Sumit Semwal <sumit.semwal@ti.com>
6 *
7 * Many thanks to linaro-mm-sig list, and specially
8 * Arnd Bergmann <arnd@arndb.de>, Rob Clark <rob@ti.com> and
9 * Daniel Vetter <daniel@ffwll.ch> for their support in creation and
10 * refining of this idea.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published by
14 * the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25#include <linux/fs.h>
26#include <linux/slab.h>
27#include <linux/dma-buf.h>
28#include <linux/anon_inodes.h>
29#include <linux/export.h>
30
31static inline int is_dma_buf_file(struct file *);
32
33static int dma_buf_release(struct inode *inode, struct file *file)
34{
35 struct dma_buf *dmabuf;
36
37 if (!is_dma_buf_file(file))
38 return -EINVAL;
39
40 dmabuf = file->private_data;
41
42 dmabuf->ops->release(dmabuf);
43 kfree(dmabuf);
44 return 0;
45}
46
47static const struct file_operations dma_buf_fops = {
48 .release = dma_buf_release,
49};
50
51/*
52 * is_dma_buf_file - Check if struct file* is associated with dma_buf
53 */
54static inline int is_dma_buf_file(struct file *file)
55{
56 return file->f_op == &dma_buf_fops;
57}
58
59/**
60 * dma_buf_export - Creates a new dma_buf, and associates an anon file
61 * with this buffer, so it can be exported.
62 * Also connect the allocator specific data and ops to the buffer.
63 *
64 * @priv: [in] Attach private data of allocator to this buffer
65 * @ops: [in] Attach allocator-defined dma buf ops to the new buffer.
66 * @size: [in] Size of the buffer
67 * @flags: [in] mode flags for the file.
68 *
69 * Returns, on success, a newly created dma_buf object, which wraps the
70 * supplied private data and operations for dma_buf_ops. On either missing
71 * ops, or error in allocating struct dma_buf, will return negative error.
72 *
73 */
74struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
75 size_t size, int flags)
76{
77 struct dma_buf *dmabuf;
78 struct file *file;
79
80 if (WARN_ON(!priv || !ops
81 || !ops->map_dma_buf
82 || !ops->unmap_dma_buf
83 || !ops->release)) {
84 return ERR_PTR(-EINVAL);
85 }
86
87 dmabuf = kzalloc(sizeof(struct dma_buf), GFP_KERNEL);
88 if (dmabuf == NULL)
89 return ERR_PTR(-ENOMEM);
90
91 dmabuf->priv = priv;
92 dmabuf->ops = ops;
93 dmabuf->size = size;
94
95 file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags);
96
97 dmabuf->file = file;
98
99 mutex_init(&dmabuf->lock);
100 INIT_LIST_HEAD(&dmabuf->attachments);
101
102 return dmabuf;
103}
104EXPORT_SYMBOL_GPL(dma_buf_export);
105
106
107/**
108 * dma_buf_fd - returns a file descriptor for the given dma_buf
109 * @dmabuf: [in] pointer to dma_buf for which fd is required.
110 *
111 * On success, returns an associated 'fd'. Else, returns error.
112 */
113int dma_buf_fd(struct dma_buf *dmabuf)
114{
115 int error, fd;
116
117 if (!dmabuf || !dmabuf->file)
118 return -EINVAL;
119
120 error = get_unused_fd();
121 if (error < 0)
122 return error;
123 fd = error;
124
125 fd_install(fd, dmabuf->file);
126
127 return fd;
128}
129EXPORT_SYMBOL_GPL(dma_buf_fd);
130
131/**
132 * dma_buf_get - returns the dma_buf structure related to an fd
133 * @fd: [in] fd associated with the dma_buf to be returned
134 *
135 * On success, returns the dma_buf structure associated with an fd; uses
136 * file's refcounting done by fget to increase refcount. returns ERR_PTR
137 * otherwise.
138 */
139struct dma_buf *dma_buf_get(int fd)
140{
141 struct file *file;
142
143 file = fget(fd);
144
145 if (!file)
146 return ERR_PTR(-EBADF);
147
148 if (!is_dma_buf_file(file)) {
149 fput(file);
150 return ERR_PTR(-EINVAL);
151 }
152
153 return file->private_data;
154}
155EXPORT_SYMBOL_GPL(dma_buf_get);
156
157/**
158 * dma_buf_put - decreases refcount of the buffer
159 * @dmabuf: [in] buffer to reduce refcount of
160 *
161 * Uses file's refcounting done implicitly by fput()
162 */
163void dma_buf_put(struct dma_buf *dmabuf)
164{
165 if (WARN_ON(!dmabuf || !dmabuf->file))
166 return;
167
168 fput(dmabuf->file);
169}
170EXPORT_SYMBOL_GPL(dma_buf_put);
171
172/**
173 * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
174 * calls attach() of dma_buf_ops to allow device-specific attach functionality
175 * @dmabuf: [in] buffer to attach device to.
176 * @dev: [in] device to be attached.
177 *
178 * Returns struct dma_buf_attachment * for this attachment; may return negative
179 * error codes.
180 *
181 */
182struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
183 struct device *dev)
184{
185 struct dma_buf_attachment *attach;
186 int ret;
187
188 if (WARN_ON(!dmabuf || !dev || !dmabuf->ops))
189 return ERR_PTR(-EINVAL);
190
191 attach = kzalloc(sizeof(struct dma_buf_attachment), GFP_KERNEL);
192 if (attach == NULL)
193 goto err_alloc;
194
195 mutex_lock(&dmabuf->lock);
196
197 attach->dev = dev;
198 attach->dmabuf = dmabuf;
199 if (dmabuf->ops->attach) {
200 ret = dmabuf->ops->attach(dmabuf, dev, attach);
201 if (ret)
202 goto err_attach;
203 }
204 list_add(&attach->node, &dmabuf->attachments);
205
206 mutex_unlock(&dmabuf->lock);
207 return attach;
208
209err_alloc:
210 return ERR_PTR(-ENOMEM);
211err_attach:
212 kfree(attach);
213 mutex_unlock(&dmabuf->lock);
214 return ERR_PTR(ret);
215}
216EXPORT_SYMBOL_GPL(dma_buf_attach);
217
218/**
219 * dma_buf_detach - Remove the given attachment from dmabuf's attachments list;
220 * optionally calls detach() of dma_buf_ops for device-specific detach
221 * @dmabuf: [in] buffer to detach from.
222 * @attach: [in] attachment to be detached; is free'd after this call.
223 *
224 */
225void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
226{
227 if (WARN_ON(!dmabuf || !attach || !dmabuf->ops))
228 return;
229
230 mutex_lock(&dmabuf->lock);
231 list_del(&attach->node);
232 if (dmabuf->ops->detach)
233 dmabuf->ops->detach(dmabuf, attach);
234
235 mutex_unlock(&dmabuf->lock);
236 kfree(attach);
237}
238EXPORT_SYMBOL_GPL(dma_buf_detach);
239
240/**
241 * dma_buf_map_attachment - Returns the scatterlist table of the attachment;
242 * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
243 * dma_buf_ops.
244 * @attach: [in] attachment whose scatterlist is to be returned
245 * @direction: [in] direction of DMA transfer
246 *
247 * Returns sg_table containing the scatterlist to be returned; may return NULL
248 * or ERR_PTR.
249 *
250 */
251struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
252 enum dma_data_direction direction)
253{
254 struct sg_table *sg_table = ERR_PTR(-EINVAL);
255
256 might_sleep();
257
258 if (WARN_ON(!attach || !attach->dmabuf || !attach->dmabuf->ops))
259 return ERR_PTR(-EINVAL);
260
261 mutex_lock(&attach->dmabuf->lock);
262 if (attach->dmabuf->ops->map_dma_buf)
263 sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
264 mutex_unlock(&attach->dmabuf->lock);
265
266 return sg_table;
267}
268EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
269
270/**
271 * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
272 * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
273 * dma_buf_ops.
274 * @attach: [in] attachment to unmap buffer from
275 * @sg_table: [in] scatterlist info of the buffer to unmap
276 *
277 */
278void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
279 struct sg_table *sg_table)
280{
281 if (WARN_ON(!attach || !attach->dmabuf || !sg_table
282 || !attach->dmabuf->ops))
283 return;
284
285 mutex_lock(&attach->dmabuf->lock);
286 if (attach->dmabuf->ops->unmap_dma_buf)
287 attach->dmabuf->ops->unmap_dma_buf(attach, sg_table);
288 mutex_unlock(&attach->dmabuf->lock);
289
290}
291EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
new file mode 100644
index 00000000000..f8ac076afa5
--- /dev/null
+++ b/include/linux/dma-buf.h
@@ -0,0 +1,176 @@
1/*
2 * Header file for dma buffer sharing framework.
3 *
4 * Copyright(C) 2011 Linaro Limited. All rights reserved.
5 * Author: Sumit Semwal <sumit.semwal@ti.com>
6 *
7 * Many thanks to linaro-mm-sig list, and specially
8 * Arnd Bergmann <arnd@arndb.de>, Rob Clark <rob@ti.com> and
9 * Daniel Vetter <daniel@ffwll.ch> for their support in creation and
10 * refining of this idea.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published by
14 * the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24#ifndef __DMA_BUF_H__
25#define __DMA_BUF_H__
26
27#include <linux/file.h>
28#include <linux/err.h>
29#include <linux/device.h>
30#include <linux/scatterlist.h>
31#include <linux/list.h>
32#include <linux/dma-mapping.h>
33
34struct dma_buf;
35struct dma_buf_attachment;
36
37/**
38 * struct dma_buf_ops - operations possible on struct dma_buf
39 * @attach: [optional] allows different devices to 'attach' themselves to the
40 * given buffer. It might return -EBUSY to signal that backing storage
41 * is already allocated and incompatible with the requirements
42 * of requesting device.
43 * @detach: [optional] detach a given device from this buffer.
44 * @map_dma_buf: returns list of scatter pages allocated, increases usecount
45 * of the buffer. Requires atleast one attach to be called
46 * before. Returned sg list should already be mapped into
47 * _device_ address space. This call may sleep. May also return
48 * -EINTR. Should return -EINVAL if attach hasn't been called yet.
49 * @unmap_dma_buf: decreases usecount of buffer, might deallocate scatter
50 * pages.
51 * @release: release this buffer; to be called after the last dma_buf_put.
52 */
53struct dma_buf_ops {
54 int (*attach)(struct dma_buf *, struct device *,
55 struct dma_buf_attachment *);
56
57 void (*detach)(struct dma_buf *, struct dma_buf_attachment *);
58
59 /* For {map,unmap}_dma_buf below, any specific buffer attributes
60 * required should get added to device_dma_parameters accessible
61 * via dev->dma_params.
62 */
63 struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,
64 enum dma_data_direction);
65 void (*unmap_dma_buf)(struct dma_buf_attachment *,
66 struct sg_table *);
67 /* TODO: Add try_map_dma_buf version, to return immed with -EBUSY
68 * if the call would block.
69 */
70
71 /* after final dma_buf_put() */
72 void (*release)(struct dma_buf *);
73
74};
75
76/**
77 * struct dma_buf - shared buffer object
78 * @size: size of the buffer
79 * @file: file pointer used for sharing buffers across, and for refcounting.
80 * @attachments: list of dma_buf_attachment that denotes all devices attached.
81 * @ops: dma_buf_ops associated with this buffer object.
82 * @priv: exporter specific private data for this buffer object.
83 */
84struct dma_buf {
85 size_t size;
86 struct file *file;
87 struct list_head attachments;
88 const struct dma_buf_ops *ops;
89 /* mutex to serialize list manipulation and other ops */
90 struct mutex lock;
91 void *priv;
92};
93
94/**
95 * struct dma_buf_attachment - holds device-buffer attachment data
96 * @dmabuf: buffer for this attachment.
97 * @dev: device attached to the buffer.
98 * @node: list of dma_buf_attachment.
99 * @priv: exporter specific attachment data.
100 *
101 * This structure holds the attachment information between the dma_buf buffer
102 * and its user device(s). The list contains one attachment struct per device
103 * attached to the buffer.
104 */
105struct dma_buf_attachment {
106 struct dma_buf *dmabuf;
107 struct device *dev;
108 struct list_head node;
109 void *priv;
110};
111
112#ifdef CONFIG_DMA_SHARED_BUFFER
113struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
114 struct device *dev);
115void dma_buf_detach(struct dma_buf *dmabuf,
116 struct dma_buf_attachment *dmabuf_attach);
117struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops,
118 size_t size, int flags);
119int dma_buf_fd(struct dma_buf *dmabuf);
120struct dma_buf *dma_buf_get(int fd);
121void dma_buf_put(struct dma_buf *dmabuf);
122
123struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *,
124 enum dma_data_direction);
125void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *);
126#else
127
128static inline struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
129 struct device *dev)
130{
131 return ERR_PTR(-ENODEV);
132}
133
134static inline void dma_buf_detach(struct dma_buf *dmabuf,
135 struct dma_buf_attachment *dmabuf_attach)
136{
137 return;
138}
139
140static inline struct dma_buf *dma_buf_export(void *priv,
141 struct dma_buf_ops *ops,
142 size_t size, int flags)
143{
144 return ERR_PTR(-ENODEV);
145}
146
147static inline int dma_buf_fd(struct dma_buf *dmabuf)
148{
149 return -ENODEV;
150}
151
152static inline struct dma_buf *dma_buf_get(int fd)
153{
154 return ERR_PTR(-ENODEV);
155}
156
157static inline void dma_buf_put(struct dma_buf *dmabuf)
158{
159 return;
160}
161
162static inline struct sg_table *dma_buf_map_attachment(
163 struct dma_buf_attachment *attach, enum dma_data_direction write)
164{
165 return ERR_PTR(-ENODEV);
166}
167
168static inline void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
169 struct sg_table *sg)
170{
171 return;
172}
173
174#endif /* CONFIG_DMA_SHARED_BUFFER */
175
176#endif /* __DMA_BUF_H__ */