All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio
@ 2016-07-21  3:53 John Stultz
  2016-07-21  3:53 ` [PATCH 1/7] k3dma: Fix hisi burst clipping John Stultz
                   ` (6 more replies)
  0 siblings, 7 replies; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Mark Brown, Andy Green

Per Mark's suggestion, I've split out the k3dma changes
on their own as they are mostly fixes and the addition
of cyclic mode.

New in v3:
* With inspiration from YongQin Liu, I figured out the reason we
were seeing occasional DMA ERR issues: The desc structures were
being allocated with kzalloc and so changes weren't necessarily
being flushed to memory before the transfers started. I fixed
this, but also uncoverd a memory leak that was happening in
cyclic mode, so I fixed that as well.

Thoughts and comments would be appreciated!

thanks
-john

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Andy Green <andy@warmcat.com>

Andy Green (4):
  k3dma: Fix hisi burst clipping
  k3dma: Fix dma err offsets
  k3dma: Fix "nobody cared" message seen on any error
  k3dma: Add cyclic mode for audio

John Stultz (3):
  k3dma: Fix memory handling with cyclic mode
  k3dma: Fix occasional DMA ERR issue by using proper dma api
  Kconfig: Allow k3dma driver to be selected for more then HISI3xx
    platforms

 drivers/dma/Kconfig |   2 +-
 drivers/dma/k3dma.c | 219 ++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 181 insertions(+), 40 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/7] k3dma: Fix hisi burst clipping
  2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
@ 2016-07-21  3:53 ` John Stultz
  2016-07-24  7:25   ` Vinod Koul
  2016-07-21  3:53 ` [PATCH 2/7] k3dma: Fix dma err offsets John Stultz
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Mark Brown, Andy Green,
	John Stultz

From: Andy Green <andy.green@linaro.org>

Max burst len is a 4-bit field, but at the moment it's clipped with
a 5-bit constant... reduce it to that which can be expressed

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Andy Green <andy@warmcat.com>
Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Andy Green <andy.green@linaro.org>
[jstultz: Forward ported to mainline]
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/dma/k3dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index 1ba2fd7..d01a11d 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -552,7 +552,7 @@ static int k3_dma_config(struct dma_chan *chan,
 	c->ccfg |= (val << 12) | (val << 16);
 
 	if ((maxburst == 0) || (maxburst > 16))
-		val = 16;
+		val = 15;
 	else
 		val = maxburst - 1;
 	c->ccfg |= (val << 20) | (val << 24);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 2/7] k3dma: Fix dma err offsets
  2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
  2016-07-21  3:53 ` [PATCH 1/7] k3dma: Fix hisi burst clipping John Stultz
@ 2016-07-21  3:53 ` John Stultz
  2016-07-21  3:53 ` [PATCH 3/7] k3dma: Fix "nobody cared" message seen on any error John Stultz
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Mark Brown, Andy Green,
	John Stultz

From: Andy Green <andy.green@linaro.org>

The offsets for ERR1 and ERR2 are wrong actually.
That's why you can never clear an error.

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Andy Green <andy@warmcat.com>
Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Andy Green <andy.green@linaro.org>
[jstultz: Forward ported to mainline]
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/dma/k3dma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index d01a11d..8dd050c 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -34,8 +34,8 @@
 #define INT_ERR1_MASK		0x20
 #define INT_ERR2_MASK		0x24
 #define INT_TC1_RAW		0x600
-#define INT_ERR1_RAW		0x608
-#define INT_ERR2_RAW		0x610
+#define INT_ERR1_RAW		0x610
+#define INT_ERR2_RAW		0x618
 #define CH_PRI			0x688
 #define CH_STAT			0x690
 #define CX_CUR_CNT		0x704
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 3/7] k3dma: Fix "nobody cared" message seen on any error
  2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
  2016-07-21  3:53 ` [PATCH 1/7] k3dma: Fix hisi burst clipping John Stultz
  2016-07-21  3:53 ` [PATCH 2/7] k3dma: Fix dma err offsets John Stultz
@ 2016-07-21  3:53 ` John Stultz
  2016-07-21  3:53 ` [PATCH 4/7] k3dma: Add cyclic mode for audio John Stultz
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Mark Brown, Andy Green,
	John Stultz

From: Andy Green <andy.green@linaro.org>

As it was before, as soon as the DMAC IP felt there was an error
he would return IRQ_NONE since no actual transfer had completed.

After spinning on that for 100K interrupts, Linux yanks the IRQ with
a "nobody cared" error.

This patch lets it handle the interrupt and keep the IRQ alive.

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Andy Green <andy@warmcat.com>
Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Andy Green <andy.green@linaro.org>
[jstultz: Forward ported to mainline]
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/dma/k3dma.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index 8dd050c..c2906a82 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -220,11 +220,13 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
 	writel_relaxed(err1, d->base + INT_ERR1_RAW);
 	writel_relaxed(err2, d->base + INT_ERR2_RAW);
 
-	if (irq_chan) {
+	if (irq_chan)
 		tasklet_schedule(&d->task);
+
+	if (irq_chan || err1 || err2)
 		return IRQ_HANDLED;
-	} else
-		return IRQ_NONE;
+
+	return IRQ_NONE;
 }
 
 static int k3_dma_start_txd(struct k3_dma_chan *c)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 4/7] k3dma: Add cyclic mode for audio
  2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
                   ` (2 preceding siblings ...)
  2016-07-21  3:53 ` [PATCH 3/7] k3dma: Fix "nobody cared" message seen on any error John Stultz
