dma: mmp_pdma: support for getting residual bytes
PATCH v2 1/1 dma: mmp_pdma: support for getting residual bytes
From: Xiang Wang <[email protected]>
In some of our drivers (e.g. UART) we may stop a running DMA before it finishes. So we need APIs to know how many bytes have been transferred.
--- drivers/dma/mmp_pdma.c | 88 +++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 80 insertions(+), 8 deletions(-)
drivers/dma/mmp_pdma.c +80 -8
@@ -104,7 +104,8 @@ struct mmp_pdma_chan {spinlock_t desc_lock;/* Descriptor list lock */ struct list_head chain_pending;/* Link descriptors queue for pending */ struct list_head chain_running;/* Link descriptors queue for running */ -bool idle;/* channel statue machine */ +enum dma_status status;/* channel status machine */ +u32 bytes_residue;struct dma_pool *desc_pool;/* Descriptors pool */ };
@@ -270,7 +271,7 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)struct mmp_pdma_desc_sw *desc;/* still in running, irq will start the pending list */ -if (!chan->idle) { +if (chan->status ==DMA_IN_PROGRESS ) {dev_dbg (chan->dev,"DMA controller still busy\n" );return ; }
@@ -307,7 +308,64 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)*/ set_desc (chan->phy, desc->async_tx.phys);enable_chan (chan->phy); - chan->idle = false; + chan->status =DMA_IN_PROGRESS ; + chan->bytes_residue =0 ; +} + +/* +* Get the number of pending bytes. Should be called with desc_lock held +* because we are accessing desc list. +*/ +static u32 mmp_pdma_get_bytes_residue (struct mmp_pdma_chan *chan) +{ +u32 reg, orig_pos, cur_pos, ddadr, residue =0 ; +bool running_desc_found = false; +struct mmp_pdma_desc_sw *desc_sw; + +/* +* When a phy channel is unavailable, maybe it has been freed, return +* last stored value for safe. +*/ +if (!chan->phy) +return chan->bytes_residue; + + reg = (chan->phy->idx <<4 ) +DDADR ; + ddadr =readl_relaxed (chan->phy->base + reg); + +/* iterate over all descriptors to sum up the number of pending bytes */ +list_for_each_entry (desc_sw, &chan->chain_running, node) { +/* for the case of a running descriptor */ +if (desc_sw->desc.ddadr == ddadr && !running_desc_found) { +switch (chan->dir) { +case DMA_DEV_TO_MEM : +case DMA_MEM_TO_MEM : + reg = (chan->phy->idx <<4 ) +DTADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dtadr; +break ; + +case DMA_MEM_TO_DEV : + reg = (chan->phy->idx <<4 ) +DSADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dsadr; +break ; + +default : + cur_pos =0 ; + orig_pos =0 ; + } + residue = (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ) + + orig_pos - cur_pos; + running_desc_found = true; +continue ; + } + +/* for the case of following un-started descriptors*/ +if (running_desc_found) + residue += (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ); + } + +return residue; }
@@ -381,7 +439,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan) chan->phy->vchan =NULL ; chan->phy =NULL ; } - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;return 1 ; }
@@ -409,7 +467,7 @@ static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)dma_pool_destroy (chan->desc_pool); chan->desc_pool =NULL ; - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;if (chan->phy) { chan->phy->vchan =NULL ;
@@ -588,9 +646,16 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,spin_lock_irqsave (&chan->desc_lock, flags);mmp_pdma_free_desc_list (chan, &chan->chain_pending);mmp_pdma_free_desc_list (chan, &chan->chain_running); + chan->bytes_residue =0 ;spin_unlock_irqrestore (&chan->desc_lock, flags); - chan->idle = true; + chan->status =DMA_SUCCESS ;break ; + +case DMA_PAUSE : +disable_chan (chan->phy); + chan->status =DMA_PAUSED ; +break ; +case DMA_SLAVE_CONFIG :if (cfg->direction ==DMA_DEV_TO_MEM ) { chan->dcmd =DCMD_INCTRGADDR |DCMD_FLOWSRC ;
@@ -637,7 +702,9 @@ static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan,unsigned long flags;spin_lock_irqsave (&chan->desc_lock, flags); - ret =dma_cookie_status (dchan, cookie, txstate); + chan->bytes_residue =mmp_pdma_get_bytes_residue (chan); +dma_set_residue (txstate, chan->bytes_residue); + ret = chan->status;spin_unlock_irqrestore (&chan->desc_lock, flags);return ret;
@@ -684,6 +751,8 @@ static void dma_do_tasklet(unsigned long data)dev_dbg (chan->dev,"completed_cookie=%d\n" , cookie); } +/* update bytes_residue so that the user can query later on */ + chan->bytes_residue =mmp_pdma_get_bytes_residue (chan);/* * move the descriptors to a temporary list so we can drop the lock * during the entire cleanup operation
@@ -691,7 +760,7 @@ static void dma_do_tasklet(unsigned long data)list_splice_tail_init (&chan->chain_running, &chain_cleanup);/* the hardware is now idle and ready for more */ - chan->idle = true; + chan->status =DMA_SUCCESS ;/* Start any pending transactions automatically */ start_pending_queue (chan);
@@ -750,6 +819,9 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,INIT_LIST_HEAD (&chan->chain_pending);INIT_LIST_HEAD (&chan->chain_running); + chan->status =DMA_SUCCESS ; + chan->bytes_residue =0 ; +/* register virt channel to dma engine */ list_add_tail (&chan->chan.device_node, &pdev->device.channels);
Signature · 1 line
1.7.5.4
Hi, all
Do you have any comments about this patch? Thanks!
2013/6/18 Xiang Wang <[email protected]>:
Quoted 178 lines
From: Xiang Wang <[email protected]>
In some of our drivers (e.g. UART) we may stop a running DMA before it finishes. So we need APIs to know how many bytes have been transferred.
Signed-off-by Xiang Wang <[email protected]>--- drivers/dma/mmp_pdma.c | 88 +++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 80 insertions(+), 8 deletions(-)drivers/dma/mmp_pdma.c +80
-9@@ -104,7 +104,8 @@ struct mmp_pdma_chan {spinlock_t desc_lock;/* Descriptor list lock */ struct list_head chain_pending;/* Link descriptors queue for pending */ struct list_head chain_running;/* Link descriptors queue for running */ -bool idle;/* channel statue machine */ +enum dma_status status;/* channel status machine */ +u32 bytes_residue;struct dma_pool *desc_pool;/* Descriptors pool */ };@@ -270,7 +271,7 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)struct mmp_pdma_desc_sw *desc;/* still in running, irq will start the pending list */ -if (!chan->idle) { +if (chan->status ==DMA_IN_PROGRESS ) {dev_dbg (chan->dev,"DMA controller still busy\n" );return ; }@@ -307,7 +308,64 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)*/ set_desc (chan->phy, desc->async_tx.phys);enable_chan (chan->phy); - chan->idle = false; + chan->status =DMA_IN_PROGRESS ; + chan->bytes_residue =0 ; +} + +/* +* Get the number of pending bytes. Should be called with desc_lock held +* because we are accessing desc list. +*/ +static u32 mmp_pdma_get_bytes_residue (struct mmp_pdma_chan *chan) +{ +u32 reg, orig_pos, cur_pos, ddadr, residue =0 ; +bool running_desc_found = false; +struct mmp_pdma_desc_sw *desc_sw; + +/* +* When a phy channel is unavailable, maybe it has been freed, return +* last stored value for safe. +*/ +if (!chan->phy) +return chan->bytes_residue; + + reg = (chan->phy->idx <<4 ) +DDADR ; + ddadr =readl_relaxed (chan->phy->base + reg); + +/* iterate over all descriptors to sum up the number of pending bytes */ +list_for_each_entry (desc_sw, &chan->chain_running, node) { +/* for the case of a running descriptor */ +if (desc_sw->desc.ddadr == ddadr && !running_desc_found) { +switch (chan->dir) { +case DMA_DEV_TO_MEM : +case DMA_MEM_TO_MEM : + reg = (chan->phy->idx <<4 ) +DTADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dtadr; +break ; + +case DMA_MEM_TO_DEV : + reg = (chan->phy->idx <<4 ) +DSADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dsadr; +break ; + +default : + cur_pos =0 ; + orig_pos =0 ; + } + residue = (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ) + + orig_pos - cur_pos; + running_desc_found = true; +continue ; + } + +/* for the case of following un-started descriptors*/ +if (running_desc_found) + residue += (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ); + } + +return residue; }@@ -381,7 +439,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan) chan->phy->vchan =NULL ; chan->phy =NULL ; } - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;return 1 ; }@@ -409,7 +467,7 @@ static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)dma_pool_destroy (chan->desc_pool); chan->desc_pool =NULL ; - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;if (chan->phy) { chan->phy->vchan =NULL ;@@ -588,9 +646,16 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,spin_lock_irqsave (&chan->desc_lock, flags);mmp_pdma_free_desc_list (chan, &chan->chain_pending);mmp_pdma_free_desc_list (chan, &chan->chain_running); + chan->bytes_residue =0 ;spin_unlock_irqrestore (&chan->desc_lock, flags); - chan->idle = true; + chan->status =DMA_SUCCESS ;break ; + +case DMA_PAUSE : +disable_chan (chan->phy); + chan->status =DMA_PAUSED ; +break ; +case DMA_SLAVE_CONFIG :if (cfg->direction ==DMA_DEV_TO_MEM ) { chan->dcmd =DCMD_INCTRGADDR |DCMD_FLOWSRC ;@@ -637,7 +702,9 @@ static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan,unsigned long flags;spin_lock_irqsave (&chan->desc_lock, flags); - ret =dma_cookie_status (dchan, cookie, txstate); + chan->bytes_residue =mmp_pdma_get_bytes_residue (chan); +dma_set_residue (txstate, chan->bytes_residue); + ret = chan->status;spin_unlock_irqrestore (&chan->desc_lock, flags);return ret;@@ -684,6 +751,8 @@ static void dma_do_tasklet(unsigned long data)dev_dbg (chan->dev,"completed_cookie=%d\n" , cookie); } +/* update bytes_residue so that the user can query later on */ + chan->bytes_residue =mmp_pdma_get_bytes_residue (chan);/* * move the descriptors to a temporary list so we can drop the lock * during the entire cleanup operation @@ -691,7 +760,7 @@ static void dma_do_tasklet(unsigned long data)list_splice_tail_init (&chan->chain_running, &chain_cleanup);/* the hardware is now idle and ready for more */ - chan->idle = true; + chan->status =DMA_SUCCESS ;/* Start any pending transactions automatically */ start_pending_queue (chan);@@ -750,6 +819,9 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,INIT_LIST_HEAD (&chan->chain_pending);INIT_LIST_HEAD (&chan->chain_running); + chan->status =DMA_SUCCESS ; + chan->bytes_residue =0 ; +/* register virt channel to dma engine */ list_add_tail (&chan->chan.device_node, &pdev->device.channels); --1.7.5.4
Signature · 2 lines
Regards, Xiang
Quoted 54 lines · Xiang Wang
From: Xiang Wang <[email protected]>
In some of our drivers (e.g. UART) we may stop a running DMA before it finishes. So we need APIs to know how many bytes have been transferred.
Signed-off-by Xiang Wang <[email protected]>--- drivers/dma/mmp_pdma.c | 88 +++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 80 insertions(+), 8 deletions(-)drivers/dma/mmp_pdma.c +18
-3@@ -104,7 +104,8 @@ struct mmp_pdma_chan {spinlock_t desc_lock;/* Descriptor list lock */ struct list_head chain_pending;/* Link descriptors queue for pending */ struct list_head chain_running;/* Link descriptors queue for running */ -bool idle;/* channel statue machine */ +enum dma_status status;/* channel status machine */ +u32 bytes_residue;struct dma_pool *desc_pool;/* Descriptors pool */ };@@ -270,7 +271,7 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)struct mmp_pdma_desc_sw *desc;/* still in running, irq will start the pending list */ -if (!chan->idle) { +if (chan->status ==DMA_IN_PROGRESS ) {dev_dbg (chan->dev,"DMA controller still busy\n" );return ; }@@ -307,7 +308,64 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)*/ set_desc (chan->phy, desc->async_tx.phys);enable_chan (chan->phy); - chan->idle = false; + chan->status =DMA_IN_PROGRESS ; + chan->bytes_residue =0 ; +} + +/* +* Get the number of pending bytes. Should be called with desc_lock held +* because we are accessing desc list. +*/ +static u32 mmp_pdma_get_bytes_residue (struct mmp_pdma_chan *chan) +{ +u32 reg, orig_pos, cur_pos, ddadr, residue =0 ; +bool running_desc_found = false; +struct mmp_pdma_desc_sw *desc_sw; + +/*
drivers/dma/mmp_pdma.c static void start_pending_queue(struct mmp_pdma_chan *chan) · line 335
Quoted 10 lines
drivers/dma/mmp_pdma.c +10
-0+* When a phy channel is unavailable, maybe it has been freed, return +* last stored value for safe. +*/ +if (!chan->phy) +return chan->bytes_residue; + + reg = (chan->phy->idx <<4 ) +DDADR ; + ddadr =readl_relaxed (chan->phy->base + reg); + +/* iterate over all descriptors to sum up the number of pending bytes */
and why?
Residue does not mean sum of all pending bytes across all descriptors submitted You need to find the residue of current descriptor only and return
Quoted 10 lines
drivers/dma/mmp_pdma.c +10
-0+list_for_each_entry (desc_sw, &chan->chain_running, node) { +/* for the case of a running descriptor */ +if (desc_sw->desc.ddadr == ddadr && !running_desc_found) { +switch (chan->dir) { +case DMA_DEV_TO_MEM : +case DMA_MEM_TO_MEM : + reg = (chan->phy->idx <<4 ) +DTADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dtadr; +break ;
drivers/dma/mmp_pdma.c static void start_pending_queue(struct mmp_pdma_chan *chan) · line 355
Quoted 10 lines
drivers/dma/mmp_pdma.c +10
-0+ +case DMA_MEM_TO_DEV : + reg = (chan->phy->idx <<4 ) +DSADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dsadr; +break ; + +default : + cur_pos =0 ; + orig_pos =0 ;
This makes no sense...
Quoted 38 lines
drivers/dma/mmp_pdma.c +15
-2+ } + residue = (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ) + + orig_pos - cur_pos; + running_desc_found = true; +continue ; + } + +/* for the case of following un-started descriptors*/ +if (running_desc_found) + residue += (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ); + } + +return residue; }@@ -381,7 +439,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan) chan->phy->vchan =NULL ; chan->phy =NULL ; } - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;return 1 ; }@@ -409,7 +467,7 @@ static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)dma_pool_destroy (chan->desc_pool); chan->desc_pool =NULL ; - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;if (chan->phy) { chan->phy->vchan =NULL ;@@ -588,9 +646,16 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,spin_lock_irqsave (&chan->desc_lock, flags);mmp_pdma_free_desc_list (chan, &chan->chain_pending);mmp_pdma_free_desc_list (chan, &chan->chain_running);
drivers/dma/mmp_pdma.c static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, · line 657
Quoted 10 lines
drivers/dma/mmp_pdma.c +7
-1+ chan->bytes_residue =0 ;spin_unlock_irqrestore (&chan->desc_lock, flags); - chan->idle = true; + chan->status =DMA_SUCCESS ;break ; + +case DMA_PAUSE : +disable_chan (chan->phy); + chan->status =DMA_PAUSED ; +break ;
this should be a separate patch
--
~Vinod
2013/7/5 Vinod Koul <[email protected]>:
Quoted 67 lines · Xiang Wang
Quoted 54 lines
From: Xiang Wang <[email protected]>
In some of our drivers (e.g. UART) we may stop a running DMA before it finishes. So we need APIs to know how many bytes have been transferred.
Signed-off-by Xiang Wang <[email protected]>--- drivers/dma/mmp_pdma.c | 88 +++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 80 insertions(+), 8 deletions(-)drivers/dma/mmp_pdma.c +18
-3@@ -104,7 +104,8 @@ struct mmp_pdma_chan {spinlock_t desc_lock;/* Descriptor list lock */ struct list_head chain_pending;/* Link descriptors queue for pending */ struct list_head chain_running;/* Link descriptors queue for running */ -bool idle;/* channel statue machine */ +enum dma_status status;/* channel status machine */ +u32 bytes_residue;struct dma_pool *desc_pool;/* Descriptors pool */ };@@ -270,7 +271,7 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)struct mmp_pdma_desc_sw *desc;/* still in running, irq will start the pending list */ -if (!chan->idle) { +if (chan->status ==DMA_IN_PROGRESS ) {dev_dbg (chan->dev,"DMA controller still busy\n" );return ; }@@ -307,7 +308,64 @@ static void start_pending_queue(struct mmp_pdma_chan *chan)*/ set_desc (chan->phy, desc->async_tx.phys);enable_chan (chan->phy); - chan->idle = false; + chan->status =DMA_IN_PROGRESS ; + chan->bytes_residue =0 ; +} + +/* +* Get the number of pending bytes. Should be called with desc_lock held +* because we are accessing desc list. +*/ +static u32 mmp_pdma_get_bytes_residue (struct mmp_pdma_chan *chan) +{ +u32 reg, orig_pos, cur_pos, ddadr, residue =0 ; +bool running_desc_found = false; +struct mmp_pdma_desc_sw *desc_sw; + +/* drivers/dma/mmp_pdma.c static void start_pending_queue(struct mmp_pdma_chan *chan) · line 335
Quoted 10 lines
drivers/dma/mmp_pdma.c +10
-0+* When a phy channel is unavailable, maybe it has been freed, return +* last stored value for safe. +*/ +if (!chan->phy) +return chan->bytes_residue; + + reg = (chan->phy->idx <<4 ) +DDADR ; + ddadr =readl_relaxed (chan->phy->base + reg); + +/* iterate over all descriptors to sum up the number of pending bytes */ and why?
Quoted 3 lines
Residue does not mean sum of all pending bytes across all descriptors submitted You need to find the residue of current descriptor only and return
Here are my thoughts:
We tell dma engine to transmit x bytes for us and it creates n descriptors to transmit which is transparent to us.
So when we want to find out how many bytes are left, dma engine should sum up all pending bytes across all descriptors.
What's your opinion?
Quoted 13 lines
Quoted 13 lines
drivers/dma/mmp_pdma.c +13
-0+list_for_each_entry (desc_sw, &chan->chain_running, node) { +/* for the case of a running descriptor */ +if (desc_sw->desc.ddadr == ddadr && !running_desc_found) { +switch (chan->dir) { +case DMA_DEV_TO_MEM : +case DMA_MEM_TO_MEM : + reg = (chan->phy->idx <<4 ) +DTADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dtadr; +break ; + +case DMA_MEM_TO_DEV : + reg = (chan->phy->idx <<4 ) +DSADR ;
Quoted 8 lines
drivers/dma/mmp_pdma.c static void start_pending_queue(struct mmp_pdma_chan *chan) · line 355
Quoted 7 lines
drivers/dma/mmp_pdma.c +7
-0+ cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dsadr; +break ; + +default : + cur_pos =0 ; + orig_pos =0 ;This makes no sense...
What do you recommend for the default case? Just return 0?
Quoted 42 lines
Quoted 42 lines
drivers/dma/mmp_pdma.c +16
-3+ } + residue = (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ) + + orig_pos - cur_pos; + running_desc_found = true; +continue ; + } + +/* for the case of following un-started descriptors*/ +if (running_desc_found) + residue += (u32)(desc_sw->desc.dcmd &DCMD_LENGTH ); + } + +return residue; }@@ -381,7 +439,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan) chan->phy->vchan =NULL ; chan->phy =NULL ; } - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;return 1 ; }@@ -409,7 +467,7 @@ static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)dma_pool_destroy (chan->desc_pool); chan->desc_pool =NULL ; - chan->idle = true; + chan->status =DMA_SUCCESS ; chan->dev_addr =0 ;if (chan->phy) { chan->phy->vchan =NULL ;@@ -588,9 +646,16 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,spin_lock_irqsave (&chan->desc_lock, flags);mmp_pdma_free_desc_list (chan, &chan->chain_pending);mmp_pdma_free_desc_list (chan, &chan->chain_running); + chan->bytes_residue =0 ;spin_unlock_irqrestore (&chan->desc_lock, flags); - chan->idle = true;
Quoted 8 lines
drivers/dma/mmp_pdma.c static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, · line 657
Quoted 7 lines
drivers/dma/mmp_pdma.c +6
-0+ chan->status =DMA_SUCCESS ;break ; + +case DMA_PAUSE : +disable_chan (chan->phy); + chan->status =DMA_PAUSED ; +break ;this should be a separate patch
OK. I'll submit a separate patch which supports PAUSE/RESUME operations.
Quoted 3 lines
--
~Vinod
--
Regards,
Xiang
Quoted 22 lines · Xiang Wang
Quoted 19 lines
Quoted 7 lines
drivers/dma/mmp_pdma.c +7
-0+static u32 mmp_pdma_get_bytes_residue (struct mmp_pdma_chan *chan) +{ +u32 reg, orig_pos, cur_pos, ddadr, residue =0 ; +bool running_desc_found = false; +struct mmp_pdma_desc_sw *desc_sw; + +/* drivers/dma/mmp_pdma.c static void start_pending_queue(struct mmp_pdma_chan *chan) · line 335
Quoted 10 lines
drivers/dma/mmp_pdma.c +10
-0+* When a phy channel is unavailable, maybe it has been freed, return +* last stored value for safe. +*/ +if (!chan->phy) +return chan->bytes_residue; + + reg = (chan->phy->idx <<4 ) +DDADR ; + ddadr =readl_relaxed (chan->phy->base + reg); + +/* iterate over all descriptors to sum up the number of pending bytes */ and why?
Quoted 3 lines
Residue does not mean sum of all pending bytes across all descriptors submitted You need to find the residue of current descriptor only and return
Quoted 6 lines
Here are my thoughts:
We tell dma engine to transmit x bytes for us and it creates n descriptors to transmit which is transparent to us.
So when we want to find out how many bytes are left, dma engine should sum up all pending bytes across all descriptors.
What's your opinion?
but you may have multiple transactions submmited. Iterating over _all_ descriptors doesnt make sense then. You need to iterate over descriptors for current transaction only.
Quoted 21 lines
Quoted 13 lines
Quoted 13 lines
drivers/dma/mmp_pdma.c +13
-0+list_for_each_entry (desc_sw, &chan->chain_running, node) { +/* for the case of a running descriptor */ +if (desc_sw->desc.ddadr == ddadr && !running_desc_found) { +switch (chan->dir) { +case DMA_DEV_TO_MEM : +case DMA_MEM_TO_MEM : + reg = (chan->phy->idx <<4 ) +DTADR ; + cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dtadr; +break ; + +case DMA_MEM_TO_DEV : + reg = (chan->phy->idx <<4 ) +DSADR ;Quoted 8 lines
drivers/dma/mmp_pdma.c static void start_pending_queue(struct mmp_pdma_chan *chan) · line 355
Quoted 7 lines
drivers/dma/mmp_pdma.c +7
-0+ cur_pos =readl_relaxed (chan->phy->base + reg); + orig_pos = desc_sw->desc.dsadr; +break ; + +default : + cur_pos =0 ; + orig_pos =0 ;This makes no sense...
Quoted 1 line
What do you recommend for the default case? Just return 0?
why should direction be anything other than these? This is error!
~Vinod