summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>2018-02-02 13:05:15 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-05-30 08:52:36 +0300
commitb3b26307208e93182df45231ef94483902cca43a (patch)
treeed1190d757017dd3841da9d544abf5f9fe08ad72 /drivers/dma
parente41de468a6f4f25895242ada6d95240a3ce968d8 (diff)
downloadlinux-b3b26307208e93182df45231ef94483902cca43a.tar.xz
dmaengine: rcar-dmac: Check the done lists in rcar_dmac_chan_get_residue()
[ Upstream commit 3e081628d510b2ddbe493371d9c574d9275da17e ] This patch fixes an issue that a race condition happens between a client driver and the rcar-dmac driver: - The rcar_dmac_isr_transfer_end() is called. - The done list appears, and desc.running is the next active list. - rcar_dmac_chan_get_residue() is called by a client driver before rcar_dmac_isr_channel_thread() is called. - The rcar_dmac_chan_get_residue() will not find any descriptors. - And, the following WARNING happens: WARN(1, "No descriptor for cookie!"); The sh-sci driver with HSCIF (921,600bps) on R-Car H3 can cause this situation. So, this patch checks the done lists in rcar_dmac_chan_get_residue() and returns zero if the done lists has the argument cookie. Tested-by: Nguyen Viet Dung <dung.nguyen.aj@renesas.com> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/sh/rcar-dmac.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7e85e9e20b16..9d6ce5051d8f 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1264,8 +1264,17 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
* 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.
+ * Also, a client driver is possible to call this function before
+ * rcar_dmac_isr_channel_thread() runs. In this case, the "desc.running"
+ * will be the next descriptor, and the done list will appear. So, if
+ * the argument cookie matches the done list's cookie, we can assume
+ * the residue is zero.
*/
if (cookie != desc->async_tx.cookie) {
+ list_for_each_entry(desc, &chan->desc.done, node) {
+ if (cookie == desc->async_tx.cookie)
+ return 0;
+ }
list_for_each_entry(desc, &chan->desc.pending, node) {
if (cookie == desc->async_tx.cookie)
return desc->size;