@ 2016-07-21  3:53 ` John Stultz
  2016-07-24  7:31   ` Vinod Koul
  2016-07-21  3:53 ` [PATCH 5/7] k3dma: Fix memory handling with cyclic mode John Stultz
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Mark Brown, Andy Green,
	John Stultz

From: Andy Green <andy.green@linaro.org>

Currently the k3dma driver doesn't offer the cyclic mode
necessary for handling audio.

This patch adds it.

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Andy Green <andy@warmcat.com>
Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Andy Green <andy.green@linaro.org>
[jstultz: Forward ported to mainline, removed a few
 bits of logic that didn't seem to have much effect]
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
v2:
* Changed pr_debug() -> dev_debug() suggested by Zhangfei
---
 drivers/dma/k3dma.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 109 insertions(+), 14 deletions(-)

diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index c2906a82..8e4c845 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 - 2015 Linaro Ltd.
  * Copyright (c) 2013 Hisilicon Limited.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,22 +25,27 @@
 
 #define DRIVER_NAME		"k3-dma"
 #define DMA_MAX_SIZE		0x1ffc
+#define DMA_CYCLIC_MAX_PERIOD	0x1000
 
 #define INT_STAT		0x00
 #define INT_TC1			0x04
+#define INT_TC2			0x08
 #define INT_ERR1		0x0c
 #define INT_ERR2		0x10
 #define INT_TC1_MASK		0x18
+#define INT_TC2_MASK		0x1c
 #define INT_ERR1_MASK		0x20
 #define INT_ERR2_MASK		0x24
 #define INT_TC1_RAW		0x600
+#define INT_TC2_RAW		0x608
 #define INT_ERR1_RAW		0x610
 #define INT_ERR2_RAW		0x618
 #define CH_PRI			0x688
 #define CH_STAT			0x690
 #define CX_CUR_CNT		0x704
 #define CX_LLI			0x800
-#define CX_CNT			0x810
+#define CX_CNT1			0x80c
+#define CX_CNT0			0x810
 #define CX_SRC			0x814
 #define CX_DST			0x818
 #define CX_CFG			0x81c
@@ -49,6 +54,7 @@
 
 #define CX_LLI_CHAIN_EN		0x2
 #define CX_CFG_EN		0x1
+#define CX_CFG_NODEIRQ		BIT(1)
 #define CX_CFG_MEM2PER		(0x1 << 2)
 #define CX_CFG_PER2MEM		(0x2 << 2)
 #define CX_CFG_SRCINCR		(0x1 << 31)
@@ -81,6 +87,7 @@ struct k3_dma_chan {
 	enum dma_transfer_direction dir;
 	dma_addr_t		dev_addr;
 	enum dma_status		status;
+	bool			cyclic;
 };
 
 struct k3_dma_phy {
@@ -134,6 +141,7 @@ static void k3_dma_terminate_chan(struct k3_dma_phy *phy, struct k3_dma_dev *d)
 
 	val = 0x1 << phy->idx;
 	writel_relaxed(val, d->base + INT_TC1_RAW);
+	writel_relaxed(val, d->base + INT_TC2_RAW);
 	writel_relaxed(val, d->base + INT_ERR1_RAW);
 	writel_relaxed(val, d->base + INT_ERR2_RAW);
 }
@@ -141,7 +149,7 @@ static void k3_dma_terminate_chan(struct k3_dma_phy *phy, struct k3_dma_dev *d)
 static void k3_dma_set_desc(struct k3_dma_phy *phy, struct k3_desc_hw *hw)
 {
 	writel_relaxed(hw->lli, phy->base + CX_LLI);
-	writel_relaxed(hw->count, phy->base + CX_CNT);
+	writel_relaxed(hw->count, phy->base + CX_CNT0);
 	writel_relaxed(hw->saddr, phy->base + CX_SRC);
 	writel_relaxed(hw->daddr, phy->base + CX_DST);
 	writel_relaxed(AXI_CFG_DEFAULT, phy->base + AXI_CFG);
@@ -175,11 +183,13 @@ static void k3_dma_enable_dma(struct k3_dma_dev *d, bool on)
 
 		/* unmask irq */
 		writel_relaxed(0xffff, d->base + INT_TC1_MASK);
+		writel_relaxed(0xffff, d->base + INT_TC2_MASK);
 		writel_relaxed(0xffff, d->base + INT_ERR1_MASK);
 		writel_relaxed(0xffff, d->base + INT_ERR2_MASK);
 	} else {
 		/* mask irq */
 		writel_relaxed(0x0, d->base + INT_TC1_MASK);
+		writel_relaxed(0x0, d->base + INT_TC2_MASK);
 		writel_relaxed(0x0, d->base + INT_ERR1_MASK);
 		writel_relaxed(0x0, d->base + INT_ERR2_MASK);
 	}
@@ -192,24 +202,31 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
 	struct k3_dma_chan *c;
 	u32 stat = readl_relaxed(d->base + INT_STAT);
 	u32 tc1  = readl_relaxed(d->base + INT_TC1);
+	u32 tc2  = readl_relaxed(d->base + INT_TC2);
 	u32 err1 = readl_relaxed(d->base + INT_ERR1);
 	u32 err2 = readl_relaxed(d->base + INT_ERR2);
 	u32 i, irq_chan = 0;
 
 	while (stat) {
 		i = __ffs(stat);
-		stat &= (stat - 1);
-		if (likely(tc1 & BIT(i))) {
+		stat &= ~BIT(i);
+		if (likely(tc1 & BIT(i)) || (tc2 & BIT(i))) {
+			unsigned long flags;
+
 			p = &d->phy[i];
 			c = p->vchan;
-			if (c) {
-				unsigned long flags;
-
+			if (c && (tc1 & BIT(i))) {
 				spin_lock_irqsave(&c->vc.lock, flags);
 				vchan_cookie_complete(&p->ds_run->vd);
 				p->ds_done = p->ds_run;
 				spin_unlock_irqrestore(&c->vc.lock, flags);
 			}
+			if (c && (tc2 & BIT(i))) {
+				spin_lock_irqsave(&c->vc.lock, flags);
+				if (p->ds_run != NULL)
+					vchan_cyclic_callback(&p->ds_run->vd);
+				spin_unlock_irqrestore(&c->vc.lock, flags);
+			}
 			irq_chan |= BIT(i);
 		}
 		if (unlikely((err1 & BIT(i)) || (err2 & BIT(i))))
@@ -217,6 +234,7 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
 	}
 
 	writel_relaxed(irq_chan, d->base + INT_TC1_RAW);
+	writel_relaxed(irq_chan, d->base + INT_TC2_RAW);
 	writel_relaxed(err1, d->base + INT_ERR1_RAW);
 	writel_relaxed(err2, d->base + INT_ERR2_RAW);
 
@@ -352,7 +370,7 @@ static enum dma_status k3_dma_tx_status(struct dma_chan *chan,
 	 * its total size.
 	 */
 	vd = vchan_find_desc(&c->vc, cookie);
-	if (vd) {
+	if (vd && !c->cyclic) {
 		bytes = container_of(vd, struct k3_dma_desc_sw, vd)->size;
 	} else if ((!p) || (!p->ds_run)) {
 		bytes = 0;
@@ -362,7 +380,8 @@ static enum dma_status k3_dma_tx_status(struct dma_chan *chan,
 
 		bytes = k3_dma_get_curr_cnt(d, p);
 		clli = k3_dma_get_curr_lli(p);
-		index = (clli - ds->desc_hw_lli) / sizeof(struct k3_desc_hw);
+		index = ((clli - ds->desc_hw_lli) /
+				sizeof(struct k3_desc_hw)) + 1;
 		for (; index < ds->desc_num; index++) {
 			bytes += ds->desc_hw[index].count;
 			/* end of lli */
@@ -403,9 +422,10 @@ static void k3_dma_issue_pending(struct dma_chan *chan)
 static void k3_dma_fill_desc(struct k3_dma_desc_sw *ds, dma_addr_t dst,
 			dma_addr_t src, size_t len, u32 num, u32 ccfg)
 {
-	if ((num + 1) < ds->desc_num)
+	if (num != ds->desc_num - 1)
 		ds->desc_hw[num].lli = ds->desc_hw_lli + (num + 1) *
 			sizeof(struct k3_desc_hw);
+
 	ds->desc_hw[num].lli |= CX_LLI_CHAIN_EN;
 	ds->desc_hw[num].count = len;
 	ds->desc_hw[num].saddr = src;
@@ -431,6 +451,7 @@ static struct dma_async_tx_descriptor *k3_dma_prep_memcpy(
 		dev_dbg(chan->device->dev, "vchan %p: kzalloc fail\n", &c->vc);
 		return NULL;
 	}
+	c->cyclic = 0;
 	ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);
 	ds->size = len;
 	ds->desc_num = num;
@@ -476,6 +497,8 @@ static struct dma_async_tx_descriptor *k3_dma_prep_slave_sg(
 	if (sgl == NULL)
 		return NULL;
 
+	c->cyclic = 0;
+
 	for_each_sg(sgl, sg, sglen, i) {
 		avail = sg_dma_len(sg);
 		if (avail > DMA_MAX_SIZE)
@@ -483,10 +506,9 @@ static struct dma_async_tx_descriptor *k3_dma_prep_slave_sg(
 	}
 
 	ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
-	if (!ds) {
-		dev_dbg(chan->device->dev, "vchan %p: kzalloc fail\n", &c->vc);
+	if (!ds)
 		return NULL;
-	}
+
 	ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);
 	ds->desc_num = num;
 	num = 0;
@@ -519,6 +541,77 @@ static struct dma_async_tx_descriptor *k3_dma_prep_slave_sg(
 	return vchan_tx_prep(&c->vc, &ds->vd, flags);
 }
 
+static struct dma_async_tx_descriptor *
+k3_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
+		       size_t buf_len, size_t period_len,
+		       enum dma_transfer_direction dir,
+		       unsigned long flags)
+{
+	struct k3_dma_chan *c = to_k3_chan(chan);
+	struct k3_dma_desc_sw *ds;
+	size_t len, avail, total = 0;
+	dma_addr_t addr, src = 0, dst = 0;
+	int num = 1, since = 0;
+	size_t modulo = DMA_CYCLIC_MAX_PERIOD;
+	u32 en_tc2 = 0;
+
+	dev_dbg(chan->device->dev, "%s: buf %p, dst %p, buf len %d, period_len = %d, dir %d\n",
+	       __func__, (void *)buf_addr, (void *)to_k3_chan(chan)->dev_addr,
+	       (int)buf_len, (int)period_len, (int)dir);
+
+	avail = buf_len;
+	if (avail > modulo)
+		num += DIV_ROUND_UP(avail, modulo) - 1;
+
+	ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
+	if (!ds)
+		return NULL;
+
+	ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);
+	ds->desc_num = num;
+
+	c->cyclic = 1;
+	addr = buf_addr;
+	avail = buf_len;
+	total = avail;
+	num = 0;
+
+	if (period_len < modulo)
+		modulo = period_len;
+
+	do {
+		len = min_t(size_t, avail, modulo);
+
+		if (dir == DMA_MEM_TO_DEV) {
+			src = addr;
+			dst = c->dev_addr;
+		} else if (dir == DMA_DEV_TO_MEM) {
+			src = c->dev_addr;
+			dst = addr;
+		}
+		since += len;
+		if (since >= period_len) {
+			/* descriptor asks for TC2 interrupt on completion */
+			en_tc2 = CX_CFG_NODEIRQ;
+			since -= period_len;
+		} else
+			en_tc2 = 0;
+
+		k3_dma_fill_desc(ds, dst, src, len, num++, c->ccfg | en_tc2);
+
+		addr += len;
+		avail -= len;
+	} while (avail);
+
+	/* "Cyclic" == end of link points back to start of link */
+	ds->desc_hw[num - 1].lli |= ds->desc_hw_lli;
+
+	ds->size = total;
+
+	return vchan_tx_prep(&c->vc, &ds->vd, flags);
+}
+
+
 static int k3_dma_config(struct dma_chan *chan,
 			 struct dma_slave_config *cfg)
 {
@@ -723,11 +816,13 @@ static int k3_dma_probe(struct platform_device *op)
 	INIT_LIST_HEAD(&d->slave.channels);
 	dma_cap_set(DMA_SLAVE, d->slave.cap_mask);
 	dma_cap_set(DMA_MEMCPY, d->slave.cap_mask);
+	dma_cap_set(DMA_CYCLIC, d->slave.cap_mask);
 	d->slave.dev = &op->dev;
 	d->slave.device_free_chan_resources = k3_dma_free_chan_resources;
 	d->slave.device_tx_status = k3_dma_tx_status;
 	d->slave.device_prep_dma_memcpy = k3_dma_prep_memcpy;
 	d->slave.device_prep_slave_sg = k3_dma_prep_slave_sg;
+	d->slave.device_prep_dma_cyclic = k3_dma_prep_dma_cyclic;
 	d->slave.device_issue_pending = k3_dma_issue_pending;
 	d->slave.device_config = k3_dma_config;
 	d->slave.device_pause = k3_dma_transfer_pause;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 5/7] k3dma: Fix memory handling with cyclic mode
  2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
                   ` (3 preceding siblings ...)
  2016-07-21  3:53 ` [PATCH 4/7] k3dma: Add cyclic mode for audio John Stultz
@ 2016-07-21  3:53 ` John Stultz
  2016-07-21  3:53 ` [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api John Stultz
  2016-07-21  3:53 ` [PATCH 7/7] Kconfig: Allow k3dma driver to be selected for more then HISI3xx platforms John Stultz
  6 siblings, 0 replies; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Mark Brown, Andy Green

