diff options
-rw-r--r-- | Documentation/dmaengine/client.txt | 38 | ||||
-rw-r--r-- | Documentation/dmaengine/provider.txt | 20 | ||||
-rw-r--r-- | drivers/dma/dmaengine.c | 5 | ||||
-rw-r--r-- | include/linux/dmaengine.h | 90 |
4 files changed, 148 insertions, 5 deletions
diff --git a/Documentation/dmaengine/client.txt b/Documentation/dmaengine/client.txt index 11fb87ff6cd0..d9f9f461102a 100644 --- a/Documentation/dmaengine/client.txt +++ b/Documentation/dmaengine/client.txt | |||
@@ -128,7 +128,7 @@ The slave DMA usage consists of following steps: | |||
128 | transaction. | 128 | transaction. |
129 | 129 | ||
130 | For cyclic DMA, a callback function may wish to terminate the | 130 | For cyclic DMA, a callback function may wish to terminate the |
131 | DMA via dmaengine_terminate_all(). | 131 | DMA via dmaengine_terminate_async(). |
132 | 132 | ||
133 | Therefore, it is important that DMA engine drivers drop any | 133 | Therefore, it is important that DMA engine drivers drop any |
134 | locks before calling the callback function which may cause a | 134 | locks before calling the callback function which may cause a |
@@ -166,12 +166,29 @@ The slave DMA usage consists of following steps: | |||
166 | 166 | ||
167 | Further APIs: | 167 | Further APIs: |
168 | 168 | ||
169 | 1. int dmaengine_terminate_all(struct dma_chan *chan) | 169 | 1. int dmaengine_terminate_sync(struct dma_chan *chan) |
170 | int dmaengine_terminate_async(struct dma_chan *chan) | ||
171 | int dmaengine_terminate_all(struct dma_chan *chan) /* DEPRECATED */ | ||
170 | 172 | ||
171 | This causes all activity for the DMA channel to be stopped, and may | 173 | This causes all activity for the DMA channel to be stopped, and may |
172 | discard data in the DMA FIFO which hasn't been fully transferred. | 174 | discard data in the DMA FIFO which hasn't been fully transferred. |
173 | No callback functions will be called for any incomplete transfers. | 175 | No callback functions will be called for any incomplete transfers. |
174 | 176 | ||
177 | Two variants of this function are available. | ||
178 | |||
179 | dmaengine_terminate_async() might not wait until the DMA has been fully | ||
180 | stopped or until any running complete callbacks have finished. But it is | ||
181 | possible to call dmaengine_terminate_async() from atomic context or from | ||
182 | within a complete callback. dmaengine_synchronize() must be called before it | ||
183 | is safe to free the memory accessed by the DMA transfer or free resources | ||
184 | accessed from within the complete callback. | ||
185 | |||
186 | dmaengine_terminate_sync() will wait for the transfer and any running | ||
187 | complete callbacks to finish before it returns. But the function must not be | ||
188 | called from atomic context or from within a complete callback. | ||
189 | |||
190 | dmaengine_terminate_all() is deprecated and should not be used in new code. | ||
191 | |||
175 | 2. int dmaengine_pause(struct dma_chan *chan) | 192 | 2. int dmaengine_pause(struct dma_chan *chan) |
176 | 193 | ||
177 | This pauses activity on the DMA channel without data loss. | 194 | This pauses activity on the DMA channel without data loss. |
@@ -197,3 +214,20 @@ Further APIs: | |||
197 | a running DMA channel. It is recommended that DMA engine users | 214 | a running DMA channel. It is recommended that DMA engine users |
198 | pause or stop (via dmaengine_terminate_all()) the channel before | 215 | pause or stop (via dmaengine_terminate_all()) the channel before |
199 | using this API. | 216 | using this API. |
217 | |||
218 | 5. void dmaengine_synchronize(struct dma_chan *chan) | ||
219 | |||
220 | Synchronize the termination of the DMA channel to the current context. | ||
221 | |||
222 | This function should be used after dmaengine_terminate_async() to synchronize | ||
223 | the termination of the DMA channel to the current context. The function will | ||
224 | wait for the transfer and any running complete callbacks to finish before it | ||
225 | returns. | ||
226 | |||
227 | If dmaengine_terminate_async() is used to stop the DMA channel this function | ||
228 | must be called before it is safe to free memory accessed by previously | ||
229 | submitted descriptors or to free any resources accessed within the complete | ||
230 | callback of previously submitted descriptors. | ||
231 | |||
232 | The behavior of this function is undefined if dma_async_issue_pending() has | ||
233 | been called between dmaengine_terminate_async() and this function. | ||
diff --git a/Documentation/dmaengine/provider.txt b/Documentation/dmaengine/provider.txt index 67d4ce4df109..122b7f4876bb 100644 --- a/Documentation/dmaengine/provider.txt +++ b/Documentation/dmaengine/provider.txt | |||
@@ -327,8 +327,24 @@ supported. | |||
327 | 327 | ||
328 | * device_terminate_all | 328 | * device_terminate_all |
329 | - Aborts all the pending and ongoing transfers on the channel | 329 | - Aborts all the pending and ongoing transfers on the channel |
330 | - This command should operate synchronously on the channel, | 330 | - For aborted transfers the complete callback should not be called |
331 | terminating right away all the channels | 331 | - Can be called from atomic context or from within a complete |
332 | callback of a descriptor. Must not sleep. Drivers must be able | ||
333 | to handle this correctly. | ||
334 | - Termination may be asynchronous. The driver does not have to | ||
335 | wait until the currently active transfer has completely stopped. | ||
336 | See device_synchronize. | ||
337 | |||
338 | * device_synchronize | ||
339 | - Must synchronize the termination of a channel to the current | ||
340 | context. | ||
341 | - Must make sure that memory for previously submitted | ||
342 | descriptors is no longer accessed by the DMA controller. | ||
343 | - Must make sure that all complete callbacks for previously | ||
344 | submitted descriptors have finished running and none are | ||
345 | scheduled to run. | ||
346 | - May sleep. | ||
347 | |||
332 | 348 | ||
333 | Misc notes (stuff that should be documented, but don't really know | 349 | Misc notes (stuff that should be documented, but don't really know |
334 | where to put them) | 350 | where to put them) |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 3ecec1445adf..d6fc82e3986f 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -265,8 +265,11 @@ static void dma_chan_put(struct dma_chan *chan) | |||
265 | module_put(dma_chan_to_owner(chan)); | 265 | module_put(dma_chan_to_owner(chan)); |
266 | 266 | ||
267 | /* This channel is not in use anymore, free it */ | 267 | /* This channel is not in use anymore, free it */ |
268 | if (!chan->client_count && chan->device->device_free_chan_resources) | 268 | if (!chan->client_count && chan->device->device_free_chan_resources) { |
269 | /* Make sure all operations have completed */ | ||
270 | dmaengine_synchronize(chan); | ||
269 | chan->device->device_free_chan_resources(chan); | 271 | chan->device->device_free_chan_resources(chan); |
272 | } | ||
270 | 273 | ||
271 | /* If the channel is used via a DMA request router, free the mapping */ | 274 | /* If the channel is used via a DMA request router, free the mapping */ |
272 | if (chan->router && chan->router->route_free) { | 275 | if (chan->router && chan->router->route_free) { |
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index c47c68e535e8..4662d9aa6d5a 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h | |||
@@ -654,6 +654,8 @@ enum dmaengine_alignment { | |||
654 | * paused. Returns 0 or an error code | 654 | * paused. Returns 0 or an error code |
655 | * @device_terminate_all: Aborts all transfers on a channel. Returns 0 | 655 | * @device_terminate_all: Aborts all transfers on a channel. Returns 0 |
656 | * or an error code | 656 | * or an error code |
657 | * @device_synchronize: Synchronizes the termination of a transfers to the | ||
658 | * current context. | ||
657 | * @device_tx_status: poll for transaction completion, the optional | 659 | * @device_tx_status: poll for transaction completion, the optional |
658 | * txstate parameter can be supplied with a pointer to get a | 660 | * txstate parameter can be supplied with a pointer to get a |
659 | * struct with auxiliary transfer status information, otherwise the call | 661 | * struct with auxiliary transfer status information, otherwise the call |
@@ -737,6 +739,7 @@ struct dma_device { | |||
737 | int (*device_pause)(struct dma_chan *chan); | 739 | int (*device_pause)(struct dma_chan *chan); |
738 | int (*device_resume)(struct dma_chan *chan); | 740 | int (*device_resume)(struct dma_chan *chan); |
739 | int (*device_terminate_all)(struct dma_chan *chan); | 741 | int (*device_terminate_all)(struct dma_chan *chan); |
742 | void (*device_synchronize)(struct dma_chan *chan); | ||
740 | 743 | ||
741 | enum dma_status (*device_tx_status)(struct dma_chan *chan, | 744 | enum dma_status (*device_tx_status)(struct dma_chan *chan, |
742 | dma_cookie_t cookie, | 745 | dma_cookie_t cookie, |
@@ -828,6 +831,13 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_sg( | |||
828 | src_sg, src_nents, flags); | 831 | src_sg, src_nents, flags); |
829 | } | 832 | } |
830 | 833 | ||
834 | /** | ||
835 | * dmaengine_terminate_all() - Terminate all active DMA transfers | ||
836 | * @chan: The channel for which to terminate the transfers | ||
837 | * | ||
838 | * This function is DEPRECATED use either dmaengine_terminate_sync() or | ||
839 | * dmaengine_terminate_async() instead. | ||
840 | */ | ||
831 | static inline int dmaengine_terminate_all(struct dma_chan *chan) | 841 | static inline int dmaengine_terminate_all(struct dma_chan *chan) |
832 | { | 842 | { |
833 | if (chan->device->device_terminate_all) | 843 | if (chan->device->device_terminate_all) |
@@ -836,6 +846,86 @@ static inline int dmaengine_terminate_all(struct dma_chan *chan) | |||
836 | return -ENOSYS; | 846 | return -ENOSYS; |
837 | } | 847 | } |
838 | 848 | ||
849 | /** | ||
850 | * dmaengine_terminate_async() - Terminate all active DMA transfers | ||
851 | * @chan: The channel for which to terminate the transfers | ||
852 | * | ||
853 | * Calling this function will terminate all active and pending descriptors | ||
854 | * that have previously been submitted to the channel. It is not guaranteed | ||
855 | * though that the transfer for the active descriptor has stopped when the | ||
856 | * function returns. Furthermore it is possible the complete callback of a | ||
857 | * submitted transfer is still running when this function returns. | ||
858 | * | ||
859 | * dmaengine_synchronize() needs to be called before it is safe to free | ||
860 | * any memory that is accessed by previously submitted descriptors or before | ||
861 | * freeing any resources accessed from within the completion callback of any | ||
862 | * perviously submitted descriptors. | ||
863 | * | ||
864 | * This function can be called from atomic context as well as from within a | ||
865 | * complete callback of a descriptor submitted on the same channel. | ||
866 | * | ||
867 | * If none of the two conditions above apply consider using | ||
868 | * dmaengine_terminate_sync() instead. | ||
869 | */ | ||
870 | static inline int dmaengine_terminate_async(struct dma_chan *chan) | ||
871 | { | ||
872 | if (chan->device->device_terminate_all) | ||
873 | return chan->device->device_terminate_all(chan); | ||
874 | |||
875 | return -EINVAL; | ||
876 | } | ||
877 | |||
878 | /** | ||
879 | * dmaengine_synchronize() - Synchronize DMA channel termination | ||
880 | * @chan: The channel to synchronize | ||
881 | * | ||
882 | * Synchronizes to the DMA channel termination to the current context. When this | ||
883 | * function returns it is guaranteed that all transfers for previously issued | ||
884 | * descriptors have stopped and and it is safe to free the memory assoicated | ||
885 | * with them. Furthermore it is guaranteed that all complete callback functions | ||
886 | * for a previously submitted descriptor have finished running and it is safe to | ||
887 | * free resources accessed from within the complete callbacks. | ||
888 | * | ||
889 | * The behavior of this function is undefined if dma_async_issue_pending() has | ||
890 | * been called between dmaengine_terminate_async() and this function. | ||
891 | * | ||
892 | * This function must only be called from non-atomic context and must not be | ||
893 | * called from within a complete callback of a descriptor submitted on the same | ||
894 | * channel. | ||
895 | */ | ||
896 | static inline void dmaengine_synchronize(struct dma_chan *chan) | ||
897 | { | ||
898 | if (chan->device->device_synchronize) | ||
899 | chan->device->device_synchronize(chan); | ||
900 | } | ||
901 | |||
902 | /** | ||
903 | * dmaengine_terminate_sync() - Terminate all active DMA transfers | ||
904 | * @chan: The channel for which to terminate the transfers | ||
905 | * | ||
906 | * Calling this function will terminate all active and pending transfers | ||
907 | * that have previously been submitted to the channel. It is similar to | ||
908 | * dmaengine_terminate_async() but guarantees that the DMA transfer has actually | ||
909 | * stopped and that all complete callbacks have finished running when the | ||
910 | * function returns. | ||
911 | * | ||
912 | * This function must only be called from non-atomic context and must not be | ||
913 | * called from within a complete callback of a descriptor submitted on the same | ||
914 | * channel. | ||
915 | */ | ||
916 | static inline int dmaengine_terminate_sync(struct dma_chan *chan) | ||
917 | { | ||
918 | int ret; | ||
919 | |||
920 | ret = dmaengine_terminate_async(chan); | ||
921 | if (ret) | ||
922 | return ret; | ||
923 | |||
924 | dmaengine_synchronize(chan); | ||
925 | |||
926 | return 0; | ||
927 | } | ||
928 | |||
839 | static inline int dmaengine_pause(struct dma_chan *chan) | 929 | static inline int dmaengine_pause(struct dma_chan *chan) |
840 | { | 930 | { |
841 | if (chan->device->device_pause) | 931 | if (chan->device->device_pause) |