Skip to contentSkip to conversation

dma: k3dma: Fix non-cyclic mode

PATCH In review John Stultz 4 participants 11 messages Jul 10, 2017 – Aug 25, 2017 dmaengine

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 dma: k3dma: Fix non-cyclic mode

From: Antonio Borneo <[email protected]>

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

This went unnoticed as the only user of k3dma was the i2s audio driver, but with a patch set to enable dma on SPI, the issue cropped up.

This patch resolves the issue by reverting part of the problematic commit.

This patch has been tested to ensure both audio playback and SPI works fine using DMA and that no memory leak is present.

Cc Vinod Koul <[email protected]>
Cc Dan Williams <[email protected]>
Cc Zhangfei Gao <[email protected]>
[jstultz: Expanded commit message a bit]
---
 drivers/dma/k3dma.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/dma/k3dma.c +4 -8
index 01e25c6..01d2a75 100644
@@ -223,7 +223,6 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
 			if (c && (tc1 & BIT(i))) {
 				spin_lock_irqsave(&c->vc.lock, flags);
 				vchan_cookie_complete(&p->ds_run->vd);
-				WARN_ON_ONCE(p->ds_done);
 				p->ds_done = p->ds_run;
 				p->ds_run = NULL;
 				spin_unlock_irqrestore(&c->vc.lock, flags);
@@ -274,13 +273,14 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
 		 */
 		list_del(&ds->vd.node);
 
-		WARN_ON_ONCE(c->phy->ds_run);
-		WARN_ON_ONCE(c->phy->ds_done);
 		c->phy->ds_run = ds;
+		c->phy->ds_done = NULL;
 		/* start dma */
 		k3_dma_set_desc(c->phy, &ds->desc_hw[0]);
 		return 0;
 	}
+	c->phy->ds_run = NULL;
+	c->phy->ds_done = NULL;
 	return -EAGAIN;
 }
 
@@ -722,11 +722,7 @@ static int k3_dma_terminate_all(struct dma_chan *chan)
 			k3_dma_free_desc(&p->ds_run->vd);
 			p->ds_run = NULL;
 		}
-		if (p->ds_done) {
-			k3_dma_free_desc(&p->ds_done->vd);
-			p->ds_done = NULL;
-		}
-
+		p->ds_done = NULL;
 	}
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 	vchan_dma_desc_free_list(&c->vc, &head);
Signature · 1 line
2.7.4
Acked-by on v1 1/1
#1 lore raw
Quoted 16 lines · John Stultz

From: Antonio Borneo <[email protected]>

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

This went unnoticed as the only user of k3dma was the i2s audio driver, but with a patch set to enable dma on SPI, the issue cropped up.

This patch resolves the issue by reverting part of the problematic commit.

This patch has been tested to ensure both audio playback and SPI works fine using DMA and that no memory leak is present.

Quoted 7 lines
Cc Vinod Koul <[email protected]>
Cc Dan Williams <[email protected]>
Cc Zhangfei Gao <[email protected]>
[jstultz: Expanded commit message a bit]

Thanks

#2 lore raw
In reply to John Stultz
Quoted 6 lines · John Stultz

From: Antonio Borneo <[email protected]>

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

Quoted 6 lines

This went unnoticed as the only user of k3dma was the i2s audio driver, but with a patch set to enable dma on SPI, the issue cropped up.

This patch resolves the issue by reverting part of the problematic commit.

Can you explain the fix here, how reverting helps around with that? Right now am not able to comprehend the fix on this..

Quoted 27 lines

This patch has been tested to ensure both audio playback and SPI works fine using DMA and that no memory leak is present.

Cc Vinod Koul <[email protected]>
Cc Dan Williams <[email protected]>
Cc Zhangfei Gao <[email protected]>
[jstultz: Expanded commit message a bit]
---
 drivers/dma/k3dma.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/dma/k3dma.c +0 -1
index 01e25c6..01d2a75 100644
@@ -223,7 +223,6 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
 			if (c && (tc1 & BIT(i))) {
 				spin_lock_irqsave(&c->vc.lock, flags);
 				vchan_cookie_complete(&p->ds_run->vd);
-				WARN_ON_ONCE(p->ds_done);
 				p->ds_done = p->ds_run;
 				p->ds_run = NULL;
 				spin_unlock_irqrestore(&c->vc.lock, flags);

drivers/dma/k3dma.c static int k3_dma_start_txd(struct k3_dma_chan *c) · line 278

Quoted 5 lines
drivers/dma/k3dma.c +0 -2
@@ -274,13 +273,14 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
 		 */
 		list_del(&ds->vd.node);
 
-		WARN_ON_ONCE(c->phy->ds_run);
-		WARN_ON_ONCE(c->phy->ds_done);

Not sure why WARN_ON should be removed?

Quoted 27 lines
drivers/dma/k3dma.c +4 -5
 		c->phy->ds_run = ds;
+		c->phy->ds_done = NULL;
 		/* start dma */
 		k3_dma_set_desc(c->phy, &ds->desc_hw[0]);
 		return 0;
 	}
+	c->phy->ds_run = NULL;
+	c->phy->ds_done = NULL;
 	return -EAGAIN;
 }
 
@@ -722,11 +722,7 @@ static int k3_dma_terminate_all(struct dma_chan *chan)
 			k3_dma_free_desc(&p->ds_run->vd);
 			p->ds_run = NULL;
 		}
-		if (p->ds_done) {
-			k3_dma_free_desc(&p->ds_done->vd);
-			p->ds_done = NULL;
-		}
-
+		p->ds_done = NULL;
 	}
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 	vchan_dma_desc_free_list(&c->vc, &head);
Signature · 1 line
2.7.4
Signature · 1 line
~Vinod
#3 lore raw
Quoted 11 lines · Vinod Koul
Quoted 10 lines · John Stultz

From: Antonio Borneo <[email protected]>

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

This went unnoticed as the only user of k3dma was the i2s audio driver, but with a patch set to enable dma on SPI, the issue cropped up.

Quoted 6 lines
Quoted 2 lines

This patch resolves the issue by reverting part of the problematic commit.

Can you explain the fix here, how reverting helps around with that? Right now am not able to comprehend the fix on this..

Hi Vinod,

thanks for your review.

The structure of the driver k3dma seams inspired to zx_dma that uses the same ds_run/ds_done method.
This driver k3dma was already working fine for non-cyclic use cases, like SPI. While preparing support for cyclic mode, the commit above removed some assignment to NULL for ds_run/ds_done at the end of the non-cyclic DMA transfer. As result, only the first non-cyclic DMA transfer completes successfully, the following non-cyclic DMA transfer hangs (plus it triggers one WARN_ON() because of the missing NULL initialization).

The main target of this patch is to re-add the NULL assignments.

Quoted 30 lines
Quoted 30 lines

This patch has been tested to ensure both audio playback and SPI works fine using DMA and that no memory leak is present.

Cc Vinod Koul <[email protected]>
Cc Dan Williams <[email protected]>
Cc Zhangfei Gao <[email protected]>
[jstultz: Expanded commit message a bit]
---
 drivers/dma/k3dma.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/dma/k3dma.c +0 -1
index 01e25c6..01d2a75 100644
@@ -223,7 +223,6 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
                      if (c && (tc1 & BIT(i))) {
                              spin_lock_irqsave(&c->vc.lock, flags);
                              vchan_cookie_complete(&p->ds_run->vd);
-                             WARN_ON_ONCE(p->ds_done);
                              p->ds_done = p->ds_run;
                              p->ds_run = NULL;
                              spin_unlock_irqrestore(&c->vc.lock, flags);
@@ -274,13 +273,14 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
               */
              list_del(&ds->vd.node);
 
Quoted 4 lines

drivers/dma/k3dma.c static int k3_dma_start_txd(struct k3_dma_chan *c) · line 278

Quoted 2 lines
drivers/dma/k3dma.c +0 -2
-             WARN_ON_ONCE(c->phy->ds_run);
-             WARN_ON_ONCE(c->phy->ds_done);

Not sure why WARN_ON should be removed?

The commit above added them. Now that the logic on ds_run/ds_done is fixed, I do not see reason for them anymore.

Best Regards
Antonio

Quoted 31 lines
Quoted 26 lines
drivers/dma/k3dma.c +4 -6
              c->phy->ds_run = ds;
+             c->phy->ds_done = NULL;
              /* start dma */
              k3_dma_set_desc(c->phy, &ds->desc_hw[0]);
              return 0;
      }
+     c->phy->ds_run = NULL;
+     c->phy->ds_done = NULL;
      return -EAGAIN;
 }
 
@@ -722,11 +722,7 @@ static int k3_dma_terminate_all(struct dma_chan *chan)
                      k3_dma_free_desc(&p->ds_run->vd);
                      p->ds_run = NULL;
              }
-             if (p->ds_done) {
-                     k3_dma_free_desc(&p->ds_done->vd);
-                     p->ds_done = NULL;
-             }
-
+             p->ds_done = NULL;
      }
      spin_unlock_irqrestore(&c->vc.lock, flags);
      vchan_dma_desc_free_list(&c->vc, &head);
--
Quoted 2 lines

2.7.4

--
~Vinod

#4 lore raw
Quoted 32 lines · Antonio Borneo
Quoted 11 lines · Vinod Koul
Quoted 10 lines · John Stultz

From: Antonio Borneo <[email protected]>

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

This went unnoticed as the only user of k3dma was the i2s audio driver, but with a patch set to enable dma on SPI, the issue cropped up.

Quoted 6 lines
Quoted 2 lines

This patch resolves the issue by reverting part of the problematic commit.

Can you explain the fix here, how reverting helps around with that? Right now am not able to comprehend the fix on this..

Hi Vinod,

thanks for your review.

The structure of the driver k3dma seams inspired to zx_dma that uses the same ds_run/ds_done method.
This driver k3dma was already working fine for non-cyclic use cases, like SPI. While preparing support for cyclic mode, the commit above removed some assignment to NULL for ds_run/ds_done at the end of the non-cyclic DMA transfer. As result, only the first non-cyclic DMA transfer completes successfully, the following non-cyclic DMA transfer hangs (plus it triggers one WARN_ON() because of the missing NULL initialization).

Quoted 1 line

The main target of this patch is to re-add the NULL assignments.

Okay so fix is only adding NULL assignments, and which was not at all clear from the changelog. The changelog need to give reviewers and maintainers and idea on why a change was done and the details of the fix.

Quoted 30 lines
Quoted 30 lines
Quoted 30 lines

This patch has been tested to ensure both audio playback and SPI works fine using DMA and that no memory leak is present.

Cc Vinod Koul <[email protected]>
Cc Dan Williams <[email protected]>
Cc Zhangfei Gao <[email protected]>
[jstultz: Expanded commit message a bit]
---
 drivers/dma/k3dma.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/dma/k3dma.c +0 -1
index 01e25c6..01d2a75 100644
@@ -223,7 +223,6 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
                      if (c && (tc1 & BIT(i))) {
                              spin_lock_irqsave(&c->vc.lock, flags);
                              vchan_cookie_complete(&p->ds_run->vd);
-                             WARN_ON_ONCE(p->ds_done);
                              p->ds_done = p->ds_run;
                              p->ds_run = NULL;
                              spin_unlock_irqrestore(&c->vc.lock, flags);
@@ -274,13 +273,14 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
               */
              list_del(&ds->vd.node);
 
Quoted 7 lines
Quoted 4 lines

drivers/dma/k3dma.c static int k3_dma_start_txd(struct k3_dma_chan *c) · line 278

Quoted 2 lines
drivers/dma/k3dma.c +0 -2
-             WARN_ON_ONCE(c->phy->ds_run);
-             WARN_ON_ONCE(c->phy->ds_done);

Not sure why WARN_ON should be removed?

The commit above added them. Now that the logic on ds_run/ds_done is fixed, I do not see reason for them anymore.

Since this is not a revert and only fix, I would prefer this to be removed from fix, if you want to remove these please do send a second patch as this has nothing to do with the fix

While at it, also change the patch title to dmaengine: ....

Thanks

Signature · 1 line
~Vinod
#5 lore raw
Quoted 33 lines · Vinod Koul
Quoted 32 lines · Antonio Borneo
Quoted 11 lines · Vinod Koul
Quoted 10 lines · John Stultz

From: Antonio Borneo <[email protected]>

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

This went unnoticed as the only user of k3dma was the i2s audio driver, but with a patch set to enable dma on SPI, the issue cropped up.

Quoted 6 lines
Quoted 2 lines

This patch resolves the issue by reverting part of the problematic commit.

Can you explain the fix here, how reverting helps around with that? Right now am not able to comprehend the fix on this..

Hi Vinod,

thanks for your review.

The structure of the driver k3dma seams inspired to zx_dma that uses the same ds_run/ds_done method.
This driver k3dma was already working fine for non-cyclic use cases, like SPI. While preparing support for cyclic mode, the commit above removed some assignment to NULL for ds_run/ds_done at the end of the non-cyclic DMA transfer. As result, only the first non-cyclic DMA transfer completes successfully, the following non-cyclic DMA transfer hangs (plus it triggers one WARN_ON() because of the missing NULL initialization).

Quoted 5 lines
Quoted 1 line

The main target of this patch is to re-add the NULL assignments.

Okay so fix is only adding NULL assignments, and which was not at all clear from the changelog. The changelog need to give reviewers and maintainers and idea on why a change was done and the details of the fix.

Ok, I will make it clear in V2

Quoted 36 lines
Quoted 36 lines
Quoted 35 lines
Quoted 28 lines

This patch has been tested to ensure both audio playback and SPI works fine using DMA and that no memory leak is present.

Cc Vinod Koul <[email protected]>
Cc Dan Williams <[email protected]>
Cc Zhangfei Gao <[email protected]>
[jstultz: Expanded commit message a bit]
---
 drivers/dma/k3dma.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/dma/k3dma.c +0 -1
index 01e25c6..01d2a75 100644
@@ -223,7 +223,6 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
                      if (c && (tc1 & BIT(i))) {
                              spin_lock_irqsave(&c->vc.lock, flags);
                              vchan_cookie_complete(&p->ds_run->vd);
-                             WARN_ON_ONCE(p->ds_done);
                              p->ds_done = p->ds_run;
                              p->ds_run = NULL;
                              spin_unlock_irqrestore(&c->vc.lock, flags);

drivers/dma/k3dma.c static int k3_dma_start_txd(struct k3_dma_chan *c) · line 278

Quoted 5 lines
drivers/dma/k3dma.c +0 -2
@@ -274,13 +273,14 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
               */
              list_del(&ds->vd.node);
 
-             WARN_ON_ONCE(c->phy->ds_run);
-             WARN_ON_ONCE(c->phy->ds_done);

Not sure why WARN_ON should be removed?

Quoted 8 lines
Quoted 2 lines

The commit above added them. Now that the logic on ds_run/ds_done is fixed, I do not see reason for them anymore.

Since this is not a revert and only fix, I would prefer this to be removed from fix, if you want to remove these please do send a second patch as this has nothing to do with the fix

While at it, also change the patch title to dmaengine: ....

Ok, I will split it and change the title.

Thanks
Antonio

Quoted 4 lines

Thanks
--
~Vinod

#6 lore raw

v2 cover dmaengine: k3dma: Fix non-cyclic mode

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

This v2 splits the initial patch in three parts:
- the real fix for non-cyclic mode
- another fix for a double free introduced in the same commit
- cosmetic removal of useless ON_WARN_ONCE()

Thread in https://patchwork.kernel.org/patch/9833791/

v1 -> v2
- split the patch
- change patch title to "dmaengine: ..."

Antonio Borneo (3):
dmaengine: k3dma: fix non-cyclic mode
dmaengine: k3dma: fix double free of descriptor
dmaengine: k3dma: remove useless ON_WARN_ONCE()

 drivers/dma/k3dma.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
Signature · 1 line
1.9.1
#7 lore raw

PATCH v2 1/3 dmaengine: k3dma: fix non-cyclic mode

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

This went unnoticed as the only user of k3dma was the i2s audio driver but, with a patch set to enable dma on SPI, the issue popped out.

The fix re-applies the initialization to ds_run/ds_done in k3_dma_start_txd() that were removed by the commit above.

Also, one of the calls to k3_dma_start_txd() is triggered by (ds_done != NULL), so remove the noisy and useless call to WARN_ON_ONCE().

---
To: [email protected]
To: Vinod Koul <[email protected]>
To: Dan Williams <[email protected]>
Cc: [email protected]
Cc: John Stultz <[email protected]>
Cc: Zhangfei Gao <[email protected]>

---
 drivers/dma/k3dma.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/k3dma.c +3 -1
index 01e25c6..c00eb12 100644
@@ -275,12 +275,14 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
 		list_del(&ds->vd.node);
 
 		WARN_ON_ONCE(c->phy->ds_run);
-		WARN_ON_ONCE(c->phy->ds_done);
 		c->phy->ds_run = ds;
+		c->phy->ds_done = NULL;
 		/* start dma */
 		k3_dma_set_desc(c->phy, &ds->desc_hw[0]);
 		return 0;
 	}
+	c->phy->ds_run = NULL;
+	c->phy->ds_done = NULL;
 	return -EAGAIN;
 }
 
Signature · 1 line
1.9.1
#8 lore raw

PATCH v2 2/3 dmaengine: k3dma: fix double free of descriptor

In reply to Antonio Borneo

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") adds code to free the descriptor in ds_done.

In cyclic mode, ds_done is never used and it's always NULL, so the added code is not executed.

In non-cyclic mode, ds_done is used as a flag: when not NULL it signals that the descriptor has been consumed. No need to free it because it would be free by vchan_complete().

The fix takes back the code changed by the commit above:
- remove the free on the descriptor;
- initialize ds_done to NULL for the next run.

---
To: [email protected]
To: Vinod Koul <[email protected]>
To: Dan Williams <[email protected]>
Cc: [email protected]
Cc: John Stultz <[email protected]>
Cc: Zhangfei Gao <[email protected]>

---
 drivers/dma/k3dma.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/dma/k3dma.c +1 -5
index c00eb12..b769623 100644
@@ -724,11 +724,7 @@ static int k3_dma_terminate_all(struct dma_chan *chan)
 			k3_dma_free_desc(&p->ds_run->vd);
 			p->ds_run = NULL;
 		}
-		if (p->ds_done) {
-			k3_dma_free_desc(&p->ds_done->vd);
-			p->ds_done = NULL;
-		}
-
+		p->ds_done = NULL;
 	}
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 	vchan_dma_desc_free_list(&c->vc, &head);
Signature · 1 line
1.9.1
#9 lore raw

PATCH v2 3/3 dmaengine: k3dma: remove useless ON_WARN_ONCE()

In reply to Antonio Borneo

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") adds few calls to ON_WARN_ONCE() to track the use of ds_run/ds_done.

After the two fixes:
- dmaengine: k3dma: fix non-cyclic mode
- dmaengine: k3dma: fix re-free of the same descriptor the behaviour of ds_run/ds_done is properly fixed. The remaining ON_WARN_ONCE() are never triggered and can be removed.

---
To: [email protected]
To: Vinod Koul <[email protected]>
To: Dan Williams <[email protected]>
Cc: [email protected]
Cc: John Stultz <[email protected]>
Cc: Zhangfei Gao <[email protected]>

---
 drivers/dma/k3dma.c | 2 --
 1 file changed, 2 deletions(-)
drivers/dma/k3dma.c +0 -2
index b769623..01d2a75 100644
@@ -223,7 +223,6 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
 			if (c && (tc1 & BIT(i))) {
 				spin_lock_irqsave(&c->vc.lock, flags);
 				vchan_cookie_complete(&p->ds_run->vd);
-				WARN_ON_ONCE(p->ds_done);
 				p->ds_done = p->ds_run;
 				p->ds_run = NULL;
 				spin_unlock_irqrestore(&c->vc.lock, flags);
@@ -274,7 +273,6 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
 		 */
 		list_del(&ds->vd.node);
 
-		WARN_ON_ONCE(c->phy->ds_run);
 		c->phy->ds_run = ds;
 		c->phy->ds_done = NULL;
 		/* start dma */
Signature · 1 line
1.9.1
Applied
#10 lore raw

Re: [PATCH v2 0/3] dmaengine: k3dma: Fix non-cyclic mode

In reply to Antonio Borneo
Quoted 3 lines · Antonio Borneo

Commit 36387a2b1f62b5c087c5fe6f0f7b23b94f722ad7 ("k3dma: Fix memory handling in preparation for cyclic mode") broke the logic around ds_run/ds_done in case of non-cyclic DMA.

Applied, thanks

Signature · 1 line
~Vinod