Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+703
+224
Documentation/dma-buf-sharing.txt
··· 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 + 8 + This document serves as a guide to device-driver writers on what is the dma-buf 9 + buffer sharing API, how to use it for exporting and using shared buffers. 10 + 11 + Any device driver which wishes to be a part of DMA buffer sharing, can do so as 12 + either the 'exporter' of buffers, or the 'user' of buffers. 13 + 14 + Say a driver A wants to use buffers created by driver B, then we call B as the 15 + exporter, and A as buffer-user. 16 + 17 + The 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 + 25 + The 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] 33 + For 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 + 38 + The dma_buf buffer sharing API usage contains the following steps: 39 + 40 + 1. Exporter announces that it wishes to export a buffer 41 + 2. Userspace gets the file descriptor associated with the exported buffer, and 42 + passes it around to potential buffer-users based on use case 43 + 3. Each buffer-user 'connects' itself to the buffer 44 + 4. When needed, buffer-user requests access to the buffer from exporter 45 + 5. When finished with its use, the buffer-user notifies end-of-DMA to exporter 46 + 6. when buffer-user is done using this buffer completely, it 'disconnects' 47 + itself from the buffer. 48 + 49 + 50 + 1. 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 + 66 + 2. 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 + 78 + 3. 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 + 103 + Until this stage, the buffer-exporter has the option to choose not to actually 104 + allocate the backing storage for this buffer, but wait for the first buffer-user 105 + to request use of buffer for allocation. 106 + 107 + 108 + 4. 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 + 141 + 5. 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 + 160 + 6. 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 + 186 + NOTES: 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 + 222 + References: 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
+11
drivers/base/Kconfig
··· 174 174 175 175 source "drivers/base/regmap/Kconfig" 176 176 177 + config 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 + 177 188 endmenu
+1
drivers/base/Makefile
··· 9 9 obj-y += power/ 10 10 obj-$(CONFIG_HAS_DMA) += dma-mapping.o 11 11 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o 12 + obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o 12 13 obj-$(CONFIG_ISA) += isa.o 13 14 obj-$(CONFIG_FW_LOADER) += firmware_class.o 14 15 obj-$(CONFIG_NUMA) += node.o
+291
drivers/base/dma-buf.c
··· 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 + 31 + static inline int is_dma_buf_file(struct file *); 32 + 33 + static 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 + 47 + static 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 + */ 54 + static 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 + */ 74 + struct 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 + } 104 + EXPORT_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 + */ 113 + int 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 + } 129 + EXPORT_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 + */ 139 + struct 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 + } 155 + EXPORT_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 + */ 163 + void dma_buf_put(struct dma_buf *dmabuf) 164 + { 165 + if (WARN_ON(!dmabuf || !dmabuf->file)) 166 + return; 167 + 168 + fput(dmabuf->file); 169 + } 170 + EXPORT_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 + */ 182 + struct 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 + 209 + err_alloc: 210 + return ERR_PTR(-ENOMEM); 211 + err_attach: 212 + kfree(attach); 213 + mutex_unlock(&dmabuf->lock); 214 + return ERR_PTR(ret); 215 + } 216 + EXPORT_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 + */ 225 + void 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 + } 238 + EXPORT_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 + */ 251 + struct 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 + } 268 + EXPORT_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 + */ 278 + void 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 + } 291 + EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
+176
include/linux/dma-buf.h
··· 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 + 34 + struct dma_buf; 35 + struct 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 + */ 53 + struct 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 + */ 84 + struct 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 + */ 105 + struct 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 113 + struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, 114 + struct device *dev); 115 + void dma_buf_detach(struct dma_buf *dmabuf, 116 + struct dma_buf_attachment *dmabuf_attach); 117 + struct dma_buf *dma_buf_export(void *priv, struct dma_buf_ops *ops, 118 + size_t size, int flags); 119 + int dma_buf_fd(struct dma_buf *dmabuf); 120 + struct dma_buf *dma_buf_get(int fd); 121 + void dma_buf_put(struct dma_buf *dmabuf); 122 + 123 + struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *, 124 + enum dma_data_direction); 125 + void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *); 126 + #else 127 + 128 + static inline struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, 129 + struct device *dev) 130 + { 131 + return ERR_PTR(-ENODEV); 132 + } 133 + 134 + static inline void dma_buf_detach(struct dma_buf *dmabuf, 135 + struct dma_buf_attachment *dmabuf_attach) 136 + { 137 + return; 138 + } 139 + 140 + static 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 + 147 + static inline int dma_buf_fd(struct dma_buf *dmabuf) 148 + { 149 + return -ENODEV; 150 + } 151 + 152 + static inline struct dma_buf *dma_buf_get(int fd) 153 + { 154 + return ERR_PTR(-ENODEV); 155 + } 156 + 157 + static inline void dma_buf_put(struct dma_buf *dmabuf) 158 + { 159 + return; 160 + } 161 + 162 + static 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 + 168 + static 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__ */