With cyclic mode, the shared virt-dma logic doesn't actually
manage the descriptor state, nor the calling of the descriptor
free callback. This results in leaking a desc structure every
time we start an audio transfer.

Thus we must manage it ourselves. The k3dma driver already keeps
track of the active and finished descriptors via ds_run and ds_done
pointers, so when we tear down everything in terminate_all, call
free_desc on the ds_run and ds_done pointers if they are not null.

NOTE: HiKey doesn't use the non-cyclic dma modes, so I'm not been
able to test those modes. But with this patch we no longer leak
the desc structures.

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Andy Green <andy@warmcat.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/dma/k3dma.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index 8e4c845..950ed36 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -219,6 +219,7 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
 				spin_lock_irqsave(&c->vc.lock, flags);
 				vchan_cookie_complete(&p->ds_run->vd);
 				p->ds_done = p->ds_run;
+				p->ds_run = NULL;
 				spin_unlock_irqrestore(&c->vc.lock, flags);
 			}
 			if (c && (tc2 & BIT(i))) {
@@ -266,14 +267,14 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
 		 * so vc->desc_issued only contains desc pending
 		 */
 		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_done = NULL;
-	c->phy->ds_run = NULL;
 	return -EAGAIN;
 }
 
@@ -659,6 +660,15 @@ static int k3_dma_config(struct dma_chan *chan,
 	return 0;
 }
 
+static void k3_dma_free_desc(struct virt_dma_desc *vd)
+{
+	struct k3_dma_desc_sw *ds =
+		container_of(vd, struct k3_dma_desc_sw, vd);
+
+	kfree(ds);
+}
+
+
 static int k3_dma_terminate_all(struct dma_chan *chan)
 {
 	struct k3_dma_chan *c = to_k3_chan(chan);
@@ -682,7 +692,15 @@ static int k3_dma_terminate_all(struct dma_chan *chan)
 		k3_dma_terminate_chan(p, d);
 		c->phy = NULL;
 		p->vchan = NULL;
-		p->ds_run = p->ds_done = NULL;
+		if (p->ds_run) {
+			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;
+		}
+
 	}
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 	vchan_dma_desc_free_list(&c->vc, &head);
@@ -735,14 +753,6 @@ static int k3_dma_transfer_resume(struct dma_chan *chan)
 	return 0;
 }
 
