Pull dma-buf updates from Sumit Semwal: - use of vma_pages instead of explicit computation - DocBook and headerdoc updates for dma-buf * tag 'dma-buf-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sumits/dma-buf: dma-buf: use vma_pages() fence: add missing descriptions for fence doc: update/fixup dma-buf related DocBook reservation: add headerdoc comments dma-buf: headerdoc fixes
Unified · Split
| @@ -128,16 +128,44 @@ X!Edrivers/base/interface.c · 127 unmodified lines | ||
| 128 | 128 | !Edrivers/base/platform.c |
| 129 | 129 | !Edrivers/base/bus.c |
| 130 | 130 | </sect1> |
| 131 | − <sect1><title>Device Drivers DMA Management</title> | |
| 131 | + <sect1> | |
| 132 | + <title>Buffer Sharing and Synchronization</title> | |
| 133 | + <para> | |
| 134 | + The dma-buf subsystem provides the framework for sharing buffers | |
| 135 | + for hardware (DMA) access across multiple device drivers and | |
| 136 | + subsystems, and for synchronizing asynchronous hardware access. | |
| 137 | + </para> | |
| 138 | + <para> | |
| 139 | + This is used, for example, by drm "prime" multi-GPU support, but | |
| 140 | + is of course not limited to GPU use cases. | |
| 141 | + </para> | |
| 142 | + <para> | |
| 143 | + The three main components of this are: (1) dma-buf, representing | |
| 144 | + a sg_table and exposed to userspace as a file descriptor to allow | |
| 145 | + passing between devices, (2) fence, which provides a mechanism | |
| 146 | + to signal when one device as finished access, and (3) reservation, | |
| 147 | + which manages the shared or exclusive fence(s) associated with | |
| 148 | + the buffer. | |
| 149 | + </para> | |
| 150 | + <sect2><title>dma-buf</title> | |
| 132 | 151 | !Edrivers/dma-buf/dma-buf.c |
| 152 | +!Iinclude/linux/dma-buf.h | |
| 153 | + </sect2> | |
| 154 | + <sect2><title>reservation</title> | |
| 155 | +!Pdrivers/dma-buf/reservation.c Reservation Object Overview | |
| 156 | +!Edrivers/dma-buf/reservation.c | |
| 157 | +!Iinclude/linux/reservation.h | |
| 158 | + </sect2> | |
| 159 | + <sect2><title>fence</title> | |
| 133 | 160 | !Edrivers/dma-buf/fence.c |
| 134 | −!Edrivers/dma-buf/seqno-fence.c | |
| 135 | 161 | !Iinclude/linux/fence.h |
| 162 | +!Edrivers/dma-buf/seqno-fence.c | |
| 136 | 163 | !Iinclude/linux/seqno-fence.h |
| 137 | −!Edrivers/dma-buf/reservation.c | |
| 138 | −!Iinclude/linux/reservation.h | |
| 139 | 164 | !Edrivers/dma-buf/sync_file.c |
| 140 | 165 | !Iinclude/linux/sync_file.h |
| 166 | + </sect2> | |
| 167 | + </sect1> | |
| 168 | + <sect1><title>Device Drivers DMA Management</title> | |
| 141 | 169 | !Edrivers/base/dma-coherent.c |
| 142 | 170 | !Edrivers/base/dma-mapping.c |
| 143 | 171 | </sect1> |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/seq_file.h> |
| 34 | 34 | #include <linux/poll.h> |
| 35 | 35 | #include <linux/reservation.h> |
| 36 | +#include <linux/mm.h> | |
| 36 | 37 | |
| 37 | 38 | #include <uapi/linux/dma-buf.h> |
| 38 | 39 | |
| @@ -90,7 +91,7 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma) · 51 unmodified lines | ||
| 90 | 91 | dmabuf = file->private_data; |
| 91 | 92 | |
| 92 | 93 | /* check for overflowing the buffer's size */ |
| 93 | − if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > | |
| 94 | + if (vma->vm_pgoff + vma_pages(vma) > | |
| 94 | 95 | dmabuf->size >> PAGE_SHIFT) |
| 95 | 96 | return -EINVAL; |
| 96 | 97 | |
| @@ -723,11 +724,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, · 626 unmodified lines | ||
| 723 | 724 | return -EINVAL; |
| 724 | 725 | |
| 725 | 726 | /* check for offset overflow */ |
| 726 | − if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff) | |
| 727 | + if (pgoff + vma_pages(vma) < pgoff) | |
| 727 | 728 | return -EOVERFLOW; |
| 728 | 729 | |
| 729 | 730 | /* check for overflowing the buffer's size */ |
| 730 | − if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > | |
| 731 | + if (pgoff + vma_pages(vma) > | |
| 731 | 732 | dmabuf->size >> PAGE_SHIFT) |
| 732 | 733 | return -EINVAL; |
| 733 | 734 | |
| @@ -35,6 +35,17 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <linux/reservation.h> |
| 36 | 36 | #include <linux/export.h> |
| 37 | 37 | |
| 38 | +/** | |
| 39 | + * DOC: Reservation Object Overview | |
| 40 | + * | |
| 41 | + * The reservation object provides a mechanism to manage shared and | |
| 42 | + * exclusive fences associated with a buffer. A reservation object | |
| 43 | + * can have attached one exclusive fence (normally associated with | |
| 44 | + * write operations) or N shared fences (read operations). The RCU | |
| 45 | + * mechanism is used to protect read access to fences from locked | |
| 46 | + * write-side updates. | |
| 47 | + */ | |
| 48 | + | |
| 38 | 49 | DEFINE_WW_CLASS(reservation_ww_class); |
| 39 | 50 | EXPORT_SYMBOL(reservation_ww_class); |
| 40 | 51 | |
| @@ -43,9 +54,17 @@ EXPORT_SYMBOL(reservation_seqcount_class); · 2 unmodified lines | ||
| 43 | 54 | |
| 44 | 55 | const char reservation_seqcount_string[] = "reservation_seqcount"; |
| 45 | 56 | EXPORT_SYMBOL(reservation_seqcount_string); |
| 46 | −/* | |
| 47 | − * Reserve space to add a shared fence to a reservation_object, | |
| 48 | − * must be called with obj->lock held. | |
| 57 | + | |
| 58 | +/** | |
| 59 | + * reservation_object_reserve_shared - Reserve space to add a shared | |
| 60 | + * fence to a reservation_object. | |
| 61 | + * @obj: reservation object | |
| 62 | + * | |
| 63 | + * Should be called before reservation_object_add_shared_fence(). Must | |
| 64 | + * be called with obj->lock held. | |
| 65 | + * | |
| 66 | + * RETURNS | |
| 67 | + * Zero for success, or -errno | |
| 49 | 68 | */ |
| 50 | 69 | int reservation_object_reserve_shared(struct reservation_object *obj) |
| 51 | 70 | { |
| @@ -180,7 +199,11 @@ done: · 128 unmodified lines | ||
| 180 | 199 | fence_put(old_fence); |
| 181 | 200 | } |
| 182 | 201 | |
| 183 | −/* | |
| 202 | +/** | |
| 203 | + * reservation_object_add_shared_fence - Add a fence to a shared slot | |
| 204 | + * @obj: the reservation object | |
| 205 | + * @fence: the shared fence to add | |
| 206 | + * | |
| 184 | 207 | * Add a fence to a shared slot, obj->lock must be held, and |
| 185 | 208 | * reservation_object_reserve_shared_fence has been called. |
| 186 | 209 | */ |
| @@ -200,6 +223,13 @@ void reservation_object_add_shared_fence(struct reservation_object *obj, · 13 unmodified lines | ||
| 200 | 223 | } |
| 201 | 224 | EXPORT_SYMBOL(reservation_object_add_shared_fence); |
| 202 | 225 | |
| 226 | +/** | |
| 227 | + * reservation_object_add_excl_fence - Add an exclusive fence. | |
| 228 | + * @obj: the reservation object | |
| 229 | + * @fence: the shared fence to add | |
| 230 | + * | |
| 231 | + * Add a fence to the exclusive slot. The obj->lock must be held. | |
| 232 | + */ | |
| 203 | 233 | void reservation_object_add_excl_fence(struct reservation_object *obj, |
| 204 | 234 | struct fence *fence) |
| 205 | 235 | { |
| @@ -233,6 +263,18 @@ void reservation_object_add_excl_fence(struct reservation_object *obj, · 27 unmodified lines | ||
| 233 | 263 | } |
| 234 | 264 | EXPORT_SYMBOL(reservation_object_add_excl_fence); |
| 235 | 265 | |
| 266 | +/** | |
| 267 | + * reservation_object_get_fences_rcu - Get an object's shared and exclusive | |
| 268 | + * fences without update side lock held | |
| 269 | + * @obj: the reservation object | |
| 270 | + * @pfence_excl: the returned exclusive fence (or NULL) | |
| 271 | + * @pshared_count: the number of shared fences returned | |
| 272 | + * @pshared: the array of shared fence ptrs returned (array is krealloc'd to | |
| 273 | + * the required size, and must be freed by caller) | |
| 274 | + * | |
| 275 | + * RETURNS | |
| 276 | + * Zero or -errno | |
| 277 | + */ | |
| 236 | 278 | int reservation_object_get_fences_rcu(struct reservation_object *obj, |
| 237 | 279 | struct fence **pfence_excl, |
| 238 | 280 | unsigned *pshared_count, |
| @@ -319,6 +361,18 @@ unlock: · 80 unmodified lines | ||
| 319 | 361 | } |
| 320 | 362 | EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu); |
| 321 | 363 | |
| 364 | +/** | |
| 365 | + * reservation_object_wait_timeout_rcu - Wait on reservation's objects | |
| 366 | + * shared and/or exclusive fences. | |
| 367 | + * @obj: the reservation object | |
| 368 | + * @wait_all: if true, wait on all fences, else wait on just exclusive fence | |
| 369 | + * @intr: if true, do interruptible wait | |
| 370 | + * @timeout: timeout value in jiffies or zero to return immediately | |
| 371 | + * | |
| 372 | + * RETURNS | |
| 373 | + * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or | |
| 374 | + * greater than zer on success. | |
| 375 | + */ | |
| 322 | 376 | long reservation_object_wait_timeout_rcu(struct reservation_object *obj, |
| 323 | 377 | bool wait_all, bool intr, |
| 324 | 378 | unsigned long timeout) |
| @@ -416,6 +470,16 @@ reservation_object_test_signaled_single(struct fence *passed_fence) · 91 unmodified lines | ||
| 416 | 470 | return ret; |
| 417 | 471 | } |
| 418 | 472 | |
| 473 | +/** | |
| 474 | + * reservation_object_test_signaled_rcu - Test if a reservation object's | |
| 475 | + * fences have been signaled. | |
| 476 | + * @obj: the reservation object | |
| 477 | + * @test_all: if true, test all fences, otherwise only test the exclusive | |
| 478 | + * fence | |
| 479 | + * | |
| 480 | + * RETURNS | |
| 481 | + * true if all fences signaled, else false | |
| 482 | + */ | |
| 419 | 483 | bool reservation_object_test_signaled_rcu(struct reservation_object *obj, |
| 420 | 484 | bool test_all) |
| 421 | 485 | { |
| @@ -112,19 +112,24 @@ struct dma_buf_ops { · 111 unmodified lines | ||
| 112 | 112 | * @file: file pointer used for sharing buffers across, and for refcounting. |
| 113 | 113 | * @attachments: list of dma_buf_attachment that denotes all devices attached. |
| 114 | 114 | * @ops: dma_buf_ops associated with this buffer object. |
| 115 | + * @lock: used internally to serialize list manipulation, attach/detach and vmap/unmap | |
| 116 | + * @vmapping_counter: used internally to refcnt the vmaps | |
| 117 | + * @vmap_ptr: the current vmap ptr if vmapping_counter > 0 | |
| 115 | 118 | * @exp_name: name of the exporter; useful for debugging. |
| 116 | 119 | * @owner: pointer to exporter module; used for refcounting when exporter is a |
| 117 | 120 | * kernel module. |
| 118 | 121 | * @list_node: node for dma_buf accounting and debugging. |
| 119 | 122 | * @priv: exporter specific private data for this buffer object. |
| 120 | 123 | * @resv: reservation object linked to this dma-buf |
| 124 | + * @poll: for userspace poll support | |
| 125 | + * @cb_excl: for userspace poll support | |
| 126 | + * @cb_shared: for userspace poll support | |
| 121 | 127 | */ |
| 122 | 128 | struct dma_buf { |
| 123 | 129 | size_t size; |
| 124 | 130 | struct file *file; |
| 125 | 131 | struct list_head attachments; |
| 126 | 132 | const struct dma_buf_ops *ops; |
| 127 | − /* mutex to serialize list manipulation, attach/detach and vmap/unmap */ | |
| 128 | 133 | struct mutex lock; |
| 129 | 134 | unsigned vmapping_counter; |
| 130 | 135 | void *vmap_ptr; |
| @@ -188,9 +193,11 @@ struct dma_buf_export_info { · 57 unmodified lines | ||
| 188 | 193 | |
| 189 | 194 | /** |
| 190 | 195 | * helper macro for exporters; zeros and fills in most common values |
| 196 | + * | |
| 197 | + * @name: export-info name | |
| 191 | 198 | */ |
| 192 | −#define DEFINE_DMA_BUF_EXPORT_INFO(a) \ | |
| 193 | − struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME, \ | |
| 199 | +#define DEFINE_DMA_BUF_EXPORT_INFO(name) \ | |
| 200 | + struct dma_buf_export_info name = { .exp_name = KBUILD_MODNAME, \ | |
| 194 | 201 | .owner = THIS_MODULE } |
| 195 | 202 | |
| 196 | 203 | /** |
| @@ -49,6 +49,8 @@ struct fence_cb; · 48 unmodified lines | ||
| 49 | 49 | * @timestamp: Timestamp when the fence was signaled. |
| 50 | 50 | * @status: Optional, only valid if < 0, must be set before calling |
| 51 | 51 | * fence_signal, indicates that the fence has completed with an error. |
| 52 | + * @child_list: list of children fences | |
| 53 | + * @active_list: list of active fences | |
| 52 | 54 | * |
| 53 | 55 | * the flags member must be manipulated and read using the appropriate |
| 54 | 56 | * atomic ops (bit_*), so taking the spinlock will not be needed most |
| @@ -49,12 +49,27 @@ extern struct ww_class reservation_ww_class; · 48 unmodified lines | ||
| 49 | 49 | extern struct lock_class_key reservation_seqcount_class; |
| 50 | 50 | extern const char reservation_seqcount_string[]; |
| 51 | 51 | |
| 52 | +/** | |
| 53 | + * struct reservation_object_list - a list of shared fences | |
| 54 | + * @rcu: for internal use | |
| 55 | + * @shared_count: table of shared fences | |
| 56 | + * @shared_max: for growing shared fence table | |
| 57 | + * @shared: shared fence table | |
| 58 | + */ | |
| 52 | 59 | struct reservation_object_list { |
| 53 | 60 | struct rcu_head rcu; |
| 54 | 61 | u32 shared_count, shared_max; |
| 55 | 62 | struct fence __rcu *shared[]; |
| 56 | 63 | }; |
| 57 | 64 | |
| 65 | +/** | |
| 66 | + * struct reservation_object - a reservation object manages fences for a buffer | |
| 67 | + * @lock: update side lock | |
| 68 | + * @seq: sequence count for managing RCU read-side synchronization | |
| 69 | + * @fence_excl: the exclusive fence, if there is one currently | |
| 70 | + * @fence: list of current shared fences | |
| 71 | + * @staged: staged copy of shared fences for RCU updates | |
| 72 | + */ | |
| 58 | 73 | struct reservation_object { |
| 59 | 74 | struct ww_mutex lock; |
| 60 | 75 | seqcount_t seq; |
| @@ -68,6 +83,10 @@ struct reservation_object { · 7 unmodified lines | ||
| 68 | 83 | #define reservation_object_assert_held(obj) \ |
| 69 | 84 | lockdep_assert_held(&(obj)->lock.base) |
| 70 | 85 | |
| 86 | +/** | |
| 87 | + * reservation_object_init - initialize a reservation object | |
| 88 | + * @obj: the reservation object | |
| 89 | + */ | |
| 71 | 90 | static inline void |
| 72 | 91 | reservation_object_init(struct reservation_object *obj) |
| 73 | 92 | { |
| @@ -79,6 +98,10 @@ reservation_object_init(struct reservation_object *obj) · 5 unmodified lines | ||
| 79 | 98 | obj->staged = NULL; |
| 80 | 99 | } |
| 81 | 100 | |
| 101 | +/** | |
| 102 | + * reservation_object_fini - destroys a reservation object | |
| 103 | + * @obj: the reservation object | |
| 104 | + */ | |
| 82 | 105 | static inline void |
| 83 | 106 | reservation_object_fini(struct reservation_object *obj) |
| 84 | 107 | { |
| @@ -106,6 +129,14 @@ reservation_object_fini(struct reservation_object *obj) · 21 unmodified lines | ||
| 106 | 129 | ww_mutex_destroy(&obj->lock); |
| 107 | 130 | } |
| 108 | 131 | |
| 132 | +/** | |
| 133 | + * reservation_object_get_list - get the reservation object's | |
| 134 | + * shared fence list, with update-side lock held | |
| 135 | + * @obj: the reservation object | |
| 136 | + * | |
| 137 | + * Returns the shared fence list. Does NOT take references to | |
| 138 | + * the fence. The obj->lock must be held. | |
| 139 | + */ | |
| 109 | 140 | static inline struct reservation_object_list * |
| 110 | 141 | reservation_object_get_list(struct reservation_object *obj) |
| 111 | 142 | { |
| @@ -113,6 +144,17 @@ reservation_object_get_list(struct reservation_object *obj) · 1 unmodified line | ||
| 113 | 144 | reservation_object_held(obj)); |
| 114 | 145 | } |
| 115 | 146 | |
| 147 | +/** | |
| 148 | + * reservation_object_get_excl - get the reservation object's | |
| 149 | + * exclusive fence, with update-side lock held | |
| 150 | + * @obj: the reservation object | |
| 151 | + * | |
| 152 | + * Returns the exclusive fence (if any). Does NOT take a | |
| 153 | + * reference. The obj->lock must be held. | |
| 154 | + * | |
| 155 | + * RETURNS | |
| 156 | + * The exclusive fence or NULL | |
| 157 | + */ | |
| 116 | 158 | static inline struct fence * |
| 117 | 159 | reservation_object_get_excl(struct reservation_object *obj) |
| 118 | 160 | { |
| @@ -120,6 +162,17 @@ reservation_object_get_excl(struct reservation_object *obj) · 1 unmodified line | ||
| 120 | 162 | reservation_object_held(obj)); |
| 121 | 163 | } |
| 122 | 164 | |
| 165 | +/** | |
| 166 | + * reservation_object_get_excl_rcu - get the reservation object's | |
| 167 | + * exclusive fence, without lock held. | |
| 168 | + * @obj: the reservation object | |
| 169 | + * | |
| 170 | + * If there is an exclusive fence, this atomically increments it's | |
| 171 | + * reference count and returns it. | |
| 172 | + * | |
| 173 | + * RETURNS | |
| 174 | + * The exclusive fence or NULL if none | |
| 175 | + */ | |
| 123 | 176 | static inline struct fence * |
| 124 | 177 | reservation_object_get_excl_rcu(struct reservation_object *obj) |
| 125 | 178 | { |