spin_unlock_irqrestore(&pch->lock, flags);
}
+static inline int
+pl330_src_addr_in_desc(struct dma_pl330_desc *desc, unsigned int sar)
+{
+ return ((desc->px.src_addr <= sar) &&
+ (sar <= (desc->px.src_addr + desc->px.bytes)));
+}
+
+static inline int
+pl330_dst_addr_in_desc(struct dma_pl330_desc *desc, unsigned int dar)
+{
+ return ((desc->px.dst_addr <= dar) &&
+ (dar <= (desc->px.dst_addr + desc->px.bytes)));
+}
+
static unsigned int pl330_tx_residue(struct dma_chan *chan)
{
struct dma_pl330_chan *pch = to_pchan(chan);
void __iomem *regs = pch->dmac->pif.base;
struct pl330_thread *thrd = pch->pl330_chid;
struct dma_pl330_desc *desc;
- unsigned int sar;
+ unsigned int sar, dar;
+ unsigned int residue = 0;
unsigned long flags;
sar = readl(regs + SA(thrd->id));
+ dar = readl(regs + DA(thrd->id));
spin_lock_irqsave(&pch->lock, flags);
/* Find the desc related to the current buffer. */
- list_for_each_entry(desc, &pch->work_list, node)
- if (desc->px.src_addr <= sar &&
- sar < (desc->px.src_addr + desc->px.bytes))
- break;
+ list_for_each_entry(desc, &pch->work_list, node) {
+ if (desc->rqcfg.src_inc && pl330_src_addr_in_desc(desc, sar)) {
+ residue = desc->px.bytes - (sar - desc->px.src_addr);
+ goto found_unlock;
+ }
+ if (desc->rqcfg.dst_inc && pl330_dst_addr_in_desc(desc, dar)) {
+ residue = desc->px.bytes - (dar - desc->px.dst_addr);
+ goto found_unlock;
+ }
+ }
+found_unlock:
spin_unlock_irqrestore(&pch->lock, flags);
- if (!desc)
- return 0;
-
- return desc->px.bytes - (sar - desc->px.src_addr);
+ return residue;
}
static enum dma_status