All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Stultz <john.stultz@linaro.org>
To: lkml <linux-kernel@vger.kernel.org>
Cc: John Stultz <john.stultz@linaro.org>,
	Zhangfei Gao <zhangfei.gao@linaro.org>,
	Jingoo Han <jg1.han@samsung.com>,
	Krzysztof Kozlowski <k.kozlowski@samsung.com>,
	Maxime Ripard <maxime.ripard@free-electrons.com>,
	Vinod Koul <vinod.koul@intel.com>,
	Dan Williams <dan.j.williams@intel.com>,
	Mark Brown <broonie@kernel.org>, Andy Green <andy@warmcat.com>
Subject: [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api
Date: Wed, 20 Jul 2016 20:53:08 -0700	[thread overview]
Message-ID: <1469073189-9167-7-git-send-email-john.stultz@linaro.org> (raw)
In-Reply-To: <1469073189-9167-1-git-send-email-john.stultz@linaro.org>

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

  parent reply	other threads:[~2016-07-21  3:54 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` John Stultz [this message]
2016-07-21  4:26   ` [PATCH 6/7] k3dma: Fix occasional DMA ERR issue by using proper dma api 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1469073189-9167-7-git-send-email-john.stultz@linaro.org \
    --to=john.stultz@linaro.org \
    --cc=andy@warmcat.com \
    --cc=broonie@kernel.org \
    --cc=dan.j.williams@intel.com \
    --cc=jg1.han@samsung.com \
    --cc=k.kozlowski@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maxime.ripard@free-electrons.com \
    --cc=vinod.koul@intel.com \
    --cc=zhangfei.gao@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.