Skip to contentSkip to conversation

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

PATCH New Barry Song 4 participants 9 messages Jul 4, 2013 – Jul 29, 2013 dmaengine

lore
Share & tools
lore

Barry Song

author
#0 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

From: Qipan Li <[email protected]>

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().

---
 drivers/dma/sirf-dma.c | 102 ++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 80 insertions(+), 22 deletions(-)
drivers/dma/sirf-dma.c +80 -22
index 1d627e2..7d500d2 100644
@@ -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:
Signature · 6 lines
1.8.2.3



Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog
#1 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

2013/7/4 Barry Song <[email protected]>

Quoted 17 lines

From: Qipan Li <[email protected]>

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().

Quoted 6 lines
---
 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?

Quoted 154 lines
drivers/dma/sirf-dma.c +49 -20
index 1d627e2..7d500d2 100644
@@ -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);

drivers/dma/sirf-dma.c +4 -0
+                       break;
+               case 2:
+                       writel_relaxed(loop_ctrl_val | 1 << (cid + 16),
+                                       sdma->base +

SIRFSOC_DMA_CH_LOOP_CTRL);

drivers/dma/sirf-dma.c +6 -0
+                       break;
+               case 0:
+               default:
+                       writel_relaxed(loop_ctrl_val | (1 << cid) |
+                                       1 << (cid + 16),
+                                       sdma->base +

SIRFSOC_DMA_CH_LOOP_CTRL);

drivers/dma/sirf-dma.c +7 -0
+                       break;
+               }
+       } else {
+               switch (buf_index) {
+               case 1:
+                       writel_relaxed((1 << cid),
+                                       sdma->base +

SIRFSOC_DMA_CH_LOOP_CTRL);

drivers/dma/sirf-dma.c +4 -0
+                       break;
+               case 2:
+                       writel_relaxed((1 << (cid + 16)),
+                                       sdma->base +

SIRFSOC_DMA_CH_LOOP_CTRL);

drivers/dma/sirf-dma.c +5 -0
+                       break;
+               case 0:
+               default:
+                       writel_relaxed((1 << cid) | 1 << (cid + 16),
+                                       sdma->base +

SIRFSOC_DMA_CH_LOOP_CTRL);

drivers/dma/sirf-dma.c +5 -2
+                       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);
Quoted 3 lines

case DMA_SLAVE_CONFIG:
--
1.8.2.3

-barry

#2 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

Quoted 1 line · Barry Song

2013/7/4 Barry Song <[email protected]>

well the submitter didn't cc me. So this wasnt in my INBOX!

Quoted 7 lines
Quoted 7 lines

From: Qipan Li <[email protected]>

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:

typo, pong ^^^^^^^^^

Quoted 9 lines
Quoted 9 lines

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().

Well this is odd, the second arg is not supposed to be valid for PAUSE op. And PAUSE means you pause the whole channel.

The above can be done by
a) have two buffers:
- prepare first and submit, and start
- while first is ongoing, prepare second and start
- first is completed, so you start processing that while second is getting DMAed
- when processing is completed, submit first again
- when second is completed, start processing that and submit that once proocessed

b) have multiple buffers, A, B, C & D and redo above schema.

Since patch is not the right approach and doesnt use API correctly NAK from me on that

~Vinod

#3 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

2013/7/29 Vinod Koul <[email protected]>:

Quoted 3 lines · Barry Song
Quoted 1 line

2013/7/4 Barry Song <[email protected]>

well the submitter didn't cc me. So this wasnt in my INBOX!

Vinod, i must did some misoperation. sorry for that.

Quoted 31 lines
Quoted 8 lines
Quoted 8 lines

From: Qipan Li <[email protected]>

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:

typo, pong ^^^^^^^^^

Quoted 9 lines
Quoted 9 lines

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().

Well this is odd, the second arg is not supposed to be valid for PAUSE op. And PAUSE means you pause the whole channel.

The above can be done by
a) have two buffers:
- prepare first and submit, and start
- while first is ongoing, prepare second and start
- first is completed, so you start processing that while second is getting DMAed
- when processing is completed, submit first again
- when second is completed, start processing that and submit that once proocessed

Quoted 1 line

b) have multiple buffers, A, B, C & D and redo above schema.

yes, that is the original idea for multiple buffer management for DMA.

the reason which pushed us to the ping-pong pause is that we don't need to issue software dma descriptor every time for every buffer as hardware can do that.
so we went to a pause for buffers which have been issued by hardware and stop buffer overflow.

Quoted 2 lines

Since patch is not the right approach and doesnt use API correctly NAK from me on that

the original idea is actually extending the DMA pause API insteading of using current PAUSE pf the whole link. i got a little worried about the patch too, guys have a long history for ping-pong pause even before using DMAEngine framework.

if your answer is definite no, let's move to your way which makes more senses.

Quoted 2 lines

~Vinod

-barry

#4 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

Quoted 11 lines · Barry Song

2013/7/29 Vinod Koul <[email protected]>:

Quoted 10 lines

The above can be done by
a) have two buffers:
- prepare first and submit, and start
- while first is ongoing, prepare second and start
- first is completed, so you start processing that while second is getting DMAed
- when processing is completed, submit first again
- when second is completed, start processing that and submit that once proocessed

Quoted 7 lines
Quoted 1 line

b) have multiple buffers, A, B, C & D and redo above schema.

yes, that is the original idea for multiple buffer management for DMA.

