History

Merge tag 'dma-buf-for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sumits/dma-buf

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

Linus Torvalds committed 10 years ago

Commit ebb8cb22 parents 6b15d66 b02da6f6 files · +169 −14Browse files

Unified · Split

6 files
  1. Documentation/DocBook/device-drivers.tmpl +32 −4
  2. drivers/dma-buf/dma-buf.c +4 −3
  3. drivers/dma-buf/reservation.c +68 −4
  4. include/linux/dma-buf.h +10 −3
  5. include/linux/fence.h +2 −0
  6. include/linux/reservation.h +53 −0
Documentation/DocBook/device-drivers.tmpl+32−4
@@ -128,16 +128,44 @@ X!Edrivers/base/interface.c · 127 unmodified lines
128!Edrivers/base/platform.c128!Edrivers/base/platform.c
129!Edrivers/base/bus.c129!Edrivers/base/bus.c
130 </sect1>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!Edrivers/dma-buf/dma-buf.c151!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!Edrivers/dma-buf/fence.c160!Edrivers/dma-buf/fence.c
134!Edrivers/dma-buf/seqno-fence.c
135!Iinclude/linux/fence.h161!Iinclude/linux/fence.h
162!Edrivers/dma-buf/seqno-fence.c
136!Iinclude/linux/seqno-fence.h163!Iinclude/linux/seqno-fence.h
137!Edrivers/dma-buf/reservation.c
138!Iinclude/linux/reservation.h
139!Edrivers/dma-buf/sync_file.c164!Edrivers/dma-buf/sync_file.c
140!Iinclude/linux/sync_file.h165!Iinclude/linux/sync_file.h
166 </sect2>
167 </sect1>
168 <sect1><title>Device Drivers DMA Management</title>
141!Edrivers/base/dma-coherent.c169!Edrivers/base/dma-coherent.c
142!Edrivers/base/dma-mapping.c170!Edrivers/base/dma-mapping.c
143 </sect1>171 </sect1>
drivers/dma-buf/dma-buf.c+4−3
@@ -33,6 +33,7 @@ · 32 unmodified lines
33#include <linux/seq_file.h>33#include <linux/seq_file.h>
34#include <linux/poll.h>34#include <linux/poll.h>
35#include <linux/reservation.h>35#include <linux/reservation.h>
36#include <linux/mm.h>
36 37
37#include <uapi/linux/dma-buf.h>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 dmabuf = file->private_data;91 dmabuf = file->private_data;
91 92
92 /* check for overflowing the buffer's size */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 dmabuf->size >> PAGE_SHIFT)95 dmabuf->size >> PAGE_SHIFT)
95 return -EINVAL;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 return -EINVAL;724 return -EINVAL;
724 725
725 /* check for offset overflow */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 return -EOVERFLOW;728 return -EOVERFLOW;
728 729
729 /* check for overflowing the buffer's size */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 dmabuf->size >> PAGE_SHIFT)732 dmabuf->size >> PAGE_SHIFT)
732 return -EINVAL;733 return -EINVAL;
733 734
drivers/dma-buf/reservation.c+68−4
@@ -35,6 +35,17 @@ · 34 unmodified lines
35#include <linux/reservation.h>35#include <linux/reservation.h>
36#include <linux/export.h>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
38DEFINE_WW_CLASS(reservation_ww_class);49DEFINE_WW_CLASS(reservation_ww_class);
39EXPORT_SYMBOL(reservation_ww_class);50EXPORT_SYMBOL(reservation_ww_class);
40 51
@@ -43,9 +54,17 @@ EXPORT_SYMBOL(reservation_seqcount_class); · 2 unmodified lines
43 54
44const char reservation_seqcount_string[] = "reservation_seqcount";55const char reservation_seqcount_string[] = "reservation_seqcount";
45EXPORT_SYMBOL(reservation_seqcount_string);56EXPORT_SYMBOL(reservation_seqcount_string);
46/*57
47 * Reserve space to add a shared fence to a reservation_object,58/**
48 * must be called with obj->lock held.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 */
50int reservation_object_reserve_shared(struct reservation_object *obj)69int reservation_object_reserve_shared(struct reservation_object *obj)
51{70{
@@ -180,7 +199,11 @@ done: · 128 unmodified lines
180 fence_put(old_fence);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 * Add a fence to a shared slot, obj->lock must be held, and207 * Add a fence to a shared slot, obj->lock must be held, and
185 * reservation_object_reserve_shared_fence has been called.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}
201EXPORT_SYMBOL(reservation_object_add_shared_fence);224EXPORT_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 */
203void reservation_object_add_excl_fence(struct reservation_object *obj,233void reservation_object_add_excl_fence(struct reservation_object *obj,
204 struct fence *fence)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}
234EXPORT_SYMBOL(reservation_object_add_excl_fence);264EXPORT_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 */
236int reservation_object_get_fences_rcu(struct reservation_object *obj,278int reservation_object_get_fences_rcu(struct reservation_object *obj,
237 struct fence **pfence_excl,279 struct fence **pfence_excl,
238 unsigned *pshared_count,280 unsigned *pshared_count,
@@ -319,6 +361,18 @@ unlock: · 80 unmodified lines
319}361}
320EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);362EXPORT_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 */
322long reservation_object_wait_timeout_rcu(struct reservation_object *obj,376long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
323 bool wait_all, bool intr,377 bool wait_all, bool intr,
324 unsigned long timeout)378 unsigned long timeout)
@@ -416,6 +470,16 @@ reservation_object_test_signaled_single(struct fence *passed_fence) · 91 unmodified lines
416 return ret;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 */
419bool reservation_object_test_signaled_rcu(struct reservation_object *obj,483bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
420 bool test_all)484 bool test_all)
421{485{
include/linux/dma-buf.h+10−3
@@ -112,19 +112,24 @@ struct dma_buf_ops { · 111 unmodified lines
112 * @file: file pointer used for sharing buffers across, and for refcounting.112 * @file: file pointer used for sharing buffers across, and for refcounting.
113 * @attachments: list of dma_buf_attachment that denotes all devices attached.113 * @attachments: list of dma_buf_attachment that denotes all devices attached.
114 * @ops: dma_buf_ops associated with this buffer object.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 * @exp_name: name of the exporter; useful for debugging.118 * @exp_name: name of the exporter; useful for debugging.
116 * @owner: pointer to exporter module; used for refcounting when exporter is a119 * @owner: pointer to exporter module; used for refcounting when exporter is a
117 * kernel module.120 * kernel module.
118 * @list_node: node for dma_buf accounting and debugging.121 * @list_node: node for dma_buf accounting and debugging.
119 * @priv: exporter specific private data for this buffer object.122 * @priv: exporter specific private data for this buffer object.
120 * @resv: reservation object linked to this dma-buf123 * @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 */
122struct dma_buf {128struct dma_buf {
123 size_t size;129 size_t size;
124 struct file *file;130 struct file *file;
125 struct list_head attachments;131 struct list_head attachments;
126 const struct dma_buf_ops *ops;132 const struct dma_buf_ops *ops;
127 /* mutex to serialize list manipulation, attach/detach and vmap/unmap */
128 struct mutex lock;133 struct mutex lock;
129 unsigned vmapping_counter;134 unsigned vmapping_counter;
130 void *vmap_ptr;135 void *vmap_ptr;
@@ -188,9 +193,11 @@ struct dma_buf_export_info { · 57 unmodified lines
188 193
189/**194/**
190 * helper macro for exporters; zeros and fills in most common values195 * 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) \199#define DEFINE_DMA_BUF_EXPORT_INFO(name) \
193 struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME, \200 struct dma_buf_export_info name = { .exp_name = KBUILD_MODNAME, \
194 .owner = THIS_MODULE }201 .owner = THIS_MODULE }
195 202
196/**203/**
include/linux/fence.h+2−0
@@ -49,6 +49,8 @@ struct fence_cb; · 48 unmodified lines
49 * @timestamp: Timestamp when the fence was signaled.49 * @timestamp: Timestamp when the fence was signaled.
50 * @status: Optional, only valid if < 0, must be set before calling50 * @status: Optional, only valid if < 0, must be set before calling
51 * fence_signal, indicates that the fence has completed with an error.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 * the flags member must be manipulated and read using the appropriate55 * the flags member must be manipulated and read using the appropriate
54 * atomic ops (bit_*), so taking the spinlock will not be needed most56 * atomic ops (bit_*), so taking the spinlock will not be needed most
include/linux/reservation.h+53−0
@@ -49,12 +49,27 @@ extern struct ww_class reservation_ww_class; · 48 unmodified lines
49extern struct lock_class_key reservation_seqcount_class;49extern struct lock_class_key reservation_seqcount_class;
50extern const char reservation_seqcount_string[];50extern 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 */
52struct reservation_object_list {59struct reservation_object_list {
53 struct rcu_head rcu;60 struct rcu_head rcu;
54 u32 shared_count, shared_max;61 u32 shared_count, shared_max;
55 struct fence __rcu *shared[];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 */
58struct reservation_object {73struct reservation_object {
59 struct ww_mutex lock;74 struct ww_mutex lock;
60 seqcount_t seq;75 seqcount_t seq;
@@ -68,6 +83,10 @@ struct reservation_object { · 7 unmodified lines
68#define reservation_object_assert_held(obj) \83#define reservation_object_assert_held(obj) \
69 lockdep_assert_held(&(obj)->lock.base)84 lockdep_assert_held(&(obj)->lock.base)
70 85
86/**
87 * reservation_object_init - initialize a reservation object
88 * @obj: the reservation object
89 */
71static inline void90static inline void
72reservation_object_init(struct reservation_object *obj)91reservation_object_init(struct reservation_object *obj)
73{92{
@@ -79,6 +98,10 @@ reservation_object_init(struct reservation_object *obj) · 5 unmodified lines
79 obj->staged = NULL;98 obj->staged = NULL;
80}99}
81 100
101/**
102 * reservation_object_fini - destroys a reservation object
103 * @obj: the reservation object
104 */
82static inline void105static inline void
83reservation_object_fini(struct reservation_object *obj)106reservation_object_fini(struct reservation_object *obj)
84{107{
@@ -106,6 +129,14 @@ reservation_object_fini(struct reservation_object *obj) · 21 unmodified lines
106 ww_mutex_destroy(&obj->lock);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 */
109static inline struct reservation_object_list *140static inline struct reservation_object_list *
110reservation_object_get_list(struct reservation_object *obj)141reservation_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 reservation_object_held(obj));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 */
116static inline struct fence *158static inline struct fence *
117reservation_object_get_excl(struct reservation_object *obj)159reservation_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 reservation_object_held(obj));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 */
123static inline struct fence *176static inline struct fence *
124reservation_object_get_excl_rcu(struct reservation_object *obj)177reservation_object_get_excl_rcu(struct reservation_object *obj)
125{178{

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t