Skip to content

Commit

Permalink
Merge branch 'topic/rcar-dma' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/broonie/sound into asoc-rcar
  • Loading branch information
Mark Brown committed May 22, 2015
2 parents b723550 + d23c9a0 commit e8a07d6
Showing 1 changed file with 21 additions and 16 deletions.
37 changes: 21 additions & 16 deletions drivers/dma/sh/rcar-dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ static dma_cookie_t rcar_dmac_tx_submit(struct dma_async_tx_descriptor *tx)
static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
{
struct rcar_dmac_desc_page *page;
unsigned long flags;
LIST_HEAD(list);
unsigned int i;

Expand All @@ -482,10 +483,10 @@ static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
list_add_tail(&desc->node, &list);
}

spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);
list_splice_tail(&list, &chan->desc.free);
list_add_tail(&page->node, &chan->desc.pages);
spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);

return 0;
}
Expand Down Expand Up @@ -516,6 +517,7 @@ static void rcar_dmac_desc_put(struct rcar_dmac_chan *chan,
static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
{
struct rcar_dmac_desc *desc, *_desc;
unsigned long flags;
LIST_HEAD(list);

/*
Expand All @@ -524,9 +526,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
* list_for_each_entry_safe, isn't safe if we release the channel lock
* around the rcar_dmac_desc_put() call.
*/
spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);
list_splice_init(&chan->desc.wait, &list);
spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);

list_for_each_entry_safe(desc, _desc, &list, node) {
if (async_tx_test_ack(&desc->async_tx)) {
Expand All @@ -539,9 +541,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
return;

/* Put the remaining descriptors back in the wait list. */
spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);
list_splice(&list, &chan->desc.wait);
spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);
}

/*
Expand All @@ -556,12 +558,13 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
{
struct rcar_dmac_desc *desc;
unsigned long flags;
int ret;

/* Recycle acked descriptors before attempting allocation. */
rcar_dmac_desc_recycle_acked(chan);

spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);

while (list_empty(&chan->desc.free)) {
/*
Expand All @@ -570,17 +573,17 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
* allocated descriptors. If the allocation fails return an
* error.
*/
spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);
ret = rcar_dmac_desc_alloc(chan, GFP_NOWAIT);
if (ret < 0)
return NULL;
spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);
}

desc = list_first_entry(&chan->desc.free, struct rcar_dmac_desc, node);
list_del(&desc->node);

spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);

return desc;
}
Expand All @@ -593,6 +596,7 @@ static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
{
struct rcar_dmac_desc_page *page;
unsigned long flags;
LIST_HEAD(list);
unsigned int i;

Expand All @@ -606,10 +610,10 @@ static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
list_add_tail(&chunk->node, &list);
}

spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);
list_splice_tail(&list, &chan->desc.chunks_free);
list_add_tail(&page->node, &chan->desc.pages);
spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);

return 0;
}
Expand All @@ -627,9 +631,10 @@ static struct rcar_dmac_xfer_chunk *
rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan)
{
struct rcar_dmac_xfer_chunk *chunk;
unsigned long flags;
int ret;

spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);

while (list_empty(&chan->desc.chunks_free)) {
/*
Expand All @@ -638,18 +643,18 @@ rcar_dmac_xfer_chunk_get(struct rcar_dmac_chan *chan)
* allocated descriptors. If the allocation fails return an
* error.
*/
spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);
ret = rcar_dmac_xfer_chunk_alloc(chan, GFP_NOWAIT);
if (ret < 0)
return NULL;
spin_lock_irq(&chan->lock);
spin_lock_irqsave(&chan->lock, flags);
}

chunk = list_first_entry(&chan->desc.chunks_free,
struct rcar_dmac_xfer_chunk, node);
list_del(&chunk->node);

spin_unlock_irq(&chan->lock);
spin_unlock_irqrestore(&chan->lock, flags);

return chunk;
}
Expand Down

0 comments on commit e8a07d6

Please sign in to comment.