the reason which pushed us to the ping-pong pause is that we don't need to issue software dma descriptor every time for every buffer as hardware can do that.

If your DMA engine is correctly implemented (and this only works for correctly implemented DMA engines), what you can do is:

- at the start of the transfer, prepare, submit and issue two buffers, each with a callback.
- when the first callback happens
- that buffer has been transferred.
- you can now do whatever you need with that data.
- prepare, submit and issue the next buffer

This means the DMA engine always has a buffer available to it, so if your CPU is fast enough, you can keep the transfer going without the DMA channel ever stopping or having to be paused. If your CPU isn't fast enough to keep up, the DMA engine will stop at the end of the last queued and issued buffer automatically.

Bonus points if you have implemented the "move to next buffer" correctly too, so that the hardware can do a continuous transfer without having to stop and wait between the buffers (provided of course that the next transfer is compatible with the previous.)

#5 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

2013/7/29 Russell King - ARM Linux <[email protected]>:

Quoted 30 lines · Barry Song
Quoted 11 lines

2013/7/29 Vinod Koul <[email protected]>:

Quoted 10 lines

The above can be done by
a) have two buffers:
- prepare first and submit, and start
- while first is ongoing, prepare second and start
- first is completed, so you start processing that while second is getting DMAed
- when processing is completed, submit first again
- when second is completed, start processing that and submit that once proocessed

Quoted 7 lines
Quoted 1 line

b) have multiple buffers, A, B, C & D and redo above schema.

yes, that is the original idea for multiple buffer management for DMA.

the reason which pushed us to the ping-pong pause is that we don't need to issue software dma descriptor every time for every buffer as hardware can do that.

If your DMA engine is correctly implemented (and this only works for correctly implemented DMA engines), what you can do is:

- at the start of the transfer, prepare, submit and issue two buffers, each with a callback.
- when the first callback happens
- that buffer has been transferred.
- you can now do whatever you need with that data.
- prepare, submit and issue the next buffer

Quoted 6 lines

This means the DMA engine always has a buffer available to it, so if your CPU is fast enough, you can keep the transfer going without the DMA channel ever stopping or having to be paused. If your CPU isn't fast enough to keep up, the DMA engine will stop at the end of the last queued and issued buffer automatically.

yes, suppose there are 4 buffers, we can issue all of buffer 0,1,2,3 at first. if buffer 0 has been read when buffer 3 is transferred, buffer0 must have been issued again.
so that will keep buffers always alive if cpu is fast enough.

Quoted 4 lines

Bonus points if you have implemented the "move to next buffer" correctly too, so that the hardware can do a continuous transfer without having to stop and wait between the buffers (provided of course that the next transfer is compatible with the previous.)

-barry

#6 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

In reply to Barry Song
Quoted 25 lines · Barry Song

2013/7/4 Barry Song <[email protected]>

Quoted 17 lines

From: Qipan Li <[email protected]>

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().

Quoted 6 lines
---
 drivers/dma/sirf-dma.c | 102
++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 80 insertions(+), 22 deletions(-)
Quoted 2 lines

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

You at least need to write up some documentation about this new feature - you need to describe exactly how this argument relates to a set of queued DMA descriptor(s) and its semantics with respect to those queued descriptors.

Quoted 1 line

From the looks of this patch, it has nothing to do with any particular

queued descriptor, but you're exposing internal knowledge of the SiRF DMA engine.

#7 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

Quoted 23 lines · Russell King - ARM Linux
Quoted 22 lines · Barry Song

2013/7/4 Barry Song <[email protected]>

Quoted 20 lines

From: Qipan Li <[email protected]>

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().

<[email protected]> --- drivers/dma/sirf-dma.c | 102 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 22 deletions(-)

Quoted 6 lines
Quoted 2 lines

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

You at least need to write up some documentation about this new feature - you need to describe exactly how this argument relates to a set of queued DMA descriptor(s) and its semantics with respect to those queued descriptors.

As I commented earlier today, I dont think we need this way. This can also be achieved with submitting descriptors after the buffer has been processed.

Quoted 3 lines

From the looks of this patch, it has nothing to do with any particular queued descriptor, but you're exposing internal knowledge of the SiRF DMA engine.

More than dmaengine its the way of modelling here which seems to be the issue

~Vinod

#8 lore raw

PATCH 1/1 DMAEngine: sirf: let the users be able to pause and resume specific buffer

2013/7/29 Vinod Koul <[email protected]>:

Quoted 24 lines · Russell King - ARM Linux
Quoted 23 lines · Barry Song
Quoted 22 lines

2013/7/4 Barry Song <[email protected]>

Quoted 20 lines

From: Qipan Li <[email protected]>

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().

<[email protected]> --- drivers/dma/sirf-dma.c | 102 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 22 deletions(-)

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

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

You at least need to write up some documentation about this new feature - you need to describe exactly how this argument relates to a set of queued DMA descriptor(s) and its semantics with respect to those queued descriptors.

As I commented earlier today, I dont think we need this way. This can also be achieved with submitting descriptors after the buffer has been processed.

we submit all buffers together at the beginning, once one buffer is right handled by cpu after dma transfers, we issue it again.

Quoted 8 lines
Quoted 4 lines

From the looks of this patch, it has nothing to do with any particular queued descriptor, but you're exposing internal knowledge of the SiRF DMA engine.

More than dmaengine its the way of modelling here which seems to be the issue

~Vinod
--

-barry