From 3565fe53334cd3f0d59ff5db0872de9370775a19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 May 2016 00:41:48 +0000 Subject: dmaengine: rcar-dmac: use list_add() on rcar_dmac_desc_put() For each descriptor, in addition to the memory used by the descriptors structure itself, the driver allocates a list of chunks as well as a buffer for hardware descriptors. Descriptors themselves are preallocated, and allocation of the chunks and buffer is performed the first time the descriptor is used. The memory isn't freed when the transfer is completed, as the chunks and buffer will be needed again when the descriptor is reused internally, so the driver keeps the memory around. If only a few descriptors are used concurrently, the current list_add_tail() implementation will result in all preallocated descriptors being used before going back to the first one, and will thus allocate chunks and a buffer for all preallocated descriptors. Using list_add() will put the complete descriptor at the head of the list of available descriptors, so the next transfer will be more likely to reuse a descriptor that already has associated memory instead of one that has never been used before. Signed-off-by: Kuninori Morimoto Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/dma/sh') diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index dfb17926297b..433e98260414 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -510,7 +510,7 @@ static void rcar_dmac_desc_put(struct rcar_dmac_chan *chan, spin_lock_irqsave(&chan->lock, flags); list_splice_tail_init(&desc->chunks, &chan->desc.chunks_free); - list_add_tail(&desc->node, &chan->desc.free); + list_add(&desc->node, &chan->desc.free); spin_unlock_irqrestore(&chan->lock, flags); } -- cgit v1.2.1 From 3544d2878817bd139dda238cdd86a15e1c03d037 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Farooq Date: Thu, 30 Jun 2016 17:15:15 +0200 Subject: dmaengine: rcar-dmac: use result of updated get_residue in tx_status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware might have complete the transfer but the interrupt handler might not have had a chance to run. If rcar_dmac_chan_get_residue() which reads HW registers finds that there is no residue return DMA_COMPLETE. Signed-off-by: Muhammad Hamza Farooq Signed-off-by: Geert Uytterhoeven [Niklas: add explanation in commit message] Signed-off-by: Niklas Söderlund Acked-by: Laurent Pinchart Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/dma/sh') diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 433e98260414..74c9563222bc 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1202,6 +1202,10 @@ static enum dma_status rcar_dmac_tx_status(struct dma_chan *chan, residue = rcar_dmac_chan_get_residue(rchan, cookie); spin_unlock_irqrestore(&rchan->lock, flags); + /* if there's no residue, the cookie is complete */ + if (!residue) + return DMA_COMPLETE; + dma_set_residue(txstate, residue); return status; -- cgit v1.2.1 From 0f78e3b58f5f99c991613db4477f893b53da5520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Thu, 30 Jun 2016 17:15:16 +0200 Subject: dmaengine: rcar-dmac: warn if transfer cannot start as TE = 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation states one should make sure both DE and TE are cleared before starting a transaction. This patch extends the current warning to look at both DE and TE. Based on previous work from Muhammad Hamza Farooq. Suggested-by: Muhammad Hamza Farooq Signed-off-by: Niklas Söderlund Acked-by: Laurent Pinchart Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/dma/sh') diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 74c9563222bc..72e7dab52c48 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -311,7 +311,7 @@ static bool rcar_dmac_chan_is_busy(struct rcar_dmac_chan *chan) { u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); - return (chcr & (RCAR_DMACHCR_DE | RCAR_DMACHCR_TE)) == RCAR_DMACHCR_DE; + return !!(chcr & (RCAR_DMACHCR_DE | RCAR_DMACHCR_TE)); } static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan) -- cgit v1.2.1 From 48c73659abae103a2f8531f825ce7a3f8dedbb39 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Farooq Date: Thu, 30 Jun 2016 17:15:17 +0200 Subject: dmaengine: rcar-dmac: Fixed active descriptor initializing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running descriptor pointer is set to NULL upon freeing resources. Other- wise, rcar_dmac_issue_pending might not start new transfers Signed-off-by: Muhammad Hamza Farooq Signed-off-by: Geert Uytterhoeven Signed-off-by: Niklas Söderlund Acked-by: Laurent Pinchart Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/dma/sh') diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 72e7dab52c48..561476c1e741 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -990,6 +990,8 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan) list_splice_init(&rchan->desc.done, &list); list_splice_init(&rchan->desc.wait, &list); + rchan->desc.running = NULL; + list_for_each_entry(desc, &list, node) rcar_dmac_realloc_hwdesc(rchan, desc, 0); -- cgit v1.2.1 From 55bd582b4d8c2266bc43cbae2ddfce31b489618f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 30 Jun 2016 17:15:18 +0200 Subject: dmaengine: rcar-dmac: Fix residue reporting for pending descriptors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cookies corresponding to pending transfers have a residue value equal to the full size of the corresponding descriptor. The driver miscomputes that and uses the size of the active descriptor instead. Fix it. Reported-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart [geert: Also check desc.active list] Signed-off-by: Geert Uytterhoeven Signed-off-by: Niklas Söderlund Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/dma/sh') diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 561476c1e741..0dd953884d1d 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1145,19 +1145,46 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, struct rcar_dmac_desc *desc = chan->desc.running; struct rcar_dmac_xfer_chunk *running = NULL; struct rcar_dmac_xfer_chunk *chunk; + enum dma_status status; unsigned int residue = 0; unsigned int dptr = 0; if (!desc) return 0; + /* + * If the cookie corresponds to a descriptor that has been completed + * there is no residue. The same check has already been performed by the + * caller but without holding the channel lock, so the descriptor could + * now be complete. + */ + status = dma_cookie_status(&chan->chan, cookie, NULL); + if (status == DMA_COMPLETE) + return 0; + /* * If the cookie doesn't correspond to the currently running transfer * then the descriptor hasn't been processed yet, and the residue is * equal to the full descriptor size. */ - if (cookie != desc->async_tx.cookie) - return desc->size; + if (cookie != desc->async_tx.cookie) { + list_for_each_entry(desc, &chan->desc.pending, node) { + if (cookie == desc->async_tx.cookie) + return desc->size; + } + list_for_each_entry(desc, &chan->desc.active, node) { + if (cookie == desc->async_tx.cookie) + return desc->size; + } + + /* + * No descriptor found for the cookie, there's thus no residue. + * This shouldn't happen if the calling driver passes a correct + * cookie value. + */ + WARN(1, "No descriptor for cookie!"); + return 0; + } /* * In descriptor mode the descriptor running pointer is not maintained -- cgit v1.2.1