apm821xx: remove 4.4 kernel support
[openwrt/staging/lynxis/omap.git] / target / linux / apm821xx / patches-4.4 / 012-dmaengine-Add-transfer-termination-synchronization-s.patch
diff --git a/target/linux/apm821xx/patches-4.4/012-dmaengine-Add-transfer-termination-synchronization-s.patch b/target/linux/apm821xx/patches-4.4/012-dmaengine-Add-transfer-termination-synchronization-s.patch
deleted file mode 100644 (file)
index 21efb04..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-From b36f09c3c441a6e59eab9315032e7d546571de3f Mon Sep 17 00:00:00 2001
-From: Lars-Peter Clausen <lars@metafoo.de>
-Date: Tue, 20 Oct 2015 11:46:28 +0200
-Subject: [PATCH] dmaengine: Add transfer termination synchronization support
-
-The DMAengine API has a long standing race condition that is inherent to
-the API itself. Calling dmaengine_terminate_all() is supposed to stop and
-abort any pending or active transfers that have previously been submitted.
-Unfortunately it is possible that this operation races against a currently
-running (or with some drivers also scheduled) completion callback.
-
-Since the API allows dmaengine_terminate_all() to be called from atomic
-context as well as from within a completion callback it is not possible to
-synchronize to the execution of the completion callback from within
-dmaengine_terminate_all() itself.
-
-This means that a user of the DMAengine API does not know when it is safe
-to free resources used in the completion callback, which can result in a
-use-after-free race condition.
-
-This patch addresses the issue by introducing an explicit synchronization
-primitive to the DMAengine API called dmaengine_synchronize().
-
-The existing dmaengine_terminate_all() is deprecated in favor of
-dmaengine_terminate_sync() and dmaengine_terminate_async(). The former
-aborts all pending and active transfers and synchronizes to the current
-context, meaning it will wait until all running completion callbacks have
-finished. This means it is only possible to call this function from
-non-atomic context. The later function does not synchronize, but can still
-be used in atomic context or from within a complete callback. It has to be
-followed up by dmaengine_synchronize() before a client can free the
-resources used in a completion callback.
-
-In addition to this the semantics of the device_terminate_all() callback
-are slightly relaxed by this patch. It is now OK for a driver to only
-schedule the termination of the active transfer, but does not necessarily
-have to wait until the DMA controller has completely stopped. The driver
-must ensure though that the controller has stopped and no longer accesses
-any memory when the device_synchronize() callback returns.
-
-This was in part done since most drivers do not pay attention to this
-anyway at the moment and to emphasize that this needs to be done when the
-device_synchronize() callback is implemented. But it also helps with
-implementing support for devices where stopping the controller can require
-operations that may sleep.
-
-Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
-Signed-off-by: Vinod Koul <vinod.koul@intel.com>
----
- Documentation/dmaengine/client.txt   | 38 ++++++++++++++-
- Documentation/dmaengine/provider.txt | 20 +++++++-
- drivers/dma/dmaengine.c              |  5 +-
- include/linux/dmaengine.h            | 90 ++++++++++++++++++++++++++++++++++++
- 4 files changed, 148 insertions(+), 5 deletions(-)
-
---- a/Documentation/dmaengine/client.txt
-+++ b/Documentation/dmaengine/client.txt
-@@ -117,7 +117,7 @@ The slave DMA usage consists of followin
-       transaction.
-       For cyclic DMA, a callback function may wish to terminate the
--      DMA via dmaengine_terminate_all().
-+      DMA via dmaengine_terminate_async().
-       Therefore, it is important that DMA engine drivers drop any
-       locks before calling the callback function which may cause a
-@@ -155,12 +155,29 @@ The slave DMA usage consists of followin
- Further APIs:
--1. int dmaengine_terminate_all(struct dma_chan *chan)
-+1. int dmaengine_terminate_sync(struct dma_chan *chan)
-+   int dmaengine_terminate_async(struct dma_chan *chan)
-+   int dmaengine_terminate_all(struct dma_chan *chan) /* DEPRECATED */
-    This causes all activity for the DMA channel to be stopped, and may
-    discard data in the DMA FIFO which hasn't been fully transferred.
-    No callback functions will be called for any incomplete transfers.
-+   Two variants of this function are available.
-+
-+   dmaengine_terminate_async() might not wait until the DMA has been fully
-+   stopped or until any running complete callbacks have finished. But it is
-+   possible to call dmaengine_terminate_async() from atomic context or from
-+   within a complete callback. dmaengine_synchronize() must be called before it
-+   is safe to free the memory accessed by the DMA transfer or free resources
-+   accessed from within the complete callback.
-+
-+   dmaengine_terminate_sync() will wait for the transfer and any running
-+   complete callbacks to finish before it returns. But the function must not be
-+   called from atomic context or from within a complete callback.
-+
-+   dmaengine_terminate_all() is deprecated and should not be used in new code.
-+
- 2. int dmaengine_pause(struct dma_chan *chan)
-    This pauses activity on the DMA channel without data loss.
-@@ -186,3 +203,20 @@ Further APIs:
-       a running DMA channel.  It is recommended that DMA engine users
-       pause or stop (via dmaengine_terminate_all()) the channel before
-       using this API.
-+
-+5. void dmaengine_synchronize(struct dma_chan *chan)
-+
-+  Synchronize the termination of the DMA channel to the current context.
-+
-+  This function should be used after dmaengine_terminate_async() to synchronize
-+  the termination of the DMA channel to the current context. The function will
-+  wait for the transfer and any running complete callbacks to finish before it
-+  returns.
-+
-+  If dmaengine_terminate_async() is used to stop the DMA channel this function
-+  must be called before it is safe to free memory accessed by previously
-+  submitted descriptors or to free any resources accessed within the complete
-+  callback of previously submitted descriptors.
-+
-+  The behavior of this function is undefined if dma_async_issue_pending() has
-+  been called between dmaengine_terminate_async() and this function.
---- a/Documentation/dmaengine/provider.txt
-+++ b/Documentation/dmaengine/provider.txt
-@@ -327,8 +327,24 @@ supported.
-    * device_terminate_all
-      - Aborts all the pending and ongoing transfers on the channel
--     - This command should operate synchronously on the channel,
--       terminating right away all the channels
-+     - For aborted transfers the complete callback should not be called
-+     - Can be called from atomic context or from within a complete
-+       callback of a descriptor. Must not sleep. Drivers must be able
-+       to handle this correctly.
-+     - Termination may be asynchronous. The driver does not have to
-+       wait until the currently active transfer has completely stopped.
-+       See device_synchronize.
-+
-+   * device_synchronize
-+     - Must synchronize the termination of a channel to the current
-+       context.
-+     - Must make sure that memory for previously submitted
-+       descriptors is no longer accessed by the DMA controller.
-+     - Must make sure that all complete callbacks for previously
-+       submitted descriptors have finished running and none are
-+       scheduled to run.
-+     - May sleep.
-+
- Misc notes (stuff that should be documented, but don't really know
- where to put them)
---- a/drivers/dma/dmaengine.c
-+++ b/drivers/dma/dmaengine.c
-@@ -266,8 +266,11 @@ static void dma_chan_put(struct dma_chan
-       module_put(dma_chan_to_owner(chan));
-       /* This channel is not in use anymore, free it */
--      if (!chan->client_count && chan->device->device_free_chan_resources)
-+      if (!chan->client_count && chan->device->device_free_chan_resources) {
-+              /* Make sure all operations have completed */
-+              dmaengine_synchronize(chan);
-               chan->device->device_free_chan_resources(chan);
-+      }
-       /* If the channel is used via a DMA request router, free the mapping */
-       if (chan->router && chan->router->route_free) {
---- a/include/linux/dmaengine.h
-+++ b/include/linux/dmaengine.h
-@@ -681,6 +681,8 @@ struct dma_filter {
-  *    paused. Returns 0 or an error code
-  * @device_terminate_all: Aborts all transfers on a channel. Returns 0
-  *    or an error code
-+ * @device_synchronize: Synchronizes the termination of a transfers to the
-+ *  current context.
-  * @device_tx_status: poll for transaction completion, the optional
-  *    txstate parameter can be supplied with a pointer to get a
-  *    struct with auxiliary transfer status information, otherwise the call
-@@ -765,6 +767,7 @@ struct dma_device {
-       int (*device_pause)(struct dma_chan *chan);
-       int (*device_resume)(struct dma_chan *chan);
-       int (*device_terminate_all)(struct dma_chan *chan);
-+      void (*device_synchronize)(struct dma_chan *chan);
-       enum dma_status (*device_tx_status)(struct dma_chan *chan,
-                                           dma_cookie_t cookie,
-@@ -856,6 +859,13 @@ static inline struct dma_async_tx_descri
-                       src_sg, src_nents, flags);
- }
-+/**
-+ * dmaengine_terminate_all() - Terminate all active DMA transfers
-+ * @chan: The channel for which to terminate the transfers
-+ *
-+ * This function is DEPRECATED use either dmaengine_terminate_sync() or
-+ * dmaengine_terminate_async() instead.
-+ */
- static inline int dmaengine_terminate_all(struct dma_chan *chan)
- {
-       if (chan->device->device_terminate_all)
-@@ -864,6 +874,86 @@ static inline int dmaengine_terminate_al
-       return -ENOSYS;
- }
-+/**
-+ * dmaengine_terminate_async() - Terminate all active DMA transfers
-+ * @chan: The channel for which to terminate the transfers
-+ *
-+ * Calling this function will terminate all active and pending descriptors
-+ * that have previously been submitted to the channel. It is not guaranteed
-+ * though that the transfer for the active descriptor has stopped when the
-+ * function returns. Furthermore it is possible the complete callback of a
-+ * submitted transfer is still running when this function returns.
-+ *
-+ * dmaengine_synchronize() needs to be called before it is safe to free
-+ * any memory that is accessed by previously submitted descriptors or before
-+ * freeing any resources accessed from within the completion callback of any
-+ * perviously submitted descriptors.
-+ *
-+ * This function can be called from atomic context as well as from within a
-+ * complete callback of a descriptor submitted on the same channel.
-+ *
-+ * If none of the two conditions above apply consider using
-+ * dmaengine_terminate_sync() instead.
-+ */
-+static inline int dmaengine_terminate_async(struct dma_chan *chan)
-+{
-+      if (chan->device->device_terminate_all)
-+              return chan->device->device_terminate_all(chan);
-+
-+      return -EINVAL;
-+}
-+
-+/**
-+ * dmaengine_synchronize() - Synchronize DMA channel termination
-+ * @chan: The channel to synchronize
-+ *
-+ * Synchronizes to the DMA channel termination to the current context. When this
-+ * function returns it is guaranteed that all transfers for previously issued
-+ * descriptors have stopped and and it is safe to free the memory assoicated
-+ * with them. Furthermore it is guaranteed that all complete callback functions
-+ * for a previously submitted descriptor have finished running and it is safe to
-+ * free resources accessed from within the complete callbacks.
-+ *
-+ * The behavior of this function is undefined if dma_async_issue_pending() has
-+ * been called between dmaengine_terminate_async() and this function.
-+ *
-+ * This function must only be called from non-atomic context and must not be
-+ * called from within a complete callback of a descriptor submitted on the same
-+ * channel.
-+ */
-+static inline void dmaengine_synchronize(struct dma_chan *chan)
-+{
-+      if (chan->device->device_synchronize)
-+              chan->device->device_synchronize(chan);
-+}
-+
-+/**
-+ * dmaengine_terminate_sync() - Terminate all active DMA transfers
-+ * @chan: The channel for which to terminate the transfers
-+ *
-+ * Calling this function will terminate all active and pending transfers
-+ * that have previously been submitted to the channel. It is similar to
-+ * dmaengine_terminate_async() but guarantees that the DMA transfer has actually
-+ * stopped and that all complete callbacks have finished running when the
-+ * function returns.
-+ *
-+ * This function must only be called from non-atomic context and must not be
-+ * called from within a complete callback of a descriptor submitted on the same
-+ * channel.
-+ */
-+static inline int dmaengine_terminate_sync(struct dma_chan *chan)
-+{
-+      int ret;
-+
-+      ret = dmaengine_terminate_async(chan);
-+      if (ret)
-+              return ret;
-+
-+      dmaengine_synchronize(chan);
-+
-+      return 0;
-+}
-+
- static inline int dmaengine_pause(struct dma_chan *chan)
- {
-       if (chan->device->device_pause)