summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorJoel Fernandes <joelf@ti.com>2013-08-29 18:05:44 -0500
committerVinod Koul <vinod.koul@intel.com>2013-09-04 18:38:46 +0530
commitb267b3bc1e781cef17ce026a72c7f0392fa45ada (patch)
tree90dd201c98fcb2e47e58776194e6c38753d9b4e7 /drivers/dma
parentc5f47990aad87deea42a330433fc57065ac1ade7 (diff)
dma: edma: Leave linked to Null slot instead of DUMMY slot
Dummy slot has been used as a way for missed-events not to be reported as missing. This has been particularly troublesome for cases where we might want to temporarily pause all incoming events. For EDMA DMAC, there is no way to do any such pausing of events as the occurence of the "next" event is not software controlled. Using "edma_pause" in IRQ handlers doesn't help as by then the event in concern from the slave is already missed. Linking a dummy slot, is seen to absorb these events which we didn't want to miss. So we don't link to dummy, but instead leave it linked to NULL set, allow an error condition and detect the channel that missed it. Consider the case where we have a scatter-list like: SG1->SG2->SG3->SG4->SG5->SG6->Null For ex, for a MAX_NR_SG of 2, earlier we were splitting this as: SG1->SG2->Null SG3->SG4->Null SG5->SG6->Null Now we split it as SG1->SG2->Null SG3->SG4->Null SG5->SG6->Dummy This approach results in lesser unwanted interrupts that occur for the last list split. The Dummy slot has the property of not raising an error condition if events are missed unlike the Null slot. We are OK with this as we're done with processing the whole list once we reach Dummy. Signed-off-by: Joel Fernandes <joelf@ti.com> [modifed duplicate s-o-b & patch title] Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/edma.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 2966ef06c477..9500720e4af4 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -158,13 +158,18 @@ static void edma_execute(struct edma_chan *echan)
/* Link to the previous slot if not the last set */
if (i != (nslots - 1))
edma_link(echan->slot[i], echan->slot[i+1]);
- /* Final pset links to the dummy pset */
- else
- edma_link(echan->slot[i], echan->ecc->dummy_slot);
}
edesc->processed += nslots;
+ /*
+ * If this is either the last set in a set of SG-list transactions
+ * then setup a link to the dummy slot, this results in all future
+ * events being absorbed and that's OK because we're done
+ */
+ if (edesc->processed == edesc->pset_nr)
+ edma_link(echan->slot[nslots-1], echan->ecc->dummy_slot);
+
edma_resume(echan->ch_num);
if (edesc->processed <= MAX_NR_SG) {