Commit e8a07d60 authored by Mark Brown's avatar Mark Brown
Browse files

Merge branch 'topic/rcar-dma' of...

Merge branch 'topic/rcar-dma' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-rcar
parents b723550d d23c9a0a
Loading
Loading
Loading
Loading
+21 −16
Original line number Original line Diff line number Diff line
@@ -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)
static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
{
{
	struct rcar_dmac_desc_page *page;
	struct rcar_dmac_desc_page *page;
	unsigned long flags;
	LIST_HEAD(list);
	LIST_HEAD(list);
	unsigned int i;
	unsigned int i;


@@ -482,10 +483,10 @@ static int rcar_dmac_desc_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
		list_add_tail(&desc->node, &list);
		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_splice_tail(&list, &chan->desc.free);
	list_add_tail(&page->node, &chan->desc.pages);
	list_add_tail(&page->node, &chan->desc.pages);
	spin_unlock_irq(&chan->lock);
	spin_unlock_irqrestore(&chan->lock, flags);


	return 0;
	return 0;
}
}
@@ -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)
static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
{
{
	struct rcar_dmac_desc *desc, *_desc;
	struct rcar_dmac_desc *desc, *_desc;
	unsigned long flags;
	LIST_HEAD(list);
	LIST_HEAD(list);


	/*
	/*
@@ -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
	 * list_for_each_entry_safe, isn't safe if we release the channel lock
	 * around the rcar_dmac_desc_put() call.
	 * 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);
	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) {
	list_for_each_entry_safe(desc, _desc, &list, node) {
		if (async_tx_test_ack(&desc->async_tx)) {
		if (async_tx_test_ack(&desc->async_tx)) {
@@ -539,9 +541,9 @@ static void rcar_dmac_desc_recycle_acked(struct rcar_dmac_chan *chan)
		return;
		return;


	/* Put the remaining descriptors back in the wait list. */
	/* 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);
	list_splice(&list, &chan->desc.wait);
	spin_unlock_irq(&chan->lock);
	spin_unlock_irqrestore(&chan->lock, flags);
}
}


/*
/*
@@ -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)
static struct rcar_dmac_desc *rcar_dmac_desc_get(struct rcar_dmac_chan *chan)
{
{
	struct rcar_dmac_desc *desc;
	struct rcar_dmac_desc *desc;
	unsigned long flags;
	int ret;
	int ret;


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


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


	while (list_empty(&chan->desc.free)) {
	while (list_empty(&chan->desc.free)) {
		/*
		/*
@@ -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
		 * allocated descriptors. If the allocation fails return an
		 * error.
		 * error.
		 */
		 */
		spin_unlock_irq(&chan->lock);
		spin_unlock_irqrestore(&chan->lock, flags);
		ret = rcar_dmac_desc_alloc(chan, GFP_NOWAIT);
		ret = rcar_dmac_desc_alloc(chan, GFP_NOWAIT);
		if (ret < 0)
		if (ret < 0)
			return NULL;
			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);
	desc = list_first_entry(&chan->desc.free, struct rcar_dmac_desc, node);
	list_del(&desc->node);
	list_del(&desc->node);


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


	return desc;
	return desc;
}
}
@@ -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)
static int rcar_dmac_xfer_chunk_alloc(struct rcar_dmac_chan *chan, gfp_t gfp)
{
{
	struct rcar_dmac_desc_page *page;
	struct rcar_dmac_desc_page *page;
	unsigned long flags;
	LIST_HEAD(list);
	LIST_HEAD(list);
	unsigned int i;
	unsigned int i;


@@ -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);
		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_splice_tail(&list, &chan->desc.chunks_free);
	list_add_tail(&page->node, &chan->desc.pages);
	list_add_tail(&page->node, &chan->desc.pages);
	spin_unlock_irq(&chan->lock);
	spin_unlock_irqrestore(&chan->lock, flags);


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


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


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


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


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


	return chunk;
	return chunk;
}
}