[PATCH] DMAEngine: sirf: let the users be able to pause and resume specific buffer

Barry Song 21cnbao at gmail.com
Sun Jul 28 22:14:24 EDT 2013


2013/7/4 Barry Song <Baohua.Song at csr.com>
>
> From: Qipan Li <Qipan.Li at csr.com>
>
> this patch adds a buffer_index in pause and resume entries, then users
> can pause and resume a buffer they want, but don't pause the whole dma.
>
> a typical application scenerios is Ping-Pang in two buffers:
> at the beginning, we enable buf1 and buf2 to receive dma data, after
> buf1 is full, we pause buf1 and handle the data in this buffer to avoid
> overflow in buf1. but at the same time, dma is still tranferring in buf2.
> once we have finished data process in buf1, we enable buf1 again.
> this will maximize the chance of dma transferring. users pause buf1 by:
> dmaengine_device_control(sirfport->rx_dma_chan, DMA_PAUSE, 1);
> users pause buf2 by:
> dmaengine_device_control(sirfport->rx_dma_chan, DMA_PAUSE, 2);
> users can still pause the whole dma transferring by dmaengine_pause().
>
> Signed-off-by: Qipan Li <Qipan.Li at csr.com>
> Signed-off-by: Barry Song <Baohua.Song at csr.com>
> ---
>  drivers/dma/sirf-dma.c | 102
> ++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 80 insertions(+), 22 deletions(-)

Hi Vinod, as we still have some other patches of dma clients depending
on this, would you give some comments about it?

>
> diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
> index 1d627e2..7d500d2 100644
> --- a/drivers/dma/sirf-dma.c
> +++ b/drivers/dma/sirf-dma.c
> @@ -315,43 +315,101 @@ static int sirfsoc_dma_terminate_all(struct
> sirfsoc_dma_chan *schan)
>         return 0;
>  }
>
> -static int sirfsoc_dma_pause_chan(struct sirfsoc_dma_chan *schan)
> +static int sirfsoc_dma_pause_chan(struct sirfsoc_dma_chan *schan,
> +                                               unsigned long buf_index)
>  {
>         struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
>         int cid = schan->chan.chan_id;
>         unsigned long flags;
> +       unsigned long loop_ctrl_val;
>
>         spin_lock_irqsave(&schan->lock, flags);
> -
> -       if (!sdma->is_marco)
> -               writel_relaxed(readl_relaxed(sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL)
> -                       & ~((1 << cid) | 1 << (cid + 16)),
> -                       sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
> -       else
> -               writel_relaxed((1 << cid) | 1 << (cid + 16),
> -                       sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL_CLR);
> -
> +       if (!sdma->is_marco) {
> +               loop_ctrl_val = readl_relaxed(sdma->base +
> +                               SIRFSOC_DMA_CH_LOOP_CTRL);
> +               switch (buf_index) {
> +               case 1:
> +                       writel_relaxed(loop_ctrl_val & ~(1 << cid),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               case 2:
> +                       writel_relaxed(loop_ctrl_val & ~(1 << (cid + 16)),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               case 0:
> +               default:
> +                       writel_relaxed(loop_ctrl_val &
> +                                       ~((1 << cid) | 1 << (cid + 16)),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               }
> +       } else {
> +               switch (buf_index) {
> +               case 1:
> +                       writel_relaxed((1 << cid), sdma->base +
> +
> SIRFSOC_DMA_CH_LOOP_CTRL_CLR);
> +                       break;
> +               case 2:
> +                       writel_relaxed(1 << (cid + 16), sdma->base +
> +
> SIRFSOC_DMA_CH_LOOP_CTRL_CLR);
> +                       break;
> +               case 0:
> +               default:
> +                       writel_relaxed((1 << cid) | 1 << (cid + 16),
> +                               sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL_CLR);
> +                       break;
> +               }
> +       }
>         spin_unlock_irqrestore(&schan->lock, flags);
>
>         return 0;
>  }
>
> -static int sirfsoc_dma_resume_chan(struct sirfsoc_dma_chan *schan)
> +static int sirfsoc_dma_resume_chan(struct sirfsoc_dma_chan *schan,
> +                                               unsigned long buf_index)
>  {
>         struct sirfsoc_dma *sdma = dma_chan_to_sirfsoc_dma(&schan->chan);
>         int cid = schan->chan.chan_id;
>         unsigned long flags;
> +       unsigned long loop_ctrl_val;
>
>         spin_lock_irqsave(&schan->lock, flags);
> -
> -       if (!sdma->is_marco)
> -               writel_relaxed(readl_relaxed(sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL)
> -                       | ((1 << cid) | 1 << (cid + 16)),
> -                       sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
> -       else
> -               writel_relaxed((1 << cid) | 1 << (cid + 16),
> -                       sdma->base + SIRFSOC_DMA_CH_LOOP_CTRL);
> -
> +       if (!sdma->is_marco) {
> +               loop_ctrl_val = readl_relaxed(sdma->base +
> +                               SIRFSOC_DMA_CH_LOOP_CTRL);
> +               switch (buf_index) {
> +               case 1:
> +                       writel_relaxed(loop_ctrl_val | (1 << cid),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               case 2:
> +                       writel_relaxed(loop_ctrl_val | 1 << (cid + 16),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               case 0:
> +               default:
> +                       writel_relaxed(loop_ctrl_val | (1 << cid) |
> +                                       1 << (cid + 16),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               }
> +       } else {
> +               switch (buf_index) {
> +               case 1:
> +                       writel_relaxed((1 << cid),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               case 2:
> +                       writel_relaxed((1 << (cid + 16)),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               case 0:
> +               default:
> +                       writel_relaxed((1 << cid) | 1 << (cid + 16),
> +                                       sdma->base +
> SIRFSOC_DMA_CH_LOOP_CTRL);
> +                       break;
> +               }
> +       }
>         spin_unlock_irqrestore(&schan->lock, flags);
>
>         return 0;
> @@ -365,9 +423,9 @@ static int sirfsoc_dma_control(struct dma_chan *chan,
> enum dma_ctrl_cmd cmd,
>
>         switch (cmd) {
>         case DMA_PAUSE:
> -               return sirfsoc_dma_pause_chan(schan);
> +               return sirfsoc_dma_pause_chan(schan, arg);
>         case DMA_RESUME:
> -               return sirfsoc_dma_resume_chan(schan);
> +               return sirfsoc_dma_resume_chan(schan, arg);
>         case DMA_TERMINATE_ALL:
>                 return sirfsoc_dma_terminate_all(schan);
>         case DMA_SLAVE_CONFIG:
> --
> 1.8.2.3


-barry



More information about the linux-arm-kernel mailing list