Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 286123
b: refs/heads/master
c: 6d0709d
h: refs/heads/master
i:
  286121: 386ab95
  286119: 562c78a
v: v3
  • Loading branch information
Mika Westerberg authored and Vinod Koul committed Dec 5, 2011
1 parent 794ae63 commit b277faf
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b62cfc5e0e59d1e0192105144b724b0c332720a0
refs/heads/master: 6d0709d2000ae7dbead759715f57ba381b7057bb
60 changes: 48 additions & 12 deletions trunk/drivers/dma/ep93xx_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ static void ep93xx_dma_set_active(struct ep93xx_dma_chan *edmac,
static struct ep93xx_dma_desc *
ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
{
if (list_empty(&edmac->active))
return NULL;

return list_first_entry(&edmac->active, struct ep93xx_dma_desc, node);
}

Expand All @@ -263,16 +266,22 @@ ep93xx_dma_get_active(struct ep93xx_dma_chan *edmac)
*/
static bool ep93xx_dma_advance_active(struct ep93xx_dma_chan *edmac)
{
struct ep93xx_dma_desc *desc;

list_rotate_left(&edmac->active);

if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags))
return true;

desc = ep93xx_dma_get_active(edmac);
if (!desc)
return false;

/*
* If txd.cookie is set it means that we are back in the first
* descriptor in the chain and hence done with it.
*/
return !ep93xx_dma_get_active(edmac)->txd.cookie;
return !desc->txd.cookie;
}

/*
Expand Down Expand Up @@ -327,9 +336,15 @@ static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)

static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
{
struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
struct ep93xx_dma_desc *desc;
u32 bus_addr;

desc = ep93xx_dma_get_active(edmac);
if (!desc) {
dev_warn(chan2dev(edmac), "M2P: empty descriptor list\n");
return;
}

if (ep93xx_dma_chan_direction(&edmac->chan) == DMA_MEM_TO_DEV)
bus_addr = desc->src_addr;
else
Expand Down Expand Up @@ -491,7 +506,13 @@ static void m2m_hw_shutdown(struct ep93xx_dma_chan *edmac)

static void m2m_fill_desc(struct ep93xx_dma_chan *edmac)
{
struct ep93xx_dma_desc *desc = ep93xx_dma_get_active(edmac);
struct ep93xx_dma_desc *desc;

desc = ep93xx_dma_get_active(edmac);
if (!desc) {
dev_warn(chan2dev(edmac), "M2M: empty descriptor list\n");
return;
}

if (edmac->buffer == 0) {
writel(desc->src_addr, edmac->regs + M2M_SAR_BASE0);
Expand Down Expand Up @@ -669,24 +690,30 @@ static void ep93xx_dma_tasklet(unsigned long data)
{
struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
struct ep93xx_dma_desc *desc, *d;
dma_async_tx_callback callback;
void *callback_param;
dma_async_tx_callback callback = NULL;
void *callback_param = NULL;
LIST_HEAD(list);

spin_lock_irq(&edmac->lock);
/*
* If dma_terminate_all() was called before we get to run, the active
* list has become empty. If that happens we aren't supposed to do
* anything more than call ep93xx_dma_advance_work().
*/
desc = ep93xx_dma_get_active(edmac);
if (desc->complete) {
edmac->last_completed = desc->txd.cookie;
list_splice_init(&edmac->active, &list);
if (desc) {
if (desc->complete) {
edmac->last_completed = desc->txd.cookie;
list_splice_init(&edmac->active, &list);
}
callback = desc->txd.callback;
callback_param = desc->txd.callback_param;
}
spin_unlock_irq(&edmac->lock);

/* Pick up the next descriptor from the queue */
ep93xx_dma_advance_work(edmac);

callback = desc->txd.callback;
callback_param = desc->txd.callback_param;

/* Now we can release all the chained descriptors */
list_for_each_entry_safe(desc, d, &list, node) {
/*
Expand All @@ -706,13 +733,22 @@ static void ep93xx_dma_tasklet(unsigned long data)
static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id)
{
struct ep93xx_dma_chan *edmac = dev_id;
struct ep93xx_dma_desc *desc;
irqreturn_t ret = IRQ_HANDLED;

spin_lock(&edmac->lock);

desc = ep93xx_dma_get_active(edmac);
if (!desc) {
dev_warn(chan2dev(edmac),
"got interrupt while active list is empty\n");
spin_unlock(&edmac->lock);
return IRQ_NONE;
}

switch (edmac->edma->hw_interrupt(edmac)) {
case INTERRUPT_DONE:
ep93xx_dma_get_active(edmac)->complete = true;
desc->complete = true;
tasklet_schedule(&edmac->tasklet);
break;

Expand Down

0 comments on commit b277faf

Please sign in to comment.