*/
 u32 coh901318_get_bytes_left(struct dma_chan *chan);
 
-/**
- * coh901318_stop() - Stops dma transfer
- * @chan: dma channel handle
- * return 0 on success otherwise negative value
- */
-void coh901318_stop(struct dma_chan *chan);
-
-/**
- * coh901318_continue() - Resumes a stopped dma transfer
- * @chan: dma channel handle
- * return 0 on success otherwise negative value
- */
-void coh901318_continue(struct dma_chan *chan);
-
 /**
  * coh901318_filter_id() - DMA channel filter function
  * @chan: dma channel handle
 
        return NULL;
 }
 
-static void atc_terminate_all(struct dma_chan *chan)
+static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_desc          *desc, *_desc;
        LIST_HEAD(list);
 
+       /* Only supports DMA_TERMINATE_ALL */
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
+
        /*
         * This is only called when something went wrong elsewhere, so
         * we don't really care about the data. Just disable the
        /* Flush all pending and queued descriptors */
        list_for_each_entry_safe(desc, _desc, &list, desc_node)
                atc_chain_complete(atchan, desc);
+
+       return 0;
 }
 
 /**
 
        if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
                atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
-               atdma->dma_common.device_terminate_all = atc_terminate_all;
+               atdma->dma_common.device_control = atc_control;
        }
 
        dma_writel(atdma, EN, AT_DMA_ENABLE);
 
 EXPORT_SYMBOL(coh901318_get_bytes_left);
 
 
-/* Stops a transfer without losing data. Enables power save.
-   Use this function in conjunction with coh901318_continue(..)
-*/
-void coh901318_stop(struct dma_chan *chan)
+/*
+ * Pauses a transfer without losing data. Enables power save.
+ * Use this function in conjunction with coh901318_resume.
+ */
+static void coh901318_pause(struct dma_chan *chan)
 {
        u32 val;
        unsigned long flags;
 
        spin_unlock_irqrestore(&cohc->lock, flags);
 }
-EXPORT_SYMBOL(coh901318_stop);
 
-/* Continues a transfer that has been stopped via 300_dma_stop(..).
+/* Resumes a transfer that has been stopped via 300_dma_stop(..).
    Power save is handled.
 */
-void coh901318_continue(struct dma_chan *chan)
+static void coh901318_resume(struct dma_chan *chan)
 {
        u32 val;
        unsigned long flags;
 
        spin_unlock_irqrestore(&cohc->lock, flags);
 }
-EXPORT_SYMBOL(coh901318_continue);
 
 bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
 {
 
        spin_unlock_irqrestore(&cohc->lock, flags);
 
-       chan->device->device_terminate_all(chan);
+       chan->device->device_control(chan, DMA_TERMINATE_ALL);
 }
 
 
        spin_unlock_irqrestore(&cohc->lock, flags);
 }
 
-static void
-coh901318_terminate_all(struct dma_chan *chan)
+static int
+coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        unsigned long flags;
        struct coh901318_chan *cohc = to_coh901318_chan(chan);
        struct coh901318_desc *cohd;
        void __iomem *virtbase = cohc->base->virtbase;
 
-       coh901318_stop(chan);
+       if (cmd == DMA_PAUSE) {
+               coh901318_pause(chan);
+               return 0;
+       }
+
+       if (cmd == DMA_RESUME) {
+               coh901318_resume(chan);
+               return 0;
+       }
+
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
 
+       /* The remainder of this function terminates the transfer */
+       coh901318_pause(chan);
        spin_lock_irqsave(&cohc->lock, flags);
 
        /* Clear any pending BE or TC interrupt */
        cohc->busy = 0;
 
        spin_unlock_irqrestore(&cohc->lock, flags);
+
+       return 0;
 }
 void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
                         struct coh901318_base *base)
        base->dma_slave.device_prep_slave_sg = coh901318_prep_slave_sg;
        base->dma_slave.device_is_tx_complete = coh901318_is_tx_complete;
        base->dma_slave.device_issue_pending = coh901318_issue_pending;
-       base->dma_slave.device_terminate_all = coh901318_terminate_all;
+       base->dma_slave.device_control = coh901318_control;
        base->dma_slave.dev = &pdev->dev;
 
        err = dma_async_device_register(&base->dma_slave);
        base->dma_memcpy.device_prep_dma_memcpy = coh901318_prep_memcpy;
        base->dma_memcpy.device_is_tx_complete = coh901318_is_tx_complete;
        base->dma_memcpy.device_issue_pending = coh901318_issue_pending;
-       base->dma_memcpy.device_terminate_all = coh901318_terminate_all;
+       base->dma_memcpy.device_control = coh901318_control;
        base->dma_memcpy.dev = &pdev->dev;
        /*
         * This controller can only access address at even 32bit boundaries,
 
        BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
                !device->device_prep_slave_sg);
        BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
-               !device->device_terminate_all);
+               !device->device_control);
 
        BUG_ON(!device->device_alloc_chan_resources);
        BUG_ON(!device->device_free_chan_resources);
 
        return NULL;
 }
 
-static void dwc_terminate_all(struct dma_chan *chan)
+static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        struct dw_dma_chan      *dwc = to_dw_dma_chan(chan);
        struct dw_dma           *dw = to_dw_dma(chan->device);
        struct dw_desc          *desc, *_desc;
        LIST_HEAD(list);
 
+       /* Only supports DMA_TERMINATE_ALL */
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
+
        /*
         * This is only called when something went wrong elsewhere, so
         * we don't really care about the data. Just disable the
        /* Flush all pending and queued descriptors */
        list_for_each_entry_safe(desc, _desc, &list, desc_node)
                dwc_descriptor_complete(dwc, desc);
+
+       return 0;
 }
 
 static enum dma_status
        dw->dma.device_prep_dma_memcpy = dwc_prep_dma_memcpy;
 
        dw->dma.device_prep_slave_sg = dwc_prep_slave_sg;
-       dw->dma.device_terminate_all = dwc_terminate_all;
+       dw->dma.device_control = dwc_control;
 
        dw->dma.device_is_tx_complete = dwc_is_tx_complete;
        dw->dma.device_issue_pending = dwc_issue_pending;
 
        return NULL;
 }
 
-static void fsl_dma_device_terminate_all(struct dma_chan *dchan)
+static int fsl_dma_device_control(struct dma_chan *dchan,
+                                 enum dma_ctrl_cmd cmd)
 {
        struct fsldma_chan *chan;
        unsigned long flags;
 
+       /* Only supports DMA_TERMINATE_ALL */
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
+
        if (!dchan)
-               return;
+               return -EINVAL;
 
        chan = to_fsl_chan(dchan);
 
        fsldma_free_desc_list(chan, &chan->ld_running);
 
        spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+       return 0;
 }
 
 /**
        fdev->common.device_is_tx_complete = fsl_dma_is_complete;
        fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
        fdev->common.device_prep_slave_sg = fsl_dma_prep_slave_sg;
-       fdev->common.device_terminate_all = fsl_dma_device_terminate_all;
+       fdev->common.device_control = fsl_dma_device_control;
        fdev->common.dev = &op->dev;
 
        dev_set_drvdata(&op->dev, fdev);
 
         */
 }
 
-static void __idmac_terminate_all(struct dma_chan *chan)
+static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        struct idmac_channel *ichan = to_idmac_chan(chan);
        struct idmac *idmac = to_idmac(chan->device);
        unsigned long flags;
        int i;
 
+       /* Only supports DMA_TERMINATE_ALL */
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
+
        ipu_disable_channel(idmac, ichan,
                            ichan->status >= IPU_CHANNEL_ENABLED);
 
        tasklet_enable(&to_ipu(idmac)->tasklet);
 
        ichan->status = IPU_CHANNEL_INITIALIZED;
+
+       return 0;
 }
 
-static void idmac_terminate_all(struct dma_chan *chan)
+static int idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        struct idmac_channel *ichan = to_idmac_chan(chan);
+       int ret;
 
        mutex_lock(&ichan->chan_mutex);
 
-       __idmac_terminate_all(chan);
+       ret = __idmac_control(chan, cmd);
 
        mutex_unlock(&ichan->chan_mutex);
+
+       return ret;
 }
 
 #ifdef DEBUG
 
        mutex_lock(&ichan->chan_mutex);
 
-       __idmac_terminate_all(chan);
+       __idmac_control(chan, DMA_TERMINATE_ALL);
 
        if (ichan->status > IPU_CHANNEL_FREE) {
 #ifdef DEBUG
 
        /* Compulsory for DMA_SLAVE fields */
        dma->device_prep_slave_sg               = idmac_prep_slave_sg;
-       dma->device_terminate_all               = idmac_terminate_all;
+       dma->device_control                     = idmac_control;
 
        INIT_LIST_HEAD(&dma->channels);
        for (i = 0; i < IPU_CHANNELS_NUM; i++) {
        for (i = 0; i < IPU_CHANNELS_NUM; i++) {
                struct idmac_channel *ichan = ipu->channel + i;
 
-               idmac_terminate_all(&ichan->dma_chan);
+               idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL);
                idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0);
        }
 
 
                               direction, flags);
 }
 
-static void sh_dmae_terminate_all(struct dma_chan *chan)
+static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
 
+       /* Only supports DMA_TERMINATE_ALL */
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
+
        if (!chan)
-               return;
+               return -EINVAL;
 
        dmae_halt(sh_chan);
 
        spin_unlock_bh(&sh_chan->desc_lock);
 
        sh_dmae_chan_ld_cleanup(sh_chan, true);
+
+       return 0;
 }
 
 static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
 
        /* Compulsory for DMA_SLAVE fields */
        shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
-       shdev->common.device_terminate_all = sh_dmae_terminate_all;
+       shdev->common.device_control = sh_dmae_control;
 
        shdev->common.dev = &pdev->dev;
        /* Default transfer size of 32 bytes requires 32-byte alignment */
 
        return &td_desc->txd;
 }
 
-static void td_terminate_all(struct dma_chan *chan)
+static int td_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        struct timb_dma_chan *td_chan =
                container_of(chan, struct timb_dma_chan, chan);
 
        dev_dbg(chan2dev(chan), "%s: Entry\n", __func__);
 
+       if (cmd != DMA_TERMINATE_ALL)
+               return -ENXIO;
+
        /* first the easy part, put the queue into the free list */
        spin_lock_bh(&td_chan->lock);
        list_for_each_entry_safe(td_desc, _td_desc, &td_chan->queue,
        /* now tear down the runnning */
        __td_finish(td_chan);
        spin_unlock_bh(&td_chan->lock);
+
+       return 0;
 }
 
 static void td_tasklet(unsigned long data)
        dma_cap_set(DMA_SLAVE, td->dma.cap_mask);
        dma_cap_set(DMA_PRIVATE, td->dma.cap_mask);
        td->dma.device_prep_slave_sg = td_prep_slave_sg;
-       td->dma.device_terminate_all = td_terminate_all;
+       td->dma.device_control = td_control;
 
        td->dma.dev = &pdev->dev;
 
 
        return &first->txd;
 }
 
-static void txx9dmac_terminate_all(struct dma_chan *chan)
+static int txx9dmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd)
 {
        struct txx9dmac_chan *dc = to_txx9dmac_chan(chan);
        struct txx9dmac_desc *desc, *_desc;
        LIST_HEAD(list);
 
+       /* Only supports DMA_TERMINATE_ALL */
+       if (cmd != DMA_TERMINATE_ALL)
+               return -EINVAL;
+
        dev_vdbg(chan2dev(chan), "terminate_all\n");
        spin_lock_bh(&dc->lock);
 
        /* Flush all pending and queued descriptors */
        list_for_each_entry_safe(desc, _desc, &list, desc_node)
                txx9dmac_descriptor_complete(dc, desc);
+
+       return 0;
 }
 
 static enum dma_status
        dc->dma.dev = &pdev->dev;
        dc->dma.device_alloc_chan_resources = txx9dmac_alloc_chan_resources;
        dc->dma.device_free_chan_resources = txx9dmac_free_chan_resources;
-       dc->dma.device_terminate_all = txx9dmac_terminate_all;
+       dc->dma.device_control = txx9dmac_control;
        dc->dma.device_is_tx_complete = txx9dmac_is_tx_complete;
        dc->dma.device_issue_pending = txx9dmac_issue_pending;
        if (pdata && pdata->memcpy_chan == ch) {
 
        struct dma_chan *chan = host->data_chan;
 
        if (chan) {
-               chan->device->device_terminate_all(chan);
+               chan->device->device_control(chan, DMA_TERMINATE_ALL);
                atmci_dma_cleanup(host);
        } else {
                /* Data transfer was stopped by the interrupt handler */
 
                unsigned long flags;
                int count;
 
-               chan->device->device_terminate_all(chan);
+               chan->device->device_control(chan, DMA_TERMINATE_ALL);
                dev_dbg(port->dev, "Read %u bytes with cookie %d\n",
                        sh_desc->partial, sh_desc->cookie);
 
 
 
        spin_unlock_irqrestore(&mx3fb->lock, flags);
 
-       mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan);
+       mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan,
+                                                  DMA_TERMINATE_ALL);
        mx3_fbi->txd = NULL;
        mx3_fbi->cookie = -EINVAL;
 }
 
        DMA_PREP_FENCE = (1 << 9),
 };
 
+/**
+ * enum dma_ctrl_cmd - DMA operations that can optionally be exercised
+ * on a running channel.
+ * @DMA_TERMINATE_ALL: terminate all ongoing transfers
+ * @DMA_PAUSE: pause ongoing transfers
+ * @DMA_RESUME: resume paused transfer
+ */
+enum dma_ctrl_cmd {
+       DMA_TERMINATE_ALL,
+       DMA_PAUSE,
+       DMA_RESUME,
+};
+
 /**
  * enum sum_check_bits - bit position of pq_check_flags
  */
  * @device_prep_dma_memset: prepares a memset operation
  * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
  * @device_prep_slave_sg: prepares a slave dma operation
- * @device_terminate_all: terminate all pending operations
+ * @device_control: manipulate all pending operations on a channel, returns
+ *     zero or error code
  * @device_is_tx_complete: poll for transaction completion
  * @device_issue_pending: push pending transactions to hardware
  */
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_data_direction direction,
                unsigned long flags);
-       void (*device_terminate_all)(struct dma_chan *chan);
+       int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd);
 
        enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
                        dma_cookie_t cookie, dma_cookie_t *last,
 
                void __iomem *base = drvdata->base;
 
                spin_unlock_irqrestore(&dmadata->dma_lock, flags);
-               chan->device->device_terminate_all(chan);
+               chan->device->device_control(chan, DMA_TERMINATE_ALL);
                /* first time */
                for (i = 0; i < NR_DMA_CHAIN; i++) {
                        desc = txx9aclc_dma_submit(dmadata,
        struct dma_chan *chan = dmadata->dma_chan;
 
        dmadata->frag_count = -1;
-       chan->device->device_terminate_all(chan);
+       chan->device->device_control(chan, DMA_TERMINATE_ALL);
        return 0;
 }
 
                struct dma_chan *chan = dmadata->dma_chan;
                if (chan) {
                        dmadata->frag_count = -1;
-                       chan->device->device_terminate_all(chan);
+                       chan->device->device_control(chan, DMA_TERMINATE_ALL);
                        dma_release_channel(chan);
                }
                dev->dmadata[i].dma_chan = NULL;