-static void k3_dma_free_desc(struct virt_dma_desc *vd)
-{
-	struct k3_dma_desc_sw *ds =
-		container_of(vd, struct k3_dma_desc_sw, vd);
-
-	kfree(ds);
-}
-
 static const struct of_device_id k3_pdma_dt_ids[] = {
 	{ .compatible = "hisilicon,k3-dma-1.0", },
 	{}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
                   ` (4 preceding siblings ...)
  2016-07-21  3:53 ` [PATCH 5/7] k3dma: Fix memory handling with cyclic mode John Stultz
@ 2016-07-21  3:53 ` John Stultz
  2016-07-21  4:26   ` zhangfei
  2016-07-21  3:53 ` [PATCH 7/7] Kconfig: Allow k3dma driver to be selected for more then HISI3xx platforms John Stultz
  6 siblings, 1 reply; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Mark Brown, Andy Green

After lots of debugging on an occasional DMA ERR issue, I realized
that the desc structures which we point the dma hardware are being
allocated out of regular memory. This means when we fill the desc
structures, that data doesn't always get flushed out to memory by
the time we start the dma transfer, resulting in the dma engine getting
some null values, resulting in a DMA ERR on the first irq.

Thus, this patch adopts mechanism similar to the zx296702_dma of
allocating the desc structures from a dma pool, so the memory caching
rules are properly set to avoid this issue.

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Andy Green <andy@warmcat.com>
Signed-off-by: John Stutlz <john.stultz@linaro.org>
---
 drivers/dma/k3dma.c | 58 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 46 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index 950ed36..259bd3b 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -8,6 +8,8 @@
  */
 #include <linux/sched.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -26,6 +28,7 @@
 #define DRIVER_NAME		"k3-dma"
 #define DMA_MAX_SIZE		0x1ffc
 #define DMA_CYCLIC_MAX_PERIOD	0x1000
+#define LLI_BLOCK_SIZE		(4 * PAGE_SIZE)
 
 #define INT_STAT		0x00
 #define INT_TC1			0x04
@@ -74,7 +77,7 @@ struct k3_dma_desc_sw {
 	dma_addr_t		desc_hw_lli;
 	size_t			desc_num;
 	size_t			size;
-	struct k3_desc_hw	desc_hw[0];
+	struct k3_desc_hw	*desc_hw;
 };
 
 struct k3_dma_phy;
@@ -107,6 +110,7 @@ struct k3_dma_dev {
 	struct k3_dma_phy	*phy;
 	struct k3_dma_chan	*chans;
 	struct clk		*clk;
+	struct dma_pool		*pool;
 	u32			dma_channels;
 	u32			dma_requests;
 };
@@ -434,6 +438,35 @@ static void k3_dma_fill_desc(struct k3_dma_desc_sw *ds, dma_addr_t dst,
 	ds->desc_hw[num].config = ccfg;
 }
 
+static struct k3_dma_desc_sw *k3_dma_alloc_desc_resource(int num,
+							struct dma_chan *chan)
+{
+	struct k3_dma_chan *c = to_k3_chan(chan);
+	struct k3_dma_desc_sw *ds;
+	struct k3_dma_dev *d = to_k3_dma(chan->device);
+	int lli_limit = LLI_BLOCK_SIZE / sizeof(struct k3_desc_hw);
+
+	if (num > lli_limit) {
+		dev_dbg(chan->device->dev, "vch %p: sg num %d exceed max %d\n",
+			&c->vc, num, lli_limit);
+		return NULL;
+	}
+
+	ds = kzalloc(sizeof(*ds), GFP_ATOMIC);
+	if (!ds)
+		return NULL;
+
+	ds->desc_hw = dma_pool_alloc(d->pool, GFP_NOWAIT, &ds->desc_hw_lli);
+	if (!ds->desc_hw) {
+		dev_dbg(chan->device->dev, "vch %p: dma alloc fail\n", &c->vc);
+		kfree(ds);
+		return NULL;
+	}
+	memset(ds->desc_hw, 0, sizeof(struct k3_desc_hw) * num);
+	ds->desc_num = num;
+	return ds;
+}
+
 static struct dma_async_tx_descriptor *k3_dma_prep_memcpy(
 	struct dma_chan *chan,	dma_addr_t dst, dma_addr_t src,
 	size_t len, unsigned long flags)
@@ -447,15 +480,14 @@ static struct dma_async_tx_descriptor *k3_dma_prep_memcpy(
 		return NULL;
 
 	num = DIV_ROUND_UP(len, DMA_MAX_SIZE);
-	ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
+
+	ds = k3_dma_alloc_desc_resource(num, chan);
 	if (!ds) {
 		dev_dbg(chan->device->dev, "vchan %p: kzalloc fail\n", &c->vc);
 		return NULL;
 	}
 	c->cyclic = 0;
-	ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);
 	ds->size = len;
-	ds->desc_num = num;
 	num = 0;
 
 	if (!c->ccfg) {
@@ -506,12 +538,9 @@ static struct dma_async_tx_descriptor *k3_dma_prep_slave_sg(
 			num += DIV_ROUND_UP(avail, DMA_MAX_SIZE) - 1;
 	}
 
-	ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
+	ds = k3_dma_alloc_desc_resource(num, chan);
 	if (!ds)
 		return NULL;
-
-	ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);
-	ds->desc_num = num;
 	num = 0;
 
 	for_each_sg(sgl, sg, sglen, i) {
@@ -564,13 +593,10 @@ k3_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
 	if (avail > modulo)
 		num += DIV_ROUND_UP(avail, modulo) - 1;
 
-	ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
+	ds = k3_dma_alloc_desc_resource(num, chan);
 	if (!ds)
 		return NULL;
 
-	ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);
-	ds->desc_num = num;
-
 	c->cyclic = 1;
 	addr = buf_addr;
 	avail = buf_len;
@@ -664,7 +690,9 @@ static void k3_dma_free_desc(struct virt_dma_desc *vd)
 {
 	struct k3_dma_desc_sw *ds =
 		container_of(vd, struct k3_dma_desc_sw, vd);
+	struct k3_dma_dev *d = to_k3_dma(vd->tx.chan->device);
 
+	dma_pool_free(d->pool, ds->desc_hw, ds->desc_hw_lli);
 	kfree(ds);
 }
 
@@ -810,6 +838,12 @@ static int k3_dma_probe(struct platform_device *op)
 	if (ret)
 		return ret;
 
+	/* A DMA memory pool for LLIs, align on 32-byte boundary */
+	d->pool = dmam_pool_create(DRIVER_NAME, &op->dev,
+					LLI_BLOCK_SIZE, 32, 0);
+	if (!d->pool)
+		return -ENOMEM;
+
 	/* init phy channel */
 	d->phy = devm_kzalloc(&op->dev,
 		d->dma_channels * sizeof(struct k3_dma_phy), GFP_KERNEL);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 7/7] Kconfig: Allow k3dma driver to be selected for more then HISI3xx platforms
  2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
                   ` (5 preceding siblings ...)
  2016-07-21  3:53 ` [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api John Stultz
@ 2016-07-21  3:53 ` John Stultz
  2016-07-22  6:56   ` kbuild test robot
  6 siblings, 1 reply; 24+ messages in thread
From: John Stultz @ 2016-07-21  3:53 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams, Liam Girdwood,
	Mark Brown, Jaroslav Kysela, Takashi Iwai, Wei Xu, Rob Herring,
	Andy Green

This allows the k3dma driver to be selected on HiKey via the ARCH_HISI
dependency.

Cc: Zhangfei Gao <zhangfei.gao@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Cc: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Vinod Koul <vinod.koul@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Andy Green <andy@warmcat.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
v2:
* Use ARCH_HISI and COMPILE_TEST dependency, suggested by Mark Brown,
  instead of just removing all dependencies.
---
 drivers/dma/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8c98779..838b932 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -279,7 +279,7 @@ config INTEL_MIC_X100_DMA
 
 config K3_DMA
 	tristate "Hisilicon K3 DMA support"
-	depends on ARCH_HI3xxx
+	depends on ARCH_HI3xxx || ARCH_HISI || COMPILE_TEST
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	help
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21  3:53 ` [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api John Stultz
@ 2016-07-21  4:26   ` zhangfei
  2016-07-21  5:22     ` John Stultz
  0 siblings, 1 reply; 24+ messages in thread
From: zhangfei @ 2016-07-21  4:26 UTC (permalink / raw)
  To: John Stultz, lkml
  Cc: Jingoo Han, Krzysztof Kozlowski, Maxime Ripard, Vinod Koul,
	Dan Williams, Mark Brown, Andy Green



On 07/21/2016 11:53 AM, John Stultz wrote:
> After lots of debugging on an occasional DMA ERR issue, I realized
> that the desc structures which we point the dma hardware are being
> allocated out of regular memory. This means when we fill the desc
> structures, that data doesn't always get flushed out to memory by
> the time we start the dma transfer, resulting in the dma engine getting
> some null values, resulting in a DMA ERR on the first irq.

How about using wmb() flush before start dma to sync desc?

I remember I used dma_pool first, then do some optimization referring 
Russell's driver.

Thanks

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21  4:26   ` zhangfei
@ 2016-07-21  5:22     ` John Stultz
  2016-07-21  6:27       ` Andy Green
  2016-07-21 16:08       ` zhangfei
  0 siblings, 2 replies; 24+ messages in thread
From: John Stultz @ 2016-07-21  5:22 UTC (permalink / raw)
  To: zhangfei
  Cc: lkml, Jingoo Han, Krzysztof Kozlowski, Maxime Ripard, Vinod Koul,
	Dan Williams, Mark Brown, Andy Green

On Wed, Jul 20, 2016 at 9:26 PM, zhangfei <zhangfei.gao@linaro.org> wrote:
>
>
> On 07/21/2016 11:53 AM, John Stultz wrote:
>>
>> After lots of debugging on an occasional DMA ERR issue, I realized
>> that the desc structures which we point the dma hardware are being
>> allocated out of regular memory. This means when we fill the desc
>> structures, that data doesn't always get flushed out to memory by
>> the time we start the dma transfer, resulting in the dma engine getting
>> some null values, resulting in a DMA ERR on the first irq.
>
>
> How about using wmb() flush before start dma to sync desc?

So I'm not going to pretend to be an expert here, but my understanding
is that wmb() syncrhonizes cpu write ordering operations across cpus,
so the cpus see all the changes before the wmb() before they see any
changes after.  But I'm not sure what effect wmb() has across cpu
cache to device ordering.   I don't think it works as a cache flush to
memory.

Andy's patch introducing the cyclic support actually had a wmb() in it
that I removed as I couldn't understand clearly why it was there (and
there wasn't a comment explaining, as required by checkpatch :).   But
even with that wmb(), the DMA ERR was still seen.

Only with these two new changes have I gotten to the point where I
can't seem to trigger the DMA error.

thanks
-john

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21  5:22     ` John Stultz
@ 2016-07-21  6:27       ` Andy Green
  2016-07-21 10:40         ` Mark Brown
  2016-07-21 16:18         ` John Stultz
  2016-07-21 16:08       ` zhangfei
  1 sibling, 2 replies; 24+ messages in thread
From: Andy Green @ 2016-07-21  6:27 UTC (permalink / raw)
  To: John Stultz, zhangfei
  Cc: lkml, Jingoo Han, Krzysztof Kozlowski, Maxime Ripard, Vinod Koul,
	Dan Williams, Mark Brown



On July 21, 2016 1:22:02 PM GMT+08:00, John Stultz <john.stultz@linaro.org> wrote:
>On Wed, Jul 20, 2016 at 9:26 PM, zhangfei <zhangfei.gao@linaro.org>
>wrote:
>>
>>
>> On 07/21/2016 11:53 AM, John Stultz wrote:
>>>
>>> After lots of debugging on an occasional DMA ERR issue, I realized
>>> that the desc structures which we point the dma hardware are being
>>> allocated out of regular memory. This means when we fill the desc
>>> structures, that data doesn't always get flushed out to memory by
>>> the time we start the dma transfer, resulting in the dma engine
>getting
>>> some null values, resulting in a DMA ERR on the first irq.
>>
>>
>> How about using wmb() flush before start dma to sync desc?
>
>So I'm not going to pretend to be an expert here, but my understanding
>is that wmb() syncrhonizes cpu write ordering operations across cpus,

IIUI what the memory barrier does is tell the *compiler* to actually do any writes that the code asked for, but which otherwise might actually be deferred past that point.  The compiler doesn't know that buffer area has other hardware snooping it, so by default it feels it can play tricks with what seems to it like just generally deferring spilling registers to memory.  wmb makes sure the compiler's pending writes actually happen right there.  (writel() etc definitions have one built-in, so they always do what you asked when you asked).

That can be of interest when syncing with other cores but also to other IPs that intend to use the written-to area immediately, which is what's happening here.  Without the barrier the write may not be issued anywhere, even to local cpu cache, until after the hw is asked to go read the buffer, corrupting what the hw sees.

>so the cpus see all the changes before the wmb() before they see any
>changes after.  But I'm not sure what effect wmb() has across cpu
>cache to device ordering.   I don't think it works as a cache flush to
>memory.
>
>Andy's patch introducing the cyclic support actually had a wmb() in it
>that I removed as I couldn't understand clearly why it was there (and
>there wasn't a comment explaining, as required by checkpatch :).   But
>even with that wmb(), the DMA ERR was still seen.

The rule about the comment is there partially because there's a general tendancy for throwing voodoo smbs on broken things in case it helps.  But writing out memory descriptors that other hw is going to read is a legit use for it I think.  If the compiler you use wasn't deferring the write, you won't notice any difference removing it, but that doesn't mean it shouldn't be there.

>Only with these two new changes have I gotten to the point where I
>can't seem to trigger the DMA error.

Sounds good...

-Andy

>thanks
>-john

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21  6:27       ` Andy Green
@ 2016-07-21 10:40         ` Mark Brown
  2016-07-21 13:12           ` Andy Green
  2016-07-21 16:18         ` John Stultz
  1 sibling, 1 reply; 24+ messages in thread
From: Mark Brown @ 2016-07-21 10:40 UTC (permalink / raw)
  To: Andy Green
  Cc: John Stultz, zhangfei, lkml, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams

[-- Attachment #1: Type: text/plain, Size: 1400 bytes --]

On Thu, Jul 21, 2016 at 02:27:02PM +0800, Andy Green wrote:
> On July 21, 2016 1:22:02 PM GMT+08:00, John Stultz <john.stultz@linaro.org> wrote:
> >On Wed, Jul 20, 2016 at 9:26 PM, zhangfei <zhangfei.gao@linaro.org>

Please fix your mail client to word wrap within paragraphs at something
substantially less than 80 columns.  Doing this makes your messages much
easier to read and reply to.

> >> How about using wmb() flush before start dma to sync desc?

> >So I'm not going to pretend to be an expert here, but my understanding
> >is that wmb() syncrhonizes cpu write ordering operations across cpus,

> IIUI what the memory barrier does is tell the *compiler* to actually
> do any writes that the code asked for, but which otherwise might
> actually be deferred past that point.  The compiler doesn't know that
> buffer area has other hardware snooping it, so by default it feels it
> can play tricks with what seems to it like just generally deferring
> spilling registers to memory.  wmb makes sure the compiler's pending
> writes actually happen right there.  (writel() etc definitions have
> one built-in, so they always do what you asked when you asked).

You might be interested in Mark Rutland's talk from ELC (Stale data, or
how we (mis-)manage modern caches):

    http://events.linuxfoundation.org/sites/events/files/slides/slides_17.pdf
    https://www.youtube.com/watch?v=F0SlIMHRnLk

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21 10:40         ` Mark Brown
@ 2016-07-21 13:12           ` Andy Green
  0 siblings, 0 replies; 24+ messages in thread
From: Andy Green @ 2016-07-21 13:12 UTC (permalink / raw)
  To: Mark Brown
  Cc: John Stultz, zhangfei, lkml, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Vinod Koul, Dan Williams

On Thu, 2016-07-21 at 11:40 +0100, Mark Brown wrote:
> On Thu, Jul 21, 2016 at 02:27:02PM +0800, Andy Green wrote:
> > 
> > On July 21, 2016 1:22:02 PM GMT+08:00, John Stultz <john.stultz@lin
> > aro.org> wrote:
> > > 
> > > On Wed, Jul 20, 2016 at 9:26 PM, zhangfei <zhangfei.gao@linaro.or
> > > g>
> 
> Please fix your mail client to word wrap within paragraphs at
> something
> substantially less than 80 columns.  Doing this makes your messages
> much
> easier to read and reply to.
> 
> > 
> > > 
> > > > 
> > > > How about using wmb() flush before start dma to sync desc?
> 
> > 
> > > 
> > > So I'm not going to pretend to be an expert here, but my
> > > understanding
> > > is that wmb() syncrhonizes cpu write ordering operations across
> > > cpus,
> 
> > 
> > IIUI what the memory barrier does is tell the *compiler* to
> > actually
> > do any writes that the code asked for, but which otherwise might
> > actually be deferred past that point.  The compiler doesn't know
> > that
> > buffer area has other hardware snooping it, so by default it feels
> > it
> > can play tricks with what seems to it like just generally deferring
> > spilling registers to memory.  wmb makes sure the compiler's
> > pending
> > writes actually happen right there.  (writel() etc definitions have
> > one built-in, so they always do what you asked when you asked).
> 
> You might be interested in Mark Rutland's talk from ELC (Stale data,
> or
> how we (mis-)manage modern caches):
> 
>     http://events.linuxfoundation.org/sites/events/files/slides/slide
> s_17.pdf

Thanks for the pointer.

That is a somewhat different animal to wmb though: wmb is about
managing when the initiator of the write actualizes it, prior to that
the write does not instantenously exist anywhere and so is not subject
to these coherency nightmares [1].

Also the presentation is from the hw POV only, at the Linux driver
level most of the considerations can be made moot if you just use the
generic Linux DMA or related apis, which thanks to the work of the Arm
Linux gods already knows how to deal with / wrap the issues, plus or
minus.  So it's not as dire as it sounds.

-Andy

[1] The details of some of those nightmares are unfortunately very
familiar to me, since I spent many months where Linux was being blamed
for Mali breakage via CCI on a platform that ultimately had its
problems resolved by tweaks in its secure world...

>     https://www.youtube.com/watch?v=F0SlIMHRnLk

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21  5:22     ` John Stultz
  2016-07-21  6:27       ` Andy Green
@ 2016-07-21 16:08       ` zhangfei
  1 sibling, 0 replies; 24+ messages in thread
From: zhangfei @ 2016-07-21 16:08 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Jingoo Han, Krzysztof Kozlowski, Maxime Ripard, Vinod Koul,
	Dan Williams, Mark Brown, Andy Green



On 07/21/2016 01:22 PM, John Stultz wrote:
> On Wed, Jul 20, 2016 at 9:26 PM, zhangfei <zhangfei.gao@linaro.org> wrote:
>>
>>
>> On 07/21/2016 11:53 AM, John Stultz wrote:
>>>
>>> After lots of debugging on an occasional DMA ERR issue, I realized
>>> that the desc structures which we point the dma hardware are being
>>> allocated out of regular memory. This means when we fill the desc
>>> structures, that data doesn't always get flushed out to memory by
>>> the time we start the dma transfer, resulting in the dma engine getting
>>> some null values, resulting in a DMA ERR on the first irq.
>>
>>
>> How about using wmb() flush before start dma to sync desc?
>
> So I'm not going to pretend to be an expert here, but my understanding
> is that wmb() syncrhonizes cpu write ordering operations across cpus,
> so the cpus see all the changes before the wmb() before they see any
> changes after.  But I'm not sure what effect wmb() has across cpu
> cache to device ordering.   I don't think it works as a cache flush to
> memory.
>
> Andy's patch introducing the cyclic support actually had a wmb() in it
> that I removed as I couldn't understand clearly why it was there (and
> there wasn't a comment explaining, as required by checkpatch :).   But
> even with that wmb(), the DMA ERR was still seen.
>
> Only with these two new changes have I gotten to the point where I
> can't seem to trigger the DMA error.
>

Yes, you are right.
Have double checked, we have to use non-cached memory here as dma 
descriptor, instead of cached memory from kzalloc.

And barrier (wmb or writel) is used to ensure descriptor are written 
before start dma.
Though we start dma much later in issue_pending -> tasklet, so the 
chance is low.

Thanks

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21  6:27       ` Andy Green
  2016-07-21 10:40         ` Mark Brown
@ 2016-07-21 16:18         ` John Stultz
  2016-07-21 19:57           ` Andy Green
  1 sibling, 1 reply; 24+ messages in thread
From: John Stultz @ 2016-07-21 16:18 UTC (permalink / raw)
  To: Andy Green
  Cc: zhangfei, lkml, Jingoo Han, Krzysztof Kozlowski, Maxime Ripard,
	Vinod Koul, Dan Williams, Mark Brown

On Wed, Jul 20, 2016 at 11:27 PM, Andy Green <andy@warmcat.com> wrote:
> On July 21, 2016 1:22:02 PM GMT+08:00, John Stultz <john.stultz@linaro.org> wrote:
>>On Wed, Jul 20, 2016 at 9:26 PM, zhangfei <zhangfei.gao@linaro.org>
>>wrote:
>>>
>>>
>>> On 07/21/2016 11:53 AM, John Stultz wrote:
>>>>
>>>> After lots of debugging on an occasional DMA ERR issue, I realized
>>>> that the desc structures which we point the dma hardware are being
>>>> allocated out of regular memory. This means when we fill the desc
>>>> structures, that data doesn't always get flushed out to memory by
>>>> the time we start the dma transfer, resulting in the dma engine
>>getting
>>>> some null values, resulting in a DMA ERR on the first irq.
>>>
>>>
>>> How about using wmb() flush before start dma to sync desc?
>>
>>So I'm not going to pretend to be an expert here, but my understanding
>>is that wmb() syncrhonizes cpu write ordering operations across cpus,
>
> IIUI what the memory barrier does is tell the *compiler* to actually do any writes that the code asked for, but which otherwise might actually be deferred past that point.  The compiler doesn't know that buffer area has other hardware snooping it, so by default it feels it can play tricks with what seems to it like just generally deferring spilling registers to memory.  wmb makes sure the compiler's pending writes actually happen right there.  (writel() etc definitions have one built-in, so they always do what you asked when you asked).
>
> That can be of interest when syncing with other cores but also to other IPs that intend to use the written-to area immediately, which is what's happening here.  Without the barrier the write may not be issued anywhere, even to local cpu cache, until after the hw is asked to go read the buffer, corrupting what the hw sees.
>
>>so the cpus see all the changes before the wmb() before they see any
>>changes after.  But I'm not sure what effect wmb() has across cpu
>>cache to device ordering.   I don't think it works as a cache flush to
>>memory.
>>
>>Andy's patch introducing the cyclic support actually had a wmb() in it
>>that I removed as I couldn't understand clearly why it was there (and
>>there wasn't a comment explaining, as required by checkpatch :).   But
>>even with that wmb(), the DMA ERR was still seen.
>
> The rule about the comment is there partially because there's a general tendancy for throwing voodoo smbs on broken things in case it helps.  But writing out memory descriptors that other hw is going to read is a legit use for it I think.  If the compiler you use wasn't deferring the write, you won't notice any difference removing it, but that doesn't mean it shouldn't be there.
>

Though from your comments above, wouldn't using writel() instead of
writel_relaxed(), followed by a wmb() be sufficient?

thanks
-john

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
  2016-07-21 16:18         ` John Stultz
@ 2016-07-21 19:57           ` Andy Green
  0 siblings, 0 replies; 24+ messages in thread
From: Andy Green @ 2016-07-21 19:57 UTC (permalink / raw)
  To: John Stultz
  Cc: zhangfei, lkml, Jingoo Han, Krzysztof Kozlowski, Maxime Ripard,
	Vinod Koul, Dan Williams, Mark Brown



On July 22, 2016 12:18:48 AM GMT+08:00, John Stultz <john.stultz@linaro.org> wrote:
>On Wed, Jul 20, 2016 at 11:27 PM, Andy Green <andy@warmcat.com> wrote:
>> On July 21, 2016 1:22:02 PM GMT+08:00, John Stultz
><john.stultz@linaro.org> wrote:
>>>On Wed, Jul 20, 2016 at 9:26 PM, zhangfei <zhangfei.gao@linaro.org>
>>>wrote:
>>>>
>>>>
>>>> On 07/21/2016 11:53 AM, John Stultz wrote:
>>>>>
>>>>> After lots of debugging on an occasional DMA ERR issue, I realized
>>>>> that the desc structures which we point the dma hardware are being
>>>>> allocated out of regular memory. This means when we fill the desc
>>>>> structures, that data doesn't always get flushed out to memory by
>>>>> the time we start the dma transfer, resulting in the dma engine
>>>getting
>>>>> some null values, resulting in a DMA ERR on the first irq.
>>>>
>>>>
>>>> How about using wmb() flush before start dma to sync desc?
>>>
>>>So I'm not going to pretend to be an expert here, but my
>understanding
>>>is that wmb() syncrhonizes cpu write ordering operations across cpus,
>>
>> IIUI what the memory barrier does is tell the *compiler* to actually
>do any writes that the code asked for, but which otherwise might
>actually be deferred past that point.  The compiler doesn't know that
>buffer area has other hardware snooping it, so by default it feels it
>can play tricks with what seems to it like just generally deferring
>spilling registers to memory.  wmb makes sure the compiler's pending
>writes actually happen right there.  (writel() etc definitions have one
>built-in, so they always do what you asked when you asked).
>>
>> That can be of interest when syncing with other cores but also to
>other IPs that intend to use the written-to area immediately, which is
>what's happening here.  Without the barrier the write may not be issued
>anywhere, even to local cpu cache, until after the hw is asked to go
>read the buffer, corrupting what the hw sees.
>>
>>>so the cpus see all the changes before the wmb() before they see any
>>>changes after.  But I'm not sure what effect wmb() has across cpu
>>>cache to device ordering.   I don't think it works as a cache flush
>to
>>>memory.
>>>
>>>Andy's patch introducing the cyclic support actually had a wmb() in
>it
>>>that I removed as I couldn't understand clearly why it was there (and
>>>there wasn't a comment explaining, as required by checkpatch :).  
>But
>>>even with that wmb(), the DMA ERR was still seen.
>>
>> The rule about the comment is there partially because there's a
>general tendancy for throwing voodoo smbs on broken things in case it
>helps.  But writing out memory descriptors that other hw is going to
>read is a legit use for it I think.  If the compiler you use wasn't
>deferring the write, you won't notice any difference removing it, but
>that doesn't mean it shouldn't be there.
>>
>
>Though from your comments above, wouldn't using writel() instead of
>writel_relaxed(), followed by a wmb() be sufficient?

Yes, since on Arm writel() sticks a wmb (ultimately a dsb instruction + outer_sync()) after every write it does. 

-Andy

>thanks
>-john

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 7/7] Kconfig: Allow k3dma driver to be selected for more then HISI3xx platforms
  2016-07-21  3:53 ` [PATCH 7/7] Kconfig: Allow k3dma driver to be selected for more then HISI3xx platforms John Stultz
@ 2016-07-22  6:56   ` kbuild test robot
  0 siblings, 0 replies; 24+ messages in thread
From: kbuild test robot @ 2016-07-22  6:56 UTC (permalink / raw)
  To: John Stultz
  Cc: kbuild-all, lkml, John Stultz, Zhangfei Gao, Jingoo Han,
	Krzysztof Kozlowski, Maxime Ripard, Vinod Koul, Dan Williams,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai, Wei Xu,
	Rob Herring, Andy Green

[-- Attachment #1: Type: text/plain, Size: 3340 bytes --]

Hi,

[auto build test WARNING on stable/master]
[also build test WARNING on v4.7-rc7]
[cannot apply to next-20160721]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/John-Stultz/K3DMA-fixes-for-HiKey-HDMI-audio/20160722-042725
base:   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git master
config: sparc64-allmodconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 5.4.0-6) 5.4.0 20160609
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sparc64 

All warnings (new ones prefixed by >>):

   In file included from include/linux/printk.h:289:0,
                    from include/linux/kernel.h:13,
                    from include/linux/sched.h:17,
                    from drivers/dma/k3dma.c:9:
   drivers/dma/k3dma.c: In function 'k3_dma_prep_dma_cyclic':
>> drivers/dma/k3dma.c:589:19: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
            __func__, (void *)buf_addr, (void *)to_k3_chan(chan)->dev_addr,
                      ^
   include/linux/dynamic_debug.h:87:9: note: in definition of macro 'dynamic_dev_dbg'
          ##__VA_ARGS__);  \
            ^
>> drivers/dma/k3dma.c:588:2: note: in expansion of macro 'dev_dbg'
     dev_dbg(chan->device->dev, "%s: buf %p, dst %p, buf len %d, period_len = %d, dir %d\n",
     ^
   drivers/dma/k3dma.c:589:37: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
            __func__, (void *)buf_addr, (void *)to_k3_chan(chan)->dev_addr,
                                        ^
   include/linux/dynamic_debug.h:87:9: note: in definition of macro 'dynamic_dev_dbg'
          ##__VA_ARGS__);  \
            ^
>> drivers/dma/k3dma.c:588:2: note: in expansion of macro 'dev_dbg'
     dev_dbg(chan->device->dev, "%s: buf %p, dst %p, buf len %d, period_len = %d, dir %d\n",
     ^

vim +589 drivers/dma/k3dma.c

286eb549 Andy Green 2016-07-20  582  	size_t len, avail, total = 0;
286eb549 Andy Green 2016-07-20  583  	dma_addr_t addr, src = 0, dst = 0;
286eb549 Andy Green 2016-07-20  584  	int num = 1, since = 0;
286eb549 Andy Green 2016-07-20  585  	size_t modulo = DMA_CYCLIC_MAX_PERIOD;
286eb549 Andy Green 2016-07-20  586  	u32 en_tc2 = 0;
286eb549 Andy Green 2016-07-20  587  
286eb549 Andy Green 2016-07-20 @588  	dev_dbg(chan->device->dev, "%s: buf %p, dst %p, buf len %d, period_len = %d, dir %d\n",
286eb549 Andy Green 2016-07-20 @589  	       __func__, (void *)buf_addr, (void *)to_k3_chan(chan)->dev_addr,
286eb549 Andy Green 2016-07-20  590  	       (int)buf_len, (int)period_len, (int)dir);
286eb549 Andy Green 2016-07-20  591  
286eb549 Andy Green 2016-07-20  592  	avail = buf_len;

:::::: The code at line 589 was first introduced by commit
:::::: 286eb549d997ae9e214f367d2a1269c9f42ab515 k3dma: Add cyclic mode for audio

:::::: TO: Andy Green <andy.green@linaro.org>
:::::: CC: 0day robot <fengguang.wu@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 46358 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/7] k3dma: Fix hisi burst clipping
  2016-07-21  3:53 ` [PATCH 1/7] k3dma: Fix hisi burst clipping John Stultz
@ 2016-07-24  7:25   ` Vinod Koul
  2016-07-29 22:40     ` John Stultz
  0 siblings, 1 reply; 24+ messages in thread
From: Vinod Koul @ 2016-07-24  7:25 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Dan Williams, Mark Brown, Andy Green

On Wed, Jul 20, 2016 at 08:53:03PM -0700, John Stultz wrote:
> From: Andy Green <andy.green@linaro.org>
> 
> Max burst len is a 4-bit field, but at the moment it's clipped with
> a 5-bit constant... reduce it to that which can be expressed

Maybe we should GENMASK() etc to avoid these errors..

>  	if ((maxburst == 0) || (maxburst > 16))
> -		val = 16;
> +		val = 15;

-- 
~Vinod

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 4/7] k3dma: Add cyclic mode for audio
  2016-07-21  3:53 ` [PATCH 4/7] k3dma: Add cyclic mode for audio John Stultz
@ 2016-07-24  7:31   ` Vinod Koul
  2016-07-29 22:38     ` John Stultz
  0 siblings, 1 reply; 24+ messages in thread
From: Vinod Koul @ 2016-07-24  7:31 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Dan Williams, Mark Brown, Andy Green

On Wed, Jul 20, 2016 at 08:53:06PM -0700, John Stultz wrote:

>  	ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
> -	if (!ds) {
> -		dev_dbg(chan->device->dev, "vchan %p: kzalloc fail\n", &c->vc);
> +	if (!ds)

This is an unrelated change

> +
> +	ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);

we should use GFP_NOWAIT. And looks like driver doesn't use GFP_NOWAIT< so
you may fix that up as well

> +	if (!ds)
> +		return NULL;
> +
> +	ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);

why no dma_map_single(()?

Also __api is internal APIs, driver should not use them. Why not plain
virt_to_phys()

-- 
~Vinod

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 4/7] k3dma: Add cyclic mode for audio
  2016-07-24  7:31   ` Vinod Koul
@ 2016-07-29 22:38     ` John Stultz
  0 siblings, 0 replies; 24+ messages in thread
From: John Stultz @ 2016-07-29 22:38 UTC (permalink / raw)
  To: Vinod Koul
  Cc: lkml, Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Dan Williams, Mark Brown, Andy Green

On Sun, Jul 24, 2016 at 12:31 AM, Vinod Koul <vinod.koul@intel.com> wrote:
> On Wed, Jul 20, 2016 at 08:53:06PM -0700, John Stultz wrote:
>
>>       ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
>> -     if (!ds) {
>> -             dev_dbg(chan->device->dev, "vchan %p: kzalloc fail\n", &c->vc);
>> +     if (!ds)
>
> This is an unrelated change

Ack. And Its fallen out with recent changes in 4.8-rc


>> +
>> +     ds = kzalloc(sizeof(*ds) + num * sizeof(ds->desc_hw[0]), GFP_ATOMIC);
>
> we should use GFP_NOWAIT. And looks like driver doesn't use GFP_NOWAIT< so
> you may fix that up as well

Done.

>> +     if (!ds)
>> +             return NULL;
>> +
>> +     ds->desc_hw_lli = __virt_to_phys((unsigned long)&ds->desc_hw[0]);
>
> why no dma_map_single(()?
>
> Also __api is internal APIs, driver should not use them. Why not plain
> virt_to_phys()

Right. This is reworked by one of the following patches, but I
reordered things in my tree so those fixes land before we add the
cyclic feature.

I'll resend after the merge-window is over (unless you'd like to see it sooner).

thanks
-john

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/7] k3dma: Fix hisi burst clipping
  2016-07-24  7:25   ` Vinod Koul
@ 2016-07-29 22:40     ` John Stultz
  2016-08-04 13:08       ` Vinod Koul
  0 siblings, 1 reply; 24+ messages in thread
From: John Stultz @ 2016-07-29 22:40 UTC (permalink / raw)
  To: Vinod Koul
  Cc: lkml, Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Dan Williams, Mark Brown, Andy Green

On Sun, Jul 24, 2016 at 12:25 AM, Vinod Koul <vinod.koul@intel.com> wrote:
> On Wed, Jul 20, 2016 at 08:53:03PM -0700, John Stultz wrote:
>> From: Andy Green <andy.green@linaro.org>
>>
>> Max burst len is a 4-bit field, but at the moment it's clipped with
>> a 5-bit constant... reduce it to that which can be expressed
>
> Maybe we should GENMASK() etc to avoid these errors..

Not sure I follow what you're thinking here... can you clarify a bit?

thanks
-john

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/7] k3dma: Fix hisi burst clipping
  2016-07-29 22:40     ` John Stultz
@ 2016-08-04 13:08       ` Vinod Koul
  2016-08-04 17:36         ` John Stultz
  0 siblings, 1 reply; 24+ messages in thread
From: Vinod Koul @ 2016-08-04 13:08 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Dan Williams, Mark Brown, Andy Green

On Fri, Jul 29, 2016 at 03:40:46PM -0700, John Stultz wrote:
> On Sun, Jul 24, 2016 at 12:25 AM, Vinod Koul <vinod.koul@intel.com> wrote:
> > On Wed, Jul 20, 2016 at 08:53:03PM -0700, John Stultz wrote:
> >> From: Andy Green <andy.green@linaro.org>
> >>
> >> Max burst len is a 4-bit field, but at the moment it's clipped with
> >> a 5-bit constant... reduce it to that which can be expressed
> >
> > Maybe we should GENMASK() etc to avoid these errors..
> 
> Not sure I follow what you're thinking here... can you clarify a bit?

I am assuming the 4bit field was a mistake by orignal author. Using GENMASK,
BIT etc macro helps you to avoid those as one would look at datasheet and
say this is specfied as bit 5 thru 9, so let me say GENMASK(5, 0) rather
than a typo which missed 5th bit.

But ofcourse if the error was due to some other reason then this one doesnt
help.

-- 
~Vinod

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/7] k3dma: Fix hisi burst clipping
  2016-08-04 13:08       ` Vinod Koul
@ 2016-08-04 17:36         ` John Stultz
  2016-08-05  3:36           ` Vinod Koul
  0 siblings, 1 reply; 24+ messages in thread
From: John Stultz @ 2016-08-04 17:36 UTC (permalink / raw)
  To: Vinod Koul
  Cc: lkml, Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Dan Williams, Mark Brown, Andy Green

On Thu, Aug 4, 2016 at 6:08 AM, Vinod Koul <vinod.koul@intel.com> wrote:
> On Fri, Jul 29, 2016 at 03:40:46PM -0700, John Stultz wrote:
>> On Sun, Jul 24, 2016 at 12:25 AM, Vinod Koul <vinod.koul@intel.com> wrote:
>> > On Wed, Jul 20, 2016 at 08:53:03PM -0700, John Stultz wrote:
>> >> From: Andy Green <andy.green@linaro.org>
>> >>
>> >> Max burst len is a 4-bit field, but at the moment it's clipped with
>> >> a 5-bit constant... reduce it to that which can be expressed
>> >
>> > Maybe we should GENMASK() etc to avoid these errors..
>>
>> Not sure I follow what you're thinking here... can you clarify a bit?
>
> I am assuming the 4bit field was a mistake by orignal author. Using GENMASK,
> BIT etc macro helps you to avoid those as one would look at datasheet and
> say this is specfied as bit 5 thru 9, so let me say GENMASK(5, 0) rather
> than a typo which missed 5th bit.
>
> But ofcourse if the error was due to some other reason then this one doesnt
> help.

It was more that in taking the cfg->src/dst_maxburst value and setting
it as a value that can be represented in 4 bits for the hardware:
        if ((maxburst == 0) || (maxburst > 16))
                val = 16;
        else
                val = maxburst - 1;

However, the logic error is trying to set the value to 16 if maxburst
is larger then 16, when 16 is 5 bits, when 15 is the largest value we
can express in 4 bits.

So I'm not sure how GENMASK() would be particularly useful (I guess
using val = GENMASK(4,0) instead of val = 15?). But I'm not sure that
makes the code any clearer.

thanks
-john

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/7] k3dma: Fix hisi burst clipping
  2016-08-04 17:36         ` John Stultz
@ 2016-08-05  3:36           ` Vinod Koul
  0 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2016-08-05  3:36 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Andy Green, Zhangfei Gao, Jingoo Han, Krzysztof Kozlowski,
	Maxime Ripard, Dan Williams, Mark Brown, Andy Green

On Thu, Aug 04, 2016 at 10:36:32AM -0700, John Stultz wrote:
> On Thu, Aug 4, 2016 at 6:08 AM, Vinod Koul <vinod.koul@intel.com> wrote:
> > On Fri, Jul 29, 2016 at 03:40:46PM -0700, John Stultz wrote:
> >> On Sun, Jul 24, 2016 at 12:25 AM, Vinod Koul <vinod.koul@intel.com> wrote:
> >> > On Wed, Jul 20, 2016 at 08:53:03PM -0700, John Stultz wrote:
> >> >> From: Andy Green <andy.green@linaro.org>
> >> >>
> >> >> Max burst len is a 4-bit field, but at the moment it's clipped with
> >> >> a 5-bit constant... reduce it to that which can be expressed
> >> >
> >> > Maybe we should GENMASK() etc to avoid these errors..
> >>
> >> Not sure I follow what you're thinking here... can you clarify a bit?
> >
> > I am assuming the 4bit field was a mistake by orignal author. Using GENMASK,
> > BIT etc macro helps you to avoid those as one would look at datasheet and
> > say this is specfied as bit 5 thru 9, so let me say GENMASK(5, 0) rather
> > than a typo which missed 5th bit.
> >
> > But ofcourse if the error was due to some other reason then this one doesnt
> > help.
> 
> It was more that in taking the cfg->src/dst_maxburst value and setting
> it as a value that can be represented in 4 bits for the hardware:
>         if ((maxburst == 0) || (maxburst > 16))
>                 val = 16;
>         else
>                 val = maxburst - 1;
> 
> However, the logic error is trying to set the value to 16 if maxburst
> is larger then 16, when 16 is 5 bits, when 15 is the largest value we
> can express in 4 bits.
> 
> So I'm not sure how GENMASK() would be particularly useful (I guess
> using val = GENMASK(4,0) instead of val = 15?). But I'm not sure that
> makes the code any clearer.

Looks like this was latter case, so it doesnt seem to help here

-- 
~Vinod

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2016-08-05  3:28 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-21  3:53 [PATCH 0/7 v3] K3DMA fixes for HiKey HDMI audio John Stultz
2016-07-21  3:53 ` [PATCH 1/7] k3dma: Fix hisi burst clipping John Stultz
2016-07-24  7:25   ` Vinod Koul
2016-07-29 22:40     ` John Stultz
2016-08-04 13:08       ` Vinod Koul
2016-08-04 17:36         ` John Stultz
2016-08-05  3:36           ` Vinod Koul
2016-07-21  3:53 ` [PATCH 2/7] k3dma: Fix dma err offsets John Stultz
2016-07-21  3:53 ` [PATCH 3/7] k3dma: Fix "nobody cared" message seen on any error John Stultz
2016-07-21  3:53 ` [PATCH 4/7] k3dma: Add cyclic mode for audio John Stultz
2016-07-24  7:31   ` Vinod Koul
2016-07-29 22:38     ` John Stultz
2016-07-21  3:53 ` [PATCH 5/7] k3dma: Fix memory handling with cyclic mode John Stultz
2016-07-21  3:53 ` [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api John Stultz
2016-07-21  4:26   ` zhangfei
2016-07-21  5:22     ` John Stultz
2016-07-21  6:27       ` Andy Green
2016-07-21 10:40         ` Mark Brown
2016-07-21 13:12           ` Andy Green
2016-07-21 16:18         ` John Stultz
2016-07-21 19:57           ` Andy Green
2016-07-21 16:08       ` zhangfei
2016-07-21  3:53 ` [PATCH 7/7] Kconfig: Allow k3dma driver to be selected for more then HISI3xx platforms John Stultz
2016-07-22  6:56   ` kbuild test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.