2659 lines
82 KiB
Diff
2659 lines
82 KiB
Diff
From de1d7ef4900e4083d3eb61a41ef21970cd572a59 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sat, 8 Sep 2018 11:03:36 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: add support for interlace single
|
||
xfer"
|
||
|
||
This reverts commit 83623425bceb4005151379cc959e41eddd2a0937.
|
||
---
|
||
drivers/dma/pl330.c | 10 +---------
|
||
1 file changed, 1 insertion(+), 9 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index b14f5c225401..8746c24d3cd7 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1477,12 +1477,6 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||
off += _emit_FLUSHP(dry_run, &buf[off],
|
||
pxs->desc->peri);
|
||
#endif
|
||
- if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
|
||
- bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
|
||
- pxs->desc->dst_interlace_size);
|
||
- else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
|
||
- bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +
|
||
- pxs->desc->src_interlace_size);
|
||
while (bursts) {
|
||
c = bursts;
|
||
off += _loop(pl330, dry_run, &buf[off], &c, pxs);
|
||
@@ -1507,9 +1501,7 @@ static inline int _setup_xfer(struct pl330_dmac *pl330,
|
||
/* Setup Loop(s) */
|
||
off += _setup_loops(pl330, dry_run, &buf[off], pxs);
|
||
|
||
- if (pxs->desc->src_interlace_size == 0 &&
|
||
- pxs->desc->dst_interlace_size == 0 &&
|
||
- pl330->peripherals_req_type == BURST) {
|
||
+ if (pl330->peripherals_req_type == BURST) {
|
||
unsigned int ccr = pxs->ccr;
|
||
unsigned long c = 0;
|
||
|
||
|
||
From 875fb88fb64f5dc61abb8c4a311de82b68792d0e Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sat, 1 Sep 2018 07:43:58 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: _loop_cyclic: fixup loopcnt is too
|
||
large"
|
||
|
||
This reverts commit 8ea3f97aab1b68b5aa1aece7eb83bef6d08b3c84.
|
||
---
|
||
drivers/dma/pl330.c | 67 +++++++++++++++++------------------------------------
|
||
1 file changed, 21 insertions(+), 46 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 8746c24d3cd7..5893c11dd858 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1341,14 +1341,19 @@ static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
|
||
return off;
|
||
}
|
||
|
||
-static int _period(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
|
||
- unsigned long bursts, const struct _xfer_spec *pxs, int ev)
|
||
+/* Returns bytes consumed */
|
||
+static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
+ u8 buf[], unsigned long bursts, const struct _xfer_spec *pxs, int ev)
|
||
{
|
||
- unsigned int lcnt1, ljmp1;
|
||
- int cyc, off = 0;
|
||
+ int cyc, off;
|
||
+ unsigned lcnt0, lcnt1, ljmp0, ljmp1, ljmpfe;
|
||
struct _arg_LPEND lpend;
|
||
struct pl330_xfer *x = &pxs->desc->px;
|
||
|
||
+ off = 0;
|
||
+ ljmpfe = off;
|
||
+ lcnt0 = pxs->desc->num_periods;
|
||
+
|
||
if (bursts > 256) {
|
||
lcnt1 = 256;
|
||
cyc = bursts / 256;
|
||
@@ -1357,6 +1362,18 @@ static int _period(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
|
||
cyc = 1;
|
||
}
|
||
|
||
+ /* forever loop */
|
||
+ off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
|
||
+ off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
|
||
+#ifdef CONFIG_ARCH_ROCKCHIP
|
||
+ if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
+ off += _emit_FLUSHP(dry_run, &buf[off],
|
||
+ pxs->desc->peri);
|
||
+#endif
|
||
+ /* loop0 */
|
||
+ off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
|
||
+ ljmp0 = off;
|
||
+
|
||
/* loop1 */
|
||
off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
|
||
ljmp1 = off;
|
||
@@ -1407,54 +1424,12 @@ static int _period(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
|
||
|
||
off += _emit_SEV(dry_run, &buf[off], ev);
|
||
|
||
- return off;
|
||
-}
|
||
-
|
||
-/* Returns bytes consumed */
|
||
-static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned int dry_run,
|
||
- u8 buf[], unsigned long bursts, const struct _xfer_spec *pxs, int ev)
|
||
-{
|
||
- int off, periods, residue, i;
|
||
- unsigned int lcnt0, ljmp0, ljmpfe;
|
||
- struct _arg_LPEND lpend;
|
||
- struct pl330_xfer *x = &pxs->desc->px;
|
||
-
|
||
- off = 0;
|
||
- ljmpfe = off;
|
||
- lcnt0 = pxs->desc->num_periods;
|
||
- periods = 1;
|
||
-
|
||
- while (lcnt0 > 256) {
|
||
- periods++;
|
||
- lcnt0 = pxs->desc->num_periods / periods;
|
||
- }
|
||
-
|
||
- residue = pxs->desc->num_periods % periods;
|
||
-
|
||
- /* forever loop */
|
||
- off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
|
||
- off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
|
||
-#ifdef CONFIG_ARCH_ROCKCHIP
|
||
- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
- off += _emit_FLUSHP(dry_run, &buf[off],
|
||
- pxs->desc->peri);
|
||
-#endif
|
||
- /* loop0 */
|
||
- off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
|
||
- ljmp0 = off;
|
||
-
|
||
- for (i = 0; i < periods; i++)
|
||
- off += _period(pl330, dry_run, &buf[off], bursts, pxs, ev);
|
||
-
|
||
lpend.cond = ALWAYS;
|
||
lpend.forever = false;
|
||
lpend.loop = 0;
|
||
lpend.bjump = off - ljmp0;
|
||
off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
|
||
- for (i = 0; i < residue; i++)
|
||
- off += _period(pl330, dry_run, &buf[off], bursts, pxs, ev);
|
||
-
|
||
lpend.cond = ALWAYS;
|
||
lpend.forever = true;
|
||
lpend.loop = 1;
|
||
|
||
From b773c238a40773bd6f717701324630a917b67567 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sun, 3 Jun 2018 07:36:35 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: add support for interlace cyclic
|
||
xfer"
|
||
|
||
This reverts commit 191583d95bae59c82b50f7437f2b738fcc5f8015.
|
||
---
|
||
drivers/dma/pl330.c | 21 ++++++++++++---------
|
||
1 file changed, 12 insertions(+), 9 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 5893c11dd858..b4a0d48bafa4 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1398,9 +1398,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
}
|
||
|
||
- if (pxs->desc->src_interlace_size == 0 &&
|
||
- pxs->desc->dst_interlace_size == 0 &&
|
||
- pl330->peripherals_req_type == BURST) {
|
||
+ if (pl330->peripherals_req_type == BURST) {
|
||
unsigned int ccr = pxs->ccr;
|
||
unsigned long c = 0;
|
||
|
||
@@ -1501,12 +1499,6 @@ static inline int _setup_xfer_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr);
|
||
int off = 0;
|
||
|
||
- if (pxs->desc->rqtype == DMA_DEV_TO_MEM)
|
||
- bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
|
||
- + pxs->desc->dst_interlace_size);
|
||
- else if (pxs->desc->rqtype == DMA_MEM_TO_DEV)
|
||
- bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr)
|
||
- + pxs->desc->src_interlace_size);
|
||
/* Setup Loop(s) */
|
||
off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev);
|
||
|
||
@@ -2729,6 +2721,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
struct dma_pl330_desc *desc = NULL;
|
||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||
struct pl330_dmac *pl330 = pch->dmac;
|
||
+ unsigned int size = 0;
|
||
dma_addr_t dst;
|
||
dma_addr_t src;
|
||
|
||
@@ -2754,12 +2747,14 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
desc->rqcfg.dst_inc = 0;
|
||
src = dma_addr;
|
||
dst = pch->fifo_addr;
|
||
+ size = pch->src_interlace_size;
|
||
break;
|
||
case DMA_DEV_TO_MEM:
|
||
desc->rqcfg.src_inc = 0;
|
||
desc->rqcfg.dst_inc = 1;
|
||
src = pch->fifo_addr;
|
||
dst = dma_addr;
|
||
+ size = pch->dst_interlace_size;
|
||
break;
|
||
default:
|
||
break;
|
||
@@ -2779,8 +2774,16 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
desc->cyclic = true;
|
||
desc->num_periods = len / period_len;
|
||
desc->txd.flags = flags;
|
||
+
|
||
desc->src_interlace_size = pch->src_interlace_size;
|
||
desc->dst_interlace_size = pch->dst_interlace_size;
|
||
+ /* refine bytes_requested if interlace_size set */
|
||
+ if (size) {
|
||
+ size += (pch->burst_len * (1 << pch->burst_sz));
|
||
+ size *= desc->bytes_requested;
|
||
+ size /= (pch->burst_len * (1 << pch->burst_sz));
|
||
+ desc->bytes_requested = size;
|
||
+ }
|
||
return &desc->txd;
|
||
}
|
||
|
||
|
||
From b933f0eb613228472124849615f5a5e075b8b787 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sun, 3 Jun 2018 07:36:53 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: add support for interlace size
|
||
config"
|
||
|
||
This reverts commit ddd2e87ad41e2c9e95322a1fb7d8ca65e578aa65.
|
||
---
|
||
drivers/dma/pl330.c | 32 --------------------------------
|
||
include/linux/dmaengine.h | 2 --
|
||
2 files changed, 34 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index b4a0d48bafa4..babaeace0a8a 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -447,10 +447,6 @@ struct dma_pl330_chan {
|
||
int burst_len; /* the number of burst */
|
||
dma_addr_t fifo_addr;
|
||
|
||
- /* interlace size */
|
||
- unsigned int src_interlace_size;
|
||
- unsigned int dst_interlace_size;
|
||
-
|
||
/* for runtime pm tracking */
|
||
bool active;
|
||
};
|
||
@@ -540,9 +536,6 @@ struct dma_pl330_desc {
|
||
/* For cyclic capability */
|
||
bool cyclic;
|
||
size_t num_periods;
|
||
- /* interlace size */
|
||
- unsigned int src_interlace_size;
|
||
- unsigned int dst_interlace_size;
|
||
};
|
||
|
||
struct _xfer_spec {
|
||
@@ -1194,10 +1187,6 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
|
||
if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
off += _emit_FLUSHP(dry_run, &buf[off],
|
||
pxs->desc->peri);
|
||
- if (pxs->desc->dst_interlace_size) {
|
||
- off += _emit_ADDH(dry_run, &buf[off], DST,
|
||
- pxs->desc->dst_interlace_size);
|
||
- }
|
||
}
|
||
|
||
return off;
|
||
@@ -1228,9 +1217,6 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330,
|
||
if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
off += _emit_FLUSHP(dry_run, &buf[off],
|
||
pxs->desc->peri);
|
||
- if (pxs->desc->src_interlace_size)
|
||
- off += _emit_ADDH(dry_run, &buf[off], SRC,
|
||
- pxs->desc->src_interlace_size);
|
||
}
|
||
|
||
return off;
|
||
@@ -2318,8 +2304,6 @@ static int pl330_config(struct dma_chan *chan,
|
||
pch->burst_sz = __ffs(slave_config->dst_addr_width);
|
||
if (slave_config->dst_maxburst)
|
||
pch->burst_len = slave_config->dst_maxburst;
|
||
- if (slave_config->src_interlace_size)
|
||
- pch->src_interlace_size = slave_config->src_interlace_size;
|
||
} else if (slave_config->direction == DMA_DEV_TO_MEM) {
|
||
if (slave_config->src_addr)
|
||
pch->fifo_addr = slave_config->src_addr;
|
||
@@ -2327,8 +2311,6 @@ static int pl330_config(struct dma_chan *chan,
|
||
pch->burst_sz = __ffs(slave_config->src_addr_width);
|
||
if (slave_config->src_maxburst)
|
||
pch->burst_len = slave_config->src_maxburst;
|
||
- if (slave_config->dst_interlace_size)
|
||
- pch->dst_interlace_size = slave_config->dst_interlace_size;
|
||
}
|
||
|
||
return 0;
|
||
@@ -2721,7 +2703,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
struct dma_pl330_desc *desc = NULL;
|
||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||
struct pl330_dmac *pl330 = pch->dmac;
|
||
- unsigned int size = 0;
|
||
dma_addr_t dst;
|
||
dma_addr_t src;
|
||
|
||
@@ -2747,14 +2728,12 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
desc->rqcfg.dst_inc = 0;
|
||
src = dma_addr;
|
||
dst = pch->fifo_addr;
|
||
- size = pch->src_interlace_size;
|
||
break;
|
||
case DMA_DEV_TO_MEM:
|
||
desc->rqcfg.src_inc = 0;
|
||
desc->rqcfg.dst_inc = 1;
|
||
src = pch->fifo_addr;
|
||
dst = dma_addr;
|
||
- size = pch->dst_interlace_size;
|
||
break;
|
||
default:
|
||
break;
|
||
@@ -2775,15 +2754,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
desc->num_periods = len / period_len;
|
||
desc->txd.flags = flags;
|
||
|
||
- desc->src_interlace_size = pch->src_interlace_size;
|
||
- desc->dst_interlace_size = pch->dst_interlace_size;
|
||
- /* refine bytes_requested if interlace_size set */
|
||
- if (size) {
|
||
- size += (pch->burst_len * (1 << pch->burst_sz));
|
||
- size *= desc->bytes_requested;
|
||
- size /= (pch->burst_len * (1 << pch->burst_sz));
|
||
- desc->bytes_requested = size;
|
||
- }
|
||
return &desc->txd;
|
||
}
|
||
|
||
@@ -2920,8 +2890,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||
|
||
desc->rqtype = direction;
|
||
desc->bytes_requested = sg_dma_len(sg);
|
||
- desc->src_interlace_size = pch->src_interlace_size;
|
||
- desc->dst_interlace_size = pch->dst_interlace_size;
|
||
}
|
||
|
||
/* Return the last desc in the chain */
|
||
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
|
||
index 3050f88daf9e..948c17e409e9 100644
|
||
--- a/include/linux/dmaengine.h
|
||
+++ b/include/linux/dmaengine.h
|
||
@@ -365,8 +365,6 @@ struct dma_slave_config {
|
||
u32 dst_maxburst;
|
||
bool device_fc;
|
||
unsigned int slave_id;
|
||
- unsigned int src_interlace_size;
|
||
- unsigned int dst_interlace_size;
|
||
};
|
||
|
||
/**
|
||
|
||
From 90870281a7399dffb49ff4d631ee9df249c3d0c0 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sun, 4 Feb 2018 10:47:28 +0100
|
||
Subject: [PATCH] Revert "dmaengine: pl330: fix bug that chan descdone is null"
|
||
|
||
This reverts commit 636c30b38ae6ec499735ce7621ba474944b4e9b7.
|
||
---
|
||
drivers/dma/pl330.c | 17 ++++++++---------
|
||
1 file changed, 8 insertions(+), 9 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index babaeace0a8a..6e375d7ec09c 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1789,17 +1789,16 @@ static int pl330_update(struct pl330_dmac *pl330)
|
||
|
||
/* Detach the req */
|
||
descdone = thrd->req[active].desc;
|
||
- if (descdone) {
|
||
- if (!descdone->cyclic) {
|
||
- thrd->req[active].desc = NULL;
|
||
- thrd->req_running = -1;
|
||
- /* Get going again ASAP */
|
||
- _start(thrd);
|
||
- }
|
||
|
||
- /* For now, just make a list of callbacks to be done */
|
||
- list_add_tail(&descdone->rqd, &pl330->req_done);
|
||
+ if (!descdone->cyclic) {
|
||
+ thrd->req[active].desc = NULL;
|
||
+ thrd->req_running = -1;
|
||
+ /* Get going again ASAP */
|
||
+ _start(thrd);
|
||
}
|
||
+
|
||
+ /* For now, just make a list of callbacks to be done */
|
||
+ list_add_tail(&descdone->rqd, &pl330->req_done);
|
||
}
|
||
}
|
||
|
||
|
||
From ca7c03b12f7c113e9f722a02c7acebabb2cccc27 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sun, 4 Feb 2018 10:47:38 +0100
|
||
Subject: [PATCH] Revert "dmaengine: pl330: flush before first loop"
|
||
|
||
This reverts commit 34be2cf4679cadbf910de9651d54b46930166446.
|
||
---
|
||
drivers/dma/pl330.c | 12 ++----------
|
||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 6e375d7ec09c..9664f71dbab2 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1351,11 +1351,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
/* forever loop */
|
||
off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
|
||
off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
|
||
-#ifdef CONFIG_ARCH_ROCKCHIP
|
||
- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
- off += _emit_FLUSHP(dry_run, &buf[off],
|
||
- pxs->desc->peri);
|
||
-#endif
|
||
+
|
||
/* loop0 */
|
||
off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
|
||
ljmp0 = off;
|
||
@@ -1431,11 +1427,7 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||
u32 ccr = pxs->ccr;
|
||
unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
|
||
int off = 0;
|
||
-#ifdef CONFIG_ARCH_ROCKCHIP
|
||
- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
- off += _emit_FLUSHP(dry_run, &buf[off],
|
||
- pxs->desc->peri);
|
||
-#endif
|
||
+
|
||
while (bursts) {
|
||
c = bursts;
|
||
off += _loop(pl330, dry_run, &buf[off], &c, pxs);
|
||
|
||
From 7e5d6f86b631c40624eb595910c23e7972783347 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sun, 4 Feb 2018 10:47:51 +0100
|
||
Subject: [PATCH] Revert "dmaengine: pl330: fix 2 bursts transfer when dma
|
||
flushes"
|
||
|
||
This reverts commit 98753e172dc1d06cf4d61c48f5c3487df0247472.
|
||
---
|
||
drivers/dma/pl330.c | 20 --------------------
|
||
1 file changed, 20 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 9664f71dbab2..9c3699ad2245 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1173,16 +1173,6 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
|
||
off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
off += _emit_ST(dry_run, &buf[off], ALWAYS);
|
||
-#ifdef CONFIG_ARCH_ROCKCHIP
|
||
- /*
|
||
- * Make suree dma has finish transmission, or later flush may
|
||
- * cause dma second transmission,and fifo is overrun.
|
||
- */
|
||
- off += _emit_WMB(dry_run, &buf[off]);
|
||
- off += _emit_NOP(dry_run, &buf[off]);
|
||
- off += _emit_WMB(dry_run, &buf[off]);
|
||
- off += _emit_NOP(dry_run, &buf[off]);
|
||
-#endif
|
||
|
||
if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
off += _emit_FLUSHP(dry_run, &buf[off],
|
||
@@ -1203,16 +1193,6 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330,
|
||
off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
off += _emit_LD(dry_run, &buf[off], ALWAYS);
|
||
off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
-#ifdef CONFIG_ARCH_ROCKCHIP
|
||
- /*
|
||
- * Make suree dma has finish transmission, or later flush may
|
||
- * cause dma second transmission,and fifo is overrun.
|
||
- */
|
||
- off += _emit_WMB(dry_run, &buf[off]);
|
||
- off += _emit_NOP(dry_run, &buf[off]);
|
||
- off += _emit_WMB(dry_run, &buf[off]);
|
||
- off += _emit_NOP(dry_run, &buf[off]);
|
||
-#endif
|
||
|
||
if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
off += _emit_FLUSHP(dry_run, &buf[off],
|
||
|
||
From 846d1829607d8806fd932fa3f8f4f0eb9e71d241 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sat, 21 Oct 2017 19:49:27 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: _loop_cyclic fix cycles of last
|
||
loop"
|
||
|
||
This reverts commit d7155171cbc65e45b5b0c8db03fd16fa57a181f2.
|
||
---
|
||
drivers/dma/pl330.c | 2 +-
|
||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 9c3699ad2245..be4ea6e089ae 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1370,7 +1370,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
ccr &= ~(0xf << CC_SRCBRSTLEN_SHFT);
|
||
ccr &= ~(0xf << CC_DSTBRSTLEN_SHFT);
|
||
off += _emit_MOV(dry_run, &buf[off], CCR, ccr);
|
||
- off += _emit_LP(dry_run, &buf[off], 1, c);
|
||
+ off += _emit_LP(dry_run, &buf[off], 1, c - 1);
|
||
ljmp1 = off;
|
||
off += _bursts(pl330, dry_run, &buf[off], pxs, 1);
|
||
lpend.cond = ALWAYS;
|
||
|
||
From f7fdbad73413294e56e632fa8353765b8e205582 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sun, 4 Feb 2018 11:05:44 +0100
|
||
Subject: [PATCH] Revert "dmaengine: pl330: pl330_tasklet init power_down by
|
||
pch->active"
|
||
|
||
This reverts commit 796b13f24a158f14d540bcf7316d843f72242c0d.
|
||
---
|
||
drivers/dma/pl330.c | 2 +-
|
||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index be4ea6e089ae..2ba795d599fb 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -2169,7 +2169,7 @@ static void pl330_tasklet(unsigned long data)
|
||
spin_lock(&pch->thread->dmac->lock);
|
||
_stop(pch->thread);
|
||
spin_unlock(&pch->thread->dmac->lock);
|
||
- power_down = pch->active;
|
||
+ power_down = true;
|
||
pch->active = false;
|
||
} else {
|
||
/* Make sure the PL330 Channel thread is active */
|
||
|
||
From 07a5172605729425390855a0b6ced66bfde22ee5 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Fri, 16 Jun 2017 23:14:54 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: _loop_cyclic supports unaligned
|
||
size"
|
||
|
||
This reverts commit 13dbe2cccd5851540af8158b12499c33801b6ef6.
|
||
---
|
||
drivers/dma/pl330.c | 38 ++++++++++----------------------------
|
||
1 file changed, 10 insertions(+), 28 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 2ba795d599fb..e5b3893d441e 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1360,28 +1360,6 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
}
|
||
|
||
- if (pl330->peripherals_req_type == BURST) {
|
||
- unsigned int ccr = pxs->ccr;
|
||
- unsigned long c = 0;
|
||
-
|
||
- c = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
|
||
-
|
||
- if (c) {
|
||
- ccr &= ~(0xf << CC_SRCBRSTLEN_SHFT);
|
||
- ccr &= ~(0xf << CC_DSTBRSTLEN_SHFT);
|
||
- off += _emit_MOV(dry_run, &buf[off], CCR, ccr);
|
||
- off += _emit_LP(dry_run, &buf[off], 1, c - 1);
|
||
- ljmp1 = off;
|
||
- off += _bursts(pl330, dry_run, &buf[off], pxs, 1);
|
||
- lpend.cond = ALWAYS;
|
||
- lpend.forever = false;
|
||
- lpend.loop = 1;
|
||
- lpend.bjump = off - ljmp1;
|
||
- off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
- off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||
- }
|
||
- }
|
||
-
|
||
off += _emit_SEV(dry_run, &buf[off], ev);
|
||
|
||
lpend.cond = ALWAYS;
|
||
@@ -1483,13 +1461,13 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
|
||
x = &pxs->desc->px;
|
||
|
||
- if (pl330->peripherals_req_type != BURST) {
|
||
- /* Error if xfer length is not aligned at burst size */
|
||
- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
- return -EINVAL;
|
||
- }
|
||
-
|
||
if (!pxs->desc->cyclic) {
|
||
+ if (pl330->peripherals_req_type != BURST) {
|
||
+ /* Error if xfer length is not aligned at burst size */
|
||
+ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
+ return -EINVAL;
|
||
+ }
|
||
+
|
||
off += _setup_xfer(pl330, dry_run, &buf[off], pxs);
|
||
|
||
/* DMASEV peripheral/event */
|
||
@@ -1497,6 +1475,10 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
/* DMAEND */
|
||
off += _emit_END(dry_run, &buf[off]);
|
||
} else {
|
||
+ /* Error if xfer length is not aligned at burst size */
|
||
+ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
+ return -EINVAL;
|
||
+
|
||
off += _setup_xfer_cyclic(pl330, dry_run, &buf[off],
|
||
pxs, thrd->ev);
|
||
}
|
||
|
||
From 5083d82f6622749e07174fe6da32e431068b59cb Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Fri, 16 Jun 2017 23:14:54 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: redefine the cyclic transfer"
|
||
|
||
This reverts commit 5f638786e66089344c9cf594b81fbf02cd794f15.
|
||
---
|
||
drivers/dma/pl330.c | 137 +++++++++++-----------------------------------------
|
||
1 file changed, 29 insertions(+), 108 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index e5b3893d441e..38c46f4e0408 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1307,76 +1307,6 @@ static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
|
||
return off;
|
||
}
|
||
|
||
-/* Returns bytes consumed */
|
||
-static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
- u8 buf[], unsigned long bursts, const struct _xfer_spec *pxs, int ev)
|
||
-{
|
||
- int cyc, off;
|
||
- unsigned lcnt0, lcnt1, ljmp0, ljmp1, ljmpfe;
|
||
- struct _arg_LPEND lpend;
|
||
- struct pl330_xfer *x = &pxs->desc->px;
|
||
-
|
||
- off = 0;
|
||
- ljmpfe = off;
|
||
- lcnt0 = pxs->desc->num_periods;
|
||
-
|
||
- if (bursts > 256) {
|
||
- lcnt1 = 256;
|
||
- cyc = bursts / 256;
|
||
- } else {
|
||
- lcnt1 = bursts;
|
||
- cyc = 1;
|
||
- }
|
||
-
|
||
- /* forever loop */
|
||
- off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
|
||
- off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
|
||
-
|
||
- /* loop0 */
|
||
- off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
|
||
- ljmp0 = off;
|
||
-
|
||
- /* loop1 */
|
||
- off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
|
||
- ljmp1 = off;
|
||
- off += _bursts(pl330, dry_run, &buf[off], pxs, cyc);
|
||
- lpend.cond = ALWAYS;
|
||
- lpend.forever = false;
|
||
- lpend.loop = 1;
|
||
- lpend.bjump = off - ljmp1;
|
||
- off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
-
|
||
- /* remainder */
|
||
- lcnt1 = bursts - (lcnt1 * cyc);
|
||
-
|
||
- if (lcnt1) {
|
||
- off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
|
||
- ljmp1 = off;
|
||
- off += _bursts(pl330, dry_run, &buf[off], pxs, 1);
|
||
- lpend.cond = ALWAYS;
|
||
- lpend.forever = false;
|
||
- lpend.loop = 1;
|
||
- lpend.bjump = off - ljmp1;
|
||
- off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
- }
|
||
-
|
||
- off += _emit_SEV(dry_run, &buf[off], ev);
|
||
-
|
||
- lpend.cond = ALWAYS;
|
||
- lpend.forever = false;
|
||
- lpend.loop = 0;
|
||
- lpend.bjump = off - ljmp0;
|
||
- off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
-
|
||
- lpend.cond = ALWAYS;
|
||
- lpend.forever = true;
|
||
- lpend.loop = 1;
|
||
- lpend.bjump = off - ljmpfe;
|
||
- off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
-
|
||
- return off;
|
||
-}
|
||
-
|
||
static inline int _setup_loops(struct pl330_dmac *pl330,
|
||
unsigned dry_run, u8 buf[],
|
||
const struct _xfer_spec *pxs)
|
||
@@ -1396,16 +1326,19 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||
}
|
||
|
||
static inline int _setup_xfer(struct pl330_dmac *pl330,
|
||
- unsigned dry_run, u8 buf[],
|
||
+ unsigned dry_run, u8 buf[], u32 period,
|
||
const struct _xfer_spec *pxs)
|
||
{
|
||
struct pl330_xfer *x = &pxs->desc->px;
|
||
+ struct pl330_reqcfg *rqcfg = &pxs->desc->rqcfg;
|
||
int off = 0;
|
||
|
||
/* DMAMOV SAR, x->src_addr */
|
||
- off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
|
||
+ off += _emit_MOV(dry_run, &buf[off], SAR,
|
||
+ x->src_addr + rqcfg->src_inc * period * x->bytes);
|
||
/* DMAMOV DAR, x->dst_addr */
|
||
- off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
|
||
+ off += _emit_MOV(dry_run, &buf[off], DAR,
|
||
+ x->dst_addr + rqcfg->dst_inc * period * x->bytes);
|
||
|
||
/* Setup Loop(s) */
|
||
off += _setup_loops(pl330, dry_run, &buf[off], pxs);
|
||
@@ -1427,20 +1360,6 @@ static inline int _setup_xfer(struct pl330_dmac *pl330,
|
||
return off;
|
||
}
|
||
|
||
-static inline int _setup_xfer_cyclic(struct pl330_dmac *pl330, unsigned dry_run,
|
||
- u8 buf[], const struct _xfer_spec *pxs, int ev)
|
||
-{
|
||
- struct pl330_xfer *x = &pxs->desc->px;
|
||
- u32 ccr = pxs->ccr;
|
||
- unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr);
|
||
- int off = 0;
|
||
-
|
||
- /* Setup Loop(s) */
|
||
- off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev);
|
||
-
|
||
- return off;
|
||
-}
|
||
-
|
||
/*
|
||
* A req is a sequence of one or more xfer units.
|
||
* Returns the number of bytes taken to setup the MC for the req.
|
||
@@ -1453,34 +1372,42 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
struct pl330_xfer *x;
|
||
u8 *buf = req->mc_cpu;
|
||
int off = 0;
|
||
+ int period;
|
||
+ int again_off;
|
||
|
||
PL330_DBGMC_START(req->mc_bus);
|
||
|
||
/* DMAMOV CCR, ccr */
|
||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||
+ again_off = off;
|
||
|
||
x = &pxs->desc->px;
|
||
+ if (pl330->peripherals_req_type != BURST) {
|
||
+ /* Error if xfer length is not aligned at burst size */
|
||
+ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
+ return -EINVAL;
|
||
+ }
|
||
|
||
- if (!pxs->desc->cyclic) {
|
||
- if (pl330->peripherals_req_type != BURST) {
|
||
- /* Error if xfer length is not aligned at burst size */
|
||
- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
- return -EINVAL;
|
||
- }
|
||
-
|
||
- off += _setup_xfer(pl330, dry_run, &buf[off], pxs);
|
||
+ for (period = 0; period < pxs->desc->num_periods; period++) {
|
||
+ off += _setup_xfer(pl330, dry_run, &buf[off], period, pxs);
|
||
|
||
/* DMASEV peripheral/event */
|
||
off += _emit_SEV(dry_run, &buf[off], thrd->ev);
|
||
+ }
|
||
+
|
||
+ if (!pxs->desc->cyclic) {
|
||
/* DMAEND */
|
||
off += _emit_END(dry_run, &buf[off]);
|
||
} else {
|
||
- /* Error if xfer length is not aligned at burst size */
|
||
- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
- return -EINVAL;
|
||
-
|
||
- off += _setup_xfer_cyclic(pl330, dry_run, &buf[off],
|
||
- pxs, thrd->ev);
|
||
+ struct _arg_LPEND lpend;
|
||
+ /* LP */
|
||
+ off += _emit_LP(dry_run, &buf[off], 0, 255);
|
||
+ /* LPEND */
|
||
+ lpend.cond = ALWAYS;
|
||
+ lpend.forever = false;
|
||
+ lpend.loop = 0;
|
||
+ lpend.bjump = off - again_off;
|
||
+ off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
}
|
||
|
||
return off;
|
||
@@ -2655,7 +2582,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
{
|
||
struct dma_pl330_desc *desc = NULL;
|
||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||
- struct pl330_dmac *pl330 = pch->dmac;
|
||
dma_addr_t dst;
|
||
dma_addr_t src;
|
||
|
||
@@ -2694,12 +2620,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
|
||
desc->rqtype = direction;
|
||
desc->rqcfg.brst_size = pch->burst_sz;
|
||
-
|
||
- if (pl330->peripherals_req_type == BURST)
|
||
- desc->rqcfg.brst_len = pch->burst_len;
|
||
- else
|
||
- desc->rqcfg.brst_len = 1;
|
||
-
|
||
+ desc->rqcfg.brst_len = pch->burst_len;
|
||
desc->bytes_requested = len;
|
||
fill_px(&desc->px, dst, src, period_len);
|
||
|
||
|
||
From e8a5eaffda3179b78b9d1bb619ddf25dd651d134 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Fri, 16 Jun 2017 23:14:54 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: make transfer run infinitely
|
||
without CPU intervention"
|
||
|
||
This reverts commit e8a6e5086cb82d59cae6ae029b1eb4432cc62288.
|
||
---
|
||
drivers/dma/pl330.c | 199 +++++++++++++++++++++++++++-------------------------
|
||
1 file changed, 105 insertions(+), 94 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 38c46f4e0408..ad9d616551f8 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -447,6 +447,9 @@ struct dma_pl330_chan {
|
||
int burst_len; /* the number of burst */
|
||
dma_addr_t fifo_addr;
|
||
|
||
+ /* for cyclic capability */
|
||
+ bool cyclic;
|
||
+
|
||
/* for runtime pm tracking */
|
||
bool active;
|
||
};
|
||
@@ -532,10 +535,6 @@ struct dma_pl330_desc {
|
||
unsigned peri:5;
|
||
/* Hook to attach to DMAC's list of reqs with due callback */
|
||
struct list_head rqd;
|
||
-
|
||
- /* For cyclic capability */
|
||
- bool cyclic;
|
||
- size_t num_periods;
|
||
};
|
||
|
||
struct _xfer_spec {
|
||
@@ -1326,19 +1325,16 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||
}
|
||
|
||
static inline int _setup_xfer(struct pl330_dmac *pl330,
|
||
- unsigned dry_run, u8 buf[], u32 period,
|
||
+ unsigned dry_run, u8 buf[],
|
||
const struct _xfer_spec *pxs)
|
||
{
|
||
struct pl330_xfer *x = &pxs->desc->px;
|
||
- struct pl330_reqcfg *rqcfg = &pxs->desc->rqcfg;
|
||
int off = 0;
|
||
|
||
/* DMAMOV SAR, x->src_addr */
|
||
- off += _emit_MOV(dry_run, &buf[off], SAR,
|
||
- x->src_addr + rqcfg->src_inc * period * x->bytes);
|
||
+ off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
|
||
/* DMAMOV DAR, x->dst_addr */
|
||
- off += _emit_MOV(dry_run, &buf[off], DAR,
|
||
- x->dst_addr + rqcfg->dst_inc * period * x->bytes);
|
||
+ off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
|
||
|
||
/* Setup Loop(s) */
|
||
off += _setup_loops(pl330, dry_run, &buf[off], pxs);
|
||
@@ -1372,14 +1368,11 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
struct pl330_xfer *x;
|
||
u8 *buf = req->mc_cpu;
|
||
int off = 0;
|
||
- int period;
|
||
- int again_off;
|
||
|
||
PL330_DBGMC_START(req->mc_bus);
|
||
|
||
/* DMAMOV CCR, ccr */
|
||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||
- again_off = off;
|
||
|
||
x = &pxs->desc->px;
|
||
if (pl330->peripherals_req_type != BURST) {
|
||
@@ -1388,27 +1381,12 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
return -EINVAL;
|
||
}
|
||
|
||
- for (period = 0; period < pxs->desc->num_periods; period++) {
|
||
- off += _setup_xfer(pl330, dry_run, &buf[off], period, pxs);
|
||
-
|
||
- /* DMASEV peripheral/event */
|
||
- off += _emit_SEV(dry_run, &buf[off], thrd->ev);
|
||
- }
|
||
+ off += _setup_xfer(pl330, dry_run, &buf[off], pxs);
|
||
|
||
- if (!pxs->desc->cyclic) {
|
||
- /* DMAEND */
|
||
- off += _emit_END(dry_run, &buf[off]);
|
||
- } else {
|
||
- struct _arg_LPEND lpend;
|
||
- /* LP */
|
||
- off += _emit_LP(dry_run, &buf[off], 0, 255);
|
||
- /* LPEND */
|
||
- lpend.cond = ALWAYS;
|
||
- lpend.forever = false;
|
||
- lpend.loop = 0;
|
||
- lpend.bjump = off - again_off;
|
||
- off += _emit_LPEND(dry_run, &buf[off], &lpend);
|
||
- }
|
||
+ /* DMASEV peripheral/event */
|
||
+ off += _emit_SEV(dry_run, &buf[off], thrd->ev);
|
||
+ /* DMAEND */
|
||
+ off += _emit_END(dry_run, &buf[off]);
|
||
|
||
return off;
|
||
}
|
||
@@ -1670,13 +1648,12 @@ static int pl330_update(struct pl330_dmac *pl330)
|
||
|
||
/* Detach the req */
|
||
descdone = thrd->req[active].desc;
|
||
+ thrd->req[active].desc = NULL;
|
||
|
||
- if (!descdone->cyclic) {
|
||
- thrd->req[active].desc = NULL;
|
||
- thrd->req_running = -1;
|
||
- /* Get going again ASAP */
|
||
- _start(thrd);
|
||
- }
|
||
+ thrd->req_running = -1;
|
||
+
|
||
+ /* Get going again ASAP */
|
||
+ _start(thrd);
|
||
|
||
/* For now, just make a list of callbacks to be done */
|
||
list_add_tail(&descdone->rqd, &pl330->req_done);
|
||
@@ -2049,27 +2026,12 @@ static void pl330_tasklet(unsigned long data)
|
||
spin_lock_irqsave(&pch->lock, flags);
|
||
|
||
/* Pick up ripe tomatoes */
|
||
- list_for_each_entry_safe(desc, _dt, &pch->work_list, node) {
|
||
+ list_for_each_entry_safe(desc, _dt, &pch->work_list, node)
|
||
if (desc->status == DONE) {
|
||
- if (!desc->cyclic) {
|
||
+ if (!pch->cyclic)
|
||
dma_cookie_complete(&desc->txd);
|
||
- list_move_tail(&desc->node, &pch->completed_list);
|
||
- } else {
|
||
- dma_async_tx_callback callback;
|
||
- void *callback_param;
|
||
-
|
||
- desc->status = BUSY;
|
||
- callback = desc->txd.callback;
|
||
- callback_param = desc->txd.callback_param;
|
||
-
|
||
- if (callback) {
|
||
- spin_unlock_irqrestore(&pch->lock, flags);
|
||
- callback(callback_param);
|
||
- spin_lock_irqsave(&pch->lock, flags);
|
||
- }
|
||
- }
|
||
+ list_move_tail(&desc->node, &pch->completed_list);
|
||
}
|
||
- }
|
||
|
||
/* Try to submit a req imm. next to the last completed cookie */
|
||
fill_queue(pch);
|
||
@@ -2097,8 +2059,20 @@ static void pl330_tasklet(unsigned long data)
|
||
callback = desc->txd.callback;
|
||
callback_param = desc->txd.callback_param;
|
||
|
||
- desc->status = FREE;
|
||
- list_move_tail(&desc->node, &pch->dmac->desc_pool);
|
||
+ if (pch->cyclic) {
|
||
+ desc->status = PREP;
|
||
+ list_move_tail(&desc->node, &pch->work_list);
|
||
+ if (power_down) {
|
||
+ pch->active = true;
|
||
+ spin_lock(&pch->thread->dmac->lock);
|
||
+ _start(pch->thread);
|
||
+ spin_unlock(&pch->thread->dmac->lock);
|
||
+ power_down = false;
|
||
+ }
|
||
+ } else {
|
||
+ desc->status = FREE;
|
||
+ list_move_tail(&desc->node, &pch->dmac->desc_pool);
|
||
+ }
|
||
|
||
dma_descriptor_unmap(&desc->txd);
|
||
|
||
@@ -2158,6 +2132,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
|
||
spin_lock_irqsave(&pl330->lock, flags);
|
||
|
||
dma_cookie_init(chan);
|
||
+ pch->cyclic = false;
|
||
|
||
pch->thread = pl330_request_channel(pl330);
|
||
if (!pch->thread) {
|
||
@@ -2281,7 +2256,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
|
||
pl330_release_channel(pch->thread);
|
||
pch->thread = NULL;
|
||
|
||
- list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
|
||
+ if (pch->cyclic)
|
||
+ list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
|
||
|
||
spin_unlock_irqrestore(&pl330->lock, flags);
|
||
pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
|
||
@@ -2335,7 +2311,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||
|
||
/* Check in pending list */
|
||
list_for_each_entry(desc, &pch->work_list, node) {
|
||
- if (desc->status == DONE && !desc->cyclic)
|
||
+ if (desc->status == DONE)
|
||
transferred = desc->bytes_requested;
|
||
else if (running && desc == running)
|
||
transferred =
|
||
@@ -2407,8 +2383,12 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
|
||
/* Assign cookies to all nodes */
|
||
while (!list_empty(&last->node)) {
|
||
desc = list_entry(last->node.next, struct dma_pl330_desc, node);
|
||
-
|
||
+ if (pch->cyclic) {
|
||
+ desc->txd.callback = last->txd.callback;
|
||
+ desc->txd.callback_param = last->txd.callback_param;
|
||
+ }
|
||
desc->last = false;
|
||
+
|
||
dma_cookie_assign(&desc->txd);
|
||
|
||
list_move_tail(&desc->node, &pch->submitted_list);
|
||
@@ -2508,9 +2488,6 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
|
||
desc->peri = peri_id ? pch->chan.chan_id : 0;
|
||
desc->rqcfg.pcfg = &pch->dmac->pcfg;
|
||
|
||
- desc->cyclic = false;
|
||
- desc->num_periods = 1;
|
||
-
|
||
dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
|
||
|
||
return desc;
|
||
@@ -2580,8 +2557,10 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
size_t period_len, enum dma_transfer_direction direction,
|
||
unsigned long flags)
|
||
{
|
||
- struct dma_pl330_desc *desc = NULL;
|
||
+ struct dma_pl330_desc *desc = NULL, *first = NULL;
|
||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||
+ struct pl330_dmac *pl330 = pch->dmac;
|
||
+ unsigned int i;
|
||
dma_addr_t dst;
|
||
dma_addr_t src;
|
||
|
||
@@ -2594,38 +2573,70 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
return NULL;
|
||
}
|
||
|
||
- desc = pl330_get_desc(pch);
|
||
- if (!desc) {
|
||
- dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n",
|
||
- __func__, __LINE__);
|
||
- return NULL;
|
||
- }
|
||
+ for (i = 0; i < len / period_len; i++) {
|
||
+ desc = pl330_get_desc(pch);
|
||
+ if (!desc) {
|
||
+ dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n",
|
||
+ __func__, __LINE__);
|
||
|
||
- switch (direction) {
|
||
- case DMA_MEM_TO_DEV:
|
||
- desc->rqcfg.src_inc = 1;
|
||
- desc->rqcfg.dst_inc = 0;
|
||
- src = dma_addr;
|
||
- dst = pch->fifo_addr;
|
||
- break;
|
||
- case DMA_DEV_TO_MEM:
|
||
- desc->rqcfg.src_inc = 0;
|
||
- desc->rqcfg.dst_inc = 1;
|
||
- src = pch->fifo_addr;
|
||
- dst = dma_addr;
|
||
- break;
|
||
- default:
|
||
- break;
|
||
+ if (!first)
|
||
+ return NULL;
|
||
+
|
||
+ spin_lock_irqsave(&pl330->pool_lock, flags);
|
||
+
|
||
+ while (!list_empty(&first->node)) {
|
||
+ desc = list_entry(first->node.next,
|
||
+ struct dma_pl330_desc, node);
|
||
+ list_move_tail(&desc->node, &pl330->desc_pool);
|
||
+ }
|
||
+
|
||
+ list_move_tail(&first->node, &pl330->desc_pool);
|
||
+
|
||
+ spin_unlock_irqrestore(&pl330->pool_lock, flags);
|
||
+
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ switch (direction) {
|
||
+ case DMA_MEM_TO_DEV:
|
||
+ desc->rqcfg.src_inc = 1;
|
||
+ desc->rqcfg.dst_inc = 0;
|
||
+ src = dma_addr;
|
||
+ dst = pch->fifo_addr;
|
||
+ break;
|
||
+ case DMA_DEV_TO_MEM:
|
||
+ desc->rqcfg.src_inc = 0;
|
||
+ desc->rqcfg.dst_inc = 1;
|
||
+ src = pch->fifo_addr;
|
||
+ dst = dma_addr;
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ desc->rqtype = direction;
|
||
+ desc->rqcfg.brst_size = pch->burst_sz;
|
||
+
|
||
+ if (pl330->peripherals_req_type == BURST)
|
||
+ desc->rqcfg.brst_len = pch->burst_len;
|
||
+ else
|
||
+ desc->rqcfg.brst_len = 1;
|
||
+
|
||
+ desc->bytes_requested = period_len;
|
||
+ fill_px(&desc->px, dst, src, period_len);
|
||
+
|
||
+ if (!first)
|
||
+ first = desc;
|
||
+ else
|
||
+ list_add_tail(&desc->node, &first->node);
|
||
+
|
||
+ dma_addr += period_len;
|
||
}
|
||
|
||
- desc->rqtype = direction;
|
||
- desc->rqcfg.brst_size = pch->burst_sz;
|
||
- desc->rqcfg.brst_len = pch->burst_len;
|
||
- desc->bytes_requested = len;
|
||
- fill_px(&desc->px, dst, src, period_len);
|
||
+ if (!desc)
|
||
+ return NULL;
|
||
|
||
- desc->cyclic = true;
|
||
- desc->num_periods = len / period_len;
|
||
+ pch->cyclic = true;
|
||
desc->txd.flags = flags;
|
||
|
||
return &desc->txd;
|
||
|
||
From 0cb8495a963957245b2196e34e404472445a9d3a Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Sun, 22 Jul 2018 16:07:46 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: fix error message to
|
||
dev_err_ratelimited"
|
||
|
||
This reverts commit e25503f147cf665b6fc910983859d9f94eaf0d00.
|
||
---
|
||
drivers/dma/pl330.c | 4 ++--
|
||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index ad9d616551f8..3d5d91084605 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1620,8 +1620,8 @@ static int pl330_update(struct pl330_dmac *pl330)
|
||
if (pl330->pcfg.num_events < 32
|
||
&& val & ~((1 << pl330->pcfg.num_events) - 1)) {
|
||
pl330->dmac_tbd.reset_dmac = true;
|
||
- dev_err_ratelimited(pl330->ddma.dev, "%s:%d Unexpected!\n",
|
||
- __func__, __LINE__);
|
||
+ dev_err(pl330->ddma.dev, "%s:%d Unexpected!\n", __func__,
|
||
+ __LINE__);
|
||
ret = 1;
|
||
goto updt_exit;
|
||
}
|
||
|
||
From c32a7b1b9bac8450d9c0ff71b2256714ab32e5c3 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Fri, 16 Jun 2017 23:14:55 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: support transfer that doesn't align
|
||
with (burst len * burst size)"
|
||
|
||
This reverts commit c66ecf19b98ffac86177c29859e683de39f44e73.
|
||
---
|
||
drivers/dma/pl330.c | 23 +++--------------------
|
||
1 file changed, 3 insertions(+), 20 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 3d5d91084605..2f5f8d40147c 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -240,7 +240,6 @@ enum pl330_byteswap {
|
||
|
||
#define BYTE_TO_BURST(b, ccr) ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr))
|
||
#define BURST_TO_BYTE(c, ccr) ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr))
|
||
-#define BYTE_MOD_BURST_LEN(b, ccr) (((b) / BRST_SIZE(ccr)) % BRST_LEN(ccr))
|
||
|
||
/*
|
||
* With 256 bytes, we can do more than 2.5MB and 5MB xfers per req
|
||
@@ -1339,20 +1338,6 @@ static inline int _setup_xfer(struct pl330_dmac *pl330,
|
||
/* Setup Loop(s) */
|
||
off += _setup_loops(pl330, dry_run, &buf[off], pxs);
|
||
|
||
- if (pl330->peripherals_req_type == BURST) {
|
||
- unsigned int ccr = pxs->ccr;
|
||
- unsigned long c = 0;
|
||
-
|
||
- c = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr);
|
||
-
|
||
- if (c) {
|
||
- ccr &= ~(0xf << CC_SRCBRSTLEN_SHFT);
|
||
- ccr &= ~(0xf << CC_DSTBRSTLEN_SHFT);
|
||
- off += _emit_MOV(dry_run, &buf[off], CCR, ccr);
|
||
- off += _loop(pl330, dry_run, &buf[off], &c, pxs);
|
||
- }
|
||
- }
|
||
-
|
||
return off;
|
||
}
|
||
|
||
@@ -1375,11 +1360,9 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||
|
||
x = &pxs->desc->px;
|
||
- if (pl330->peripherals_req_type != BURST) {
|
||
- /* Error if xfer length is not aligned at burst size */
|
||
- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
- return -EINVAL;
|
||
- }
|
||
+ /* Error if xfer length is not aligned at burst size */
|
||
+ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
+ return -EINVAL;
|
||
|
||
off += _setup_xfer(pl330, dry_run, &buf[off], pxs);
|
||
|
||
|
||
From 8a5c2aac1f170e5d8a8cdce3ab147cf641e38981 Mon Sep 17 00:00:00 2001
|
||
From: Jonas Karlman <jonas@kwiboo.se>
|
||
Date: Fri, 16 Jun 2017 23:14:55 +0200
|
||
Subject: [PATCH] Revert "dmaengine: pl330: add burst mode according to dts
|
||
config"
|
||
|
||
This reverts commit 8e770f371cc27f8828cb9ceb0516adc23fe75995.
|
||
---
|
||
drivers/dma/pl330.c | 36 ++++++++++++++----------------------
|
||
1 file changed, 14 insertions(+), 22 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 2f5f8d40147c..f7977979cbf5 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -494,8 +494,6 @@ struct pl330_dmac {
|
||
/* Peripheral channels connected to this DMAC */
|
||
unsigned int num_peripherals;
|
||
struct dma_pl330_chan *peripherals; /* keep at end */
|
||
- /* set peripherals request type according to soc config*/
|
||
- enum pl330_cond peripherals_req_type;
|
||
int quirks;
|
||
};
|
||
|
||
@@ -1165,7 +1163,12 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
|
||
int cyc)
|
||
{
|
||
int off = 0;
|
||
- enum pl330_cond cond = pl330->peripherals_req_type;
|
||
+ enum pl330_cond cond;
|
||
+
|
||
+ if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
|
||
+ cond = BURST;
|
||
+ else
|
||
+ cond = SINGLE;
|
||
|
||
while (cyc--) {
|
||
off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
@@ -1185,7 +1188,12 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330,
|
||
const struct _xfer_spec *pxs, int cyc)
|
||
{
|
||
int off = 0;
|
||
- enum pl330_cond cond = pl330->peripherals_req_type;
|
||
+ enum pl330_cond cond;
|
||
+
|
||
+ if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
|
||
+ cond = BURST;
|
||
+ else
|
||
+ cond = SINGLE;
|
||
|
||
while (cyc--) {
|
||
off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
@@ -2599,12 +2607,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
|
||
desc->rqtype = direction;
|
||
desc->rqcfg.brst_size = pch->burst_sz;
|
||
-
|
||
- if (pl330->peripherals_req_type == BURST)
|
||
- desc->rqcfg.brst_len = pch->burst_len;
|
||
- else
|
||
- desc->rqcfg.brst_len = 1;
|
||
-
|
||
+ desc->rqcfg.brst_len = 1;
|
||
desc->bytes_requested = period_len;
|
||
fill_px(&desc->px, dst, src, period_len);
|
||
|
||
@@ -2706,7 +2709,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||
{
|
||
struct dma_pl330_desc *first, *desc = NULL;
|
||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||
- struct pl330_dmac *pl330 = pch->dmac;
|
||
struct scatterlist *sg;
|
||
int i;
|
||
dma_addr_t addr;
|
||
@@ -2750,12 +2752,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||
}
|
||
|
||
desc->rqcfg.brst_size = pch->burst_sz;
|
||
-
|
||
- if (pl330->peripherals_req_type == BURST)
|
||
- desc->rqcfg.brst_len = pch->burst_len;
|
||
- else
|
||
- desc->rqcfg.brst_len = 1;
|
||
-
|
||
+ desc->rqcfg.brst_len = 1;
|
||
desc->rqtype = direction;
|
||
desc->bytes_requested = sg_dma_len(sg);
|
||
}
|
||
@@ -2851,11 +2848,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
|
||
pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
|
||
|
||
- if (of_find_property(np, "peripherals-req-type-burst", NULL))
|
||
- pl330->peripherals_req_type = BURST;
|
||
- else
|
||
- pl330->peripherals_req_type = SINGLE;
|
||
-
|
||
/* get quirk */
|
||
for (i = 0; i < ARRAY_SIZE(of_quirks); i++)
|
||
if (of_property_read_bool(np, of_quirks[i].quirk))
|
||
|
||
From 31567aa7a43385bbc429eff72855b49c90c2ac97 Mon Sep 17 00:00:00 2001
|
||
From: Vinod Koul <vinod.koul@intel.com>
|
||
Date: Tue, 5 Jul 2016 10:02:16 +0530
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: explicitly freeup irq
|
||
|
||
dmaengine device should explicitly call devm_free_irq() when using
|
||
devm_request_irq().
|
||
|
||
The irq is still ON when devices remove is executed and irq should be
|
||
quiesced before remove is completed.
|
||
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
Cc: Jassi Brar <jassisinghbrar@gmail.com>
|
||
Cc: Linus Walleij <linus.walleij@linaro.org>
|
||
(cherry picked from commit 46cf94d6ab38420690d890d9922bfc61a7b3e2c5)
|
||
---
|
||
drivers/dma/pl330.c | 6 ++++++
|
||
1 file changed, 6 insertions(+)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index f7977979cbf5..b6793b0d53c9 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -3015,12 +3015,18 @@ static int pl330_remove(struct amba_device *adev)
|
||
{
|
||
struct pl330_dmac *pl330 = amba_get_drvdata(adev);
|
||
struct dma_pl330_chan *pch, *_p;
|
||
+ int i, irq;
|
||
|
||
pm_runtime_get_noresume(pl330->ddma.dev);
|
||
|
||
if (adev->dev.of_node)
|
||
of_dma_controller_free(adev->dev.of_node);
|
||
|
||
+ for (i = 0; i < AMBA_NR_IRQS; i++) {
|
||
+ irq = adev->irq[i];
|
||
+ devm_free_irq(&adev->dev, irq, pl330);
|
||
+ }
|
||
+
|
||
dma_async_device_unregister(&pl330->ddma);
|
||
|
||
/* Idle the DMAC */
|
||
|
||
From ba1d527ad2e0ac6b1f60f79b6e15cd2231876367 Mon Sep 17 00:00:00 2001
|
||
From: Stephen Barber <smbarber@chromium.org>
|
||
Date: Thu, 18 Aug 2016 17:59:59 -0700
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix residual for non-running BUSY
|
||
descriptors
|
||
|
||
Only one descriptor in the work list should be running at
|
||
any given time, but it's possible to have an enqueued BUSY
|
||
descriptor that has not yet transferred any data, or for
|
||
a BUSY descriptor to linger briefly before transitioning
|
||
to DONE. These cases should be handled to keep residual
|
||
calculations consistent even with the non-running BUSY
|
||
descriptors in the work list.
|
||
|
||
Signed-off-by: Stephen Barber <smbarber@chromium.org>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit d64e9a2c750930272492952c16f3f2c95311a6c9)
|
||
---
|
||
drivers/dma/pl330.c | 13 ++++++++++++-
|
||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index b6793b0d53c9..7e05ef5ba37f 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -2283,7 +2283,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||
{
|
||
enum dma_status ret;
|
||
unsigned long flags;
|
||
- struct dma_pl330_desc *desc, *running = NULL;
|
||
+ struct dma_pl330_desc *desc, *running = NULL, *last_enq = NULL;
|
||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||
unsigned int transferred, residual = 0;
|
||
|
||
@@ -2300,6 +2300,8 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||
if (pch->thread->req_running != -1)
|
||
running = pch->thread->req[pch->thread->req_running].desc;
|
||
|
||
+ last_enq = pch->thread->req[pch->thread->lstenq].desc;
|
||
+
|
||
/* Check in pending list */
|
||
list_for_each_entry(desc, &pch->work_list, node) {
|
||
if (desc->status == DONE)
|
||
@@ -2307,6 +2309,15 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||
else if (running && desc == running)
|
||
transferred =
|
||
pl330_get_current_xferred_count(pch, desc);
|
||
+ else if (desc->status == BUSY)
|
||
+ /*
|
||
+ * Busy but not running means either just enqueued,
|
||
+ * or finished and not yet marked done
|
||
+ */
|
||
+ if (desc == last_enq)
|
||
+ transferred = 0;
|
||
+ else
|
||
+ transferred = desc->bytes_requested;
|
||
else
|
||
transferred = 0;
|
||
residual += desc->bytes_requested - transferred;
|
||
|
||
From c6ddb1c340be89262163fc1f1ddbeff2b7adac7c Mon Sep 17 00:00:00 2001
|
||
From: Hsin-Yu Chao <hychao@chromium.org>
|
||
Date: Tue, 23 Aug 2016 17:16:55 +0800
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: Acquire dmac's spinlock in
|
||
pl330_tx_status
|
||
|
||
There is a racing when accessing dmac thread in pl330_tx_status that
|
||
the pl330_update is handling active request at the same time and
|
||
changing the status of descriptors. This could cause an invalid
|
||
transferred count from BUSY descriptor added up to the residual number.
|
||
Fix the bug by using the dmac's spinlock in pl330_tx_status to protect
|
||
thread resources from changing.
|
||
Note that the nested order of holding dmac's and dma_chan's spinlock is
|
||
consistent with the rest of the driver: dma_chan first and then dmac,
|
||
so it is safe from deadlock scenario.
|
||
|
||
Signed-off-by: Hsin-Yu Chao <hychao@chromium.org>
|
||
Reviewed-by: Guenter Roeck <groeck@chromium.org>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit a40235a2278a315261ee007fc433ec1cfb31666f)
|
||
---
|
||
drivers/dma/pl330.c | 2 ++
|
||
1 file changed, 2 insertions(+)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 7e05ef5ba37f..93efdcc54f19 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -2296,6 +2296,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||
goto out;
|
||
|
||
spin_lock_irqsave(&pch->lock, flags);
|
||
+ spin_lock(&pch->thread->dmac->lock);
|
||
|
||
if (pch->thread->req_running != -1)
|
||
running = pch->thread->req[pch->thread->req_running].desc;
|
||
@@ -2338,6 +2339,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
|
||
if (desc->last)
|
||
residual = 0;
|
||
}
|
||
+ spin_unlock(&pch->thread->dmac->lock);
|
||
spin_unlock_irqrestore(&pch->lock, flags);
|
||
|
||
out:
|
||
|
||
From a2bd9dfc9421a44c86ad35c6b29fc28534917553 Mon Sep 17 00:00:00 2001
|
||
From: Stephen Barber <smbarber@chromium.org>
|
||
Date: Tue, 1 Nov 2016 16:44:27 -0700
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: Handle xferred count if DMAMOV
|
||
hasn't finished
|
||
|
||
After executing DMAGO it's possible that a request can come in for the
|
||
current xferred count, but if that happens too soon then DMAMOV SAR/DAR
|
||
may not have yet completed. If that happens, we should explicitly return 0
|
||
since nothing has been transferred yet.
|
||
|
||
Signed-off-by: Stephen Barber <smbarber@chromium.org>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit c44da03dd517c11c2b3525937b0a241fc1c69399)
|
||
---
|
||
drivers/dma/pl330.c | 5 +++++
|
||
1 file changed, 5 insertions(+)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 93efdcc54f19..497cc048feaa 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -2274,6 +2274,11 @@ static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
|
||
}
|
||
pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
|
||
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
||
+
|
||
+ /* If DMAMOV hasn't finished yet, SAR/DAR can be zero */
|
||
+ if (!val)
|
||
+ return 0;
|
||
+
|
||
return val - addr;
|
||
}
|
||
|
||
|
||
From 166204f617a83115d81ffdf34329757b4b1f9fb0 Mon Sep 17 00:00:00 2001
|
||
From: Vladimir Murzin <vladimir.murzin@arm.com>
|
||
Date: Wed, 7 Dec 2016 13:17:40 +0000
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: do not generate unaligned access
|
||
|
||
When PL330 is used with !MMU the following fault is seen:
|
||
|
||
Unhandled fault: alignment exception (0x801) at 0x8f26a002
|
||
Internal error: : 801 [#1] ARM
|
||
Modules linked in:
|
||
CPU: 0 PID: 640 Comm: dma0chan0-copy0 Not tainted 4.8.0-6a82063-clean+ #1600
|
||
Hardware name: ARM-Versatile Express
|
||
task: 8f1baa80 task.stack: 8e6fe000
|
||
PC is at _setup_req+0x4c/0x350
|
||
LR is at 0x8f2cbc00
|
||
pc : [<801ea538>] lr : [<8f2cbc00>] psr: 60000093
|
||
sp : 8e6ffdc0 ip : 00000000 fp : 00000000
|
||
r10: 00000000 r9 : 8f2cba10 r8 : 8f2cbc00
|
||
r7 : 80000013 r6 : 8f21a050 r5 : 8f21a000 r4 : 8f2ac800
|
||
r3 : 8e6ffe18 r2 : 00944251 r1 : ffffffbc r0 : 8f26a000
|
||
Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none
|
||
Control: 00c5387c
|
||
Process dma0chan0-copy0 (pid: 640, stack limit = 0x8e6fe210)
|
||
Stack: (0x8e6ffdc0 to 0x8e700000)
|
||
fdc0: 00000001 60000093 00000000 8f2cba10 8f26a000 00000004 8f0ae000 8f2cbc00
|
||
fde0: 8f0ae000 8f2ac800 8f21a000 8f21a050 80000013 8f2cbc00 8f2cba10 00000000
|
||
fe00: 60000093 801ebca0 8e6ffe18 000013ff 40000093 00000000 00944251 8f2ac800
|
||
fe20: a0000013 8f2b1320 00001986 00000000 00000001 000013ff 8f1e4f00 8f2cba10
|
||
fe40: 8e6fff6c 801e9044 00000003 00000000 fef98c80 002faf07 8e6ffe7c 00000000
|
||
fe60: 00000002 00000000 00001986 8f1f158d 8f1e4f00 80568de4 00000002 00000000
|
||
fe80: 00001986 8f1f53ff 40000001 80580500 8f1f158d 8001e00c 00000000 cfdfdfdf
|
||
fea0: fdae2a25 00000001 00000004 8e6fe000 00000008 00000010 00000000 00000005
|
||
fec0: 8f2b1330 8f2b1334 8e6ffe80 8e6ffe8c 00001986 00000000 8f21a014 00000001
|
||
fee0: 8e6ffe60 8e6ffe78 00000002 00000000 000013ff 00000001 80568de4 8f1e8018
|
||
ff00: 0000158d 8055ec30 00000001 803f6b00 00001986 8f2cba10 fdae2a25 00000001
|
||
ff20: 8f1baca8 8e6fff24 8e6fff24 00000000 8e6fff24 ac6f3037 00000000 00000000
|
||
ff40: 00000000 8e6fe000 8f1e4f40 00000000 8f1e4f40 8f1e4f00 801e84ec 00000000
|
||
ff60: 00000000 00000000 00000000 80031714 dfdfdfcf 00000000 dfdfdfcf 8f1e4f00
|
||
ff80: 00000000 8e6fff84 8e6fff84 00000000 8e6fff90 8e6fff90 8e6fffac 8f1e4f40
|
||
ffa0: 80031640 00000000 00000000 8000f548 00000000 00000000 00000000 00000000
|
||
ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||
ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 dfdfdfcf cfdfdfdf
|
||
[<801ea538>] (_setup_req) from [<801ebca0>] (pl330_tasklet+0x41c/0x490)
|
||
[<801ebca0>] (pl330_tasklet) from [<801e9044>] (dmatest_func+0xb58/0x149c)
|
||
[<801e9044>] (dmatest_func) from [<80031714>] (kthread+0xd4/0xec)
|
||
[<80031714>] (kthread) from [<8000f548>] (ret_from_fork+0x14/0x2c)
|
||
Code: e3a03001 e3e01043 e5c03001 e59d3048 (e5802002)
|
||
|
||
This happens because _emit_{ADDH,MOV,GO) accessing to unaligned data
|
||
while writing to buffer. Fix it with writing to buffer byte by byte.
|
||
|
||
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
|
||
Tested-by: Robin Murphy <robin.murphy@arm.com>
|
||
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit d07c9e1e212c9687f9198bfeba582e86cae3f6f9)
|
||
---
|
||
drivers/dma/pl330.c | 15 ++++++++++-----
|
||
1 file changed, 10 insertions(+), 5 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 497cc048feaa..eb274eeda0aa 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -573,7 +573,8 @@ static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
|
||
|
||
buf[0] = CMD_DMAADDH;
|
||
buf[0] |= (da << 1);
|
||
- *((__le16 *)&buf[1]) = cpu_to_le16(val);
|
||
+ buf[1] = val;
|
||
+ buf[2] = val >> 8;
|
||
|
||
PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
|
||
da == 1 ? "DA" : "SA", val);
|
||
@@ -727,7 +728,10 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
|
||
|
||
buf[0] = CMD_DMAMOV;
|
||
buf[1] = dst;
|
||
- *((__le32 *)&buf[2]) = cpu_to_le32(val);
|
||
+ buf[2] = val;
|
||
+ buf[3] = val >> 8;
|
||
+ buf[4] = val >> 16;
|
||
+ buf[5] = val >> 24;
|
||
|
||
PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
|
||
dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
|
||
@@ -902,10 +906,11 @@ static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
|
||
|
||
buf[0] = CMD_DMAGO;
|
||
buf[0] |= (ns << 1);
|
||
-
|
||
buf[1] = chan & 0x7;
|
||
-
|
||
- *((__le32 *)&buf[2]) = cpu_to_le32(addr);
|
||
+ buf[2] = addr;
|
||
+ buf[3] = addr >> 8;
|
||
+ buf[4] = addr >> 16;
|
||
+ buf[5] = addr >> 24;
|
||
|
||
return SZ_DMAGO;
|
||
}
|
||
|
||
From 50165cc7de07efd5986eeb604bbefe6328a142c4 Mon Sep 17 00:00:00 2001
|
||
From: Vinod Koul <vinod.koul@intel.com>
|
||
Date: Fri, 9 Dec 2016 15:24:12 +0530
|
||
Subject: [PATCH] =?UTF-8?q?UPSTREAM:=20dmaengine:=20pl330:=20remove=20unus?=
|
||
=?UTF-8?q?ed=20=E2=80=98regs=E2=80=99?=
|
||
MIME-Version: 1.0
|
||
Content-Type: text/plain; charset=UTF-8
|
||
Content-Transfer-Encoding: 8bit
|
||
|
||
In pl330_add(), variable ‘regs’ is initialized but never used, which
|
||
leads to warning with W=1.
|
||
|
||
drivers/dma/pl330.c: In function 'pl330_add':
|
||
drivers/dma/pl330.c:1891:16: warning: variable 'regs' set but not used [-Wunused-but-set-variable]
|
||
|
||
So remove it.
|
||
|
||
Cc: Linus Walleij <linus.walleij@linaro.org>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit 920e00d62ef9a818a4af7b2f9e1dbca23f846fc1)
|
||
---
|
||
drivers/dma/pl330.c | 3 ---
|
||
1 file changed, 3 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index eb274eeda0aa..14efb0e4a6a8 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1889,11 +1889,8 @@ static int dmac_alloc_resources(struct pl330_dmac *pl330)
|
||
|
||
static int pl330_add(struct pl330_dmac *pl330)
|
||
{
|
||
- void __iomem *regs;
|
||
int i, ret;
|
||
|
||
- regs = pl330->base;
|
||
-
|
||
/* Check if we can handle this DMAC */
|
||
if ((pl330->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
|
||
dev_err(pl330->ddma.dev, "PERIPH_ID 0x%x !\n",
|
||
|
||
From 9d2bcf1dd31ccb4cf3486deeda428b5e4211aff7 Mon Sep 17 00:00:00 2001
|
||
From: Marek Szyprowski <m.szyprowski@samsung.com>
|
||
Date: Mon, 27 Mar 2017 07:31:03 +0200
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: remove pdata based initialization
|
||
|
||
This driver is now used only on platforms which support device tree, so
|
||
it is safe to remove legacy platform data based initialization code.
|
||
|
||
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
|
||
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||
Acked-by: Arnd Bergmann <arnd@arndb.de>
|
||
For plat-samsung:
|
||
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit e8bb4673596ea28fab287dbc417e8100d798cd40)
|
||
---
|
||
arch/arm/plat-samsung/devs.c | 1 -
|
||
drivers/dma/pl330.c | 42 ++++++++----------------------------------
|
||
include/linux/amba/pl330.h | 35 -----------------------------------
|
||
3 files changed, 8 insertions(+), 70 deletions(-)
|
||
delete mode 100644 include/linux/amba/pl330.h
|
||
|
||
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
|
||
index e212f9d804bd..2ef19ad5cb62 100644
|
||
--- a/arch/arm/plat-samsung/devs.c
|
||
+++ b/arch/arm/plat-samsung/devs.c
|
||
@@ -10,7 +10,6 @@
|
||
* published by the Free Software Foundation.
|
||
*/
|
||
|
||
-#include <linux/amba/pl330.h>
|
||
#include <linux/kernel.h>
|
||
#include <linux/types.h>
|
||
#include <linux/interrupt.h>
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 14efb0e4a6a8..8d6c483663dc 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -22,7 +22,6 @@
|
||
#include <linux/dma-mapping.h>
|
||
#include <linux/dmaengine.h>
|
||
#include <linux/amba/bus.h>
|
||
-#include <linux/amba/pl330.h>
|
||
#include <linux/scatterlist.h>
|
||
#include <linux/of.h>
|
||
#include <linux/of_dma.h>
|
||
@@ -2084,18 +2083,6 @@ static void pl330_tasklet(unsigned long data)
|
||
}
|
||
}
|
||
|
||
-bool pl330_filter(struct dma_chan *chan, void *param)
|
||
-{
|
||
- u8 *peri_id;
|
||
-
|
||
- if (chan->device->dev->driver != &pl330_driver.drv)
|
||
- return false;
|
||
-
|
||
- peri_id = chan->private;
|
||
- return *peri_id == (unsigned long)param;
|
||
-}
|
||
-EXPORT_SYMBOL(pl330_filter);
|
||
-
|
||
static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
|
||
struct of_dma *ofdma)
|
||
{
|
||
@@ -2840,7 +2827,6 @@ static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume);
|
||
static int
|
||
pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
{
|
||
- struct dma_pl330_platdata *pdat;
|
||
struct pl330_config *pcfg;
|
||
struct pl330_dmac *pl330;
|
||
struct dma_pl330_chan *pch, *_p;
|
||
@@ -2850,8 +2836,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
int num_chan;
|
||
struct device_node *np = adev->dev.of_node;
|
||
|
||
- pdat = dev_get_platdata(&adev->dev);
|
||
-
|
||
ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
|
||
if (ret)
|
||
return ret;
|
||
@@ -2866,7 +2850,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
pd = &pl330->ddma;
|
||
pd->dev = &adev->dev;
|
||
|
||
- pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
|
||
+ pl330->mcbufsz = 0;
|
||
|
||
/* get quirk */
|
||
for (i = 0; i < ARRAY_SIZE(of_quirks); i++)
|
||
@@ -2910,10 +2894,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
INIT_LIST_HEAD(&pd->channels);
|
||
|
||
/* Initialize channel parameters */
|
||
- if (pdat)
|
||
- num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan);
|
||
- else
|
||
- num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan);
|
||
+ num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan);
|
||
|
||
pl330->num_peripherals = num_chan;
|
||
|
||
@@ -2926,11 +2907,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
|
||
for (i = 0; i < num_chan; i++) {
|
||
pch = &pl330->peripherals[i];
|
||
- if (!adev->dev.of_node)
|
||
- pch->chan.private = pdat ? &pdat->peri_id[i] : NULL;
|
||
- else
|
||
- pch->chan.private = adev->dev.of_node;
|
||
|
||
+ pch->chan.private = adev->dev.of_node;
|
||
INIT_LIST_HEAD(&pch->submitted_list);
|
||
INIT_LIST_HEAD(&pch->work_list);
|
||
INIT_LIST_HEAD(&pch->completed_list);
|
||
@@ -2943,15 +2921,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
list_add_tail(&pch->chan.device_node, &pd->channels);
|
||
}
|
||
|
||
- if (pdat) {
|
||
- pd->cap_mask = pdat->cap_mask;
|
||
- } else {
|
||
- dma_cap_set(DMA_MEMCPY, pd->cap_mask);
|
||
- if (pcfg->num_peri) {
|
||
- dma_cap_set(DMA_SLAVE, pd->cap_mask);
|
||
- dma_cap_set(DMA_CYCLIC, pd->cap_mask);
|
||
- dma_cap_set(DMA_PRIVATE, pd->cap_mask);
|
||
- }
|
||
+ dma_cap_set(DMA_MEMCPY, pd->cap_mask);
|
||
+ if (pcfg->num_peri) {
|
||
+ dma_cap_set(DMA_SLAVE, pd->cap_mask);
|
||
+ dma_cap_set(DMA_CYCLIC, pd->cap_mask);
|
||
+ dma_cap_set(DMA_PRIVATE, pd->cap_mask);
|
||
}
|
||
|
||
pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
|
||
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
|
||
deleted file mode 100644
|
||
index fe93758e8403..000000000000
|
||
--- a/include/linux/amba/pl330.h
|
||
+++ /dev/null
|
||
@@ -1,35 +0,0 @@
|
||
-/* linux/include/linux/amba/pl330.h
|
||
- *
|
||
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
|
||
- * Jaswinder Singh <jassi.brar@samsung.com>
|
||
- *
|
||
- * This program is free software; you can redistribute it and/or modify
|
||
- * it under the terms of the GNU General Public License as published by
|
||
- * the Free Software Foundation; either version 2 of the License, or
|
||
- * (at your option) any later version.
|
||
- */
|
||
-
|
||
-#ifndef __AMBA_PL330_H_
|
||
-#define __AMBA_PL330_H_
|
||
-
|
||
-#include <linux/dmaengine.h>
|
||
-
|
||
-struct dma_pl330_platdata {
|
||
- /*
|
||
- * Number of valid peripherals connected to DMAC.
|
||
- * This may be different from the value read from
|
||
- * CR0, as the PL330 implementation might have 'holes'
|
||
- * in the peri list or the peri could also be reached
|
||
- * from another DMAC which the platform prefers.
|
||
- */
|
||
- u8 nr_valid_peri;
|
||
- /* Array of valid peripherals */
|
||
- u8 *peri_id;
|
||
- /* Operational capabilities */
|
||
- dma_cap_mask_t cap_mask;
|
||
- /* Bytes to allocate for MC buffer */
|
||
- unsigned mcbuf_sz;
|
||
-};
|
||
-
|
||
-extern bool pl330_filter(struct dma_chan *chan, void *param);
|
||
-#endif /* __AMBA_PL330_H_ */
|
||
|
||
From 4ecadbeac3bbd8cd7e2377681b458a4036c33233 Mon Sep 17 00:00:00 2001
|
||
From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
|
||
Date: Thu, 1 Jun 2017 19:22:01 +0100
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix warning in pl330_remove
|
||
|
||
When removing a device with less than 9 IRQs (AMBA_NR_IRQS), we'll get a
|
||
big WARN_ON from devres.c because pl330_remove calls devm_free_irqs for
|
||
unallocated irqs. Similarly to pl330_probe, check that IRQ number is
|
||
present before calling devm_free_irq.
|
||
|
||
Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit ebcdaee4cebb3a8d0d702ab5e9392373672ec1de)
|
||
---
|
||
drivers/dma/pl330.c | 3 ++-
|
||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 8d6c483663dc..f6a4a89ae8aa 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -3018,7 +3018,8 @@ static int pl330_remove(struct amba_device *adev)
|
||
|
||
for (i = 0; i < AMBA_NR_IRQS; i++) {
|
||
irq = adev->irq[i];
|
||
- devm_free_irq(&adev->dev, irq, pl330);
|
||
+ if (irq)
|
||
+ devm_free_irq(&adev->dev, irq, pl330);
|
||
}
|
||
|
||
dma_async_device_unregister(&pl330->ddma);
|
||
|
||
From 062d0ddfbc9c08f971870e6ce8636a06b5b6d4d7 Mon Sep 17 00:00:00 2001
|
||
From: Matthias Kaehlcke <mka@chromium.org>
|
||
Date: Thu, 15 Jun 2017 16:55:57 -0700
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: Delete unused functions
|
||
|
||
The functions _queue_empty(), _emit_ADDH(), _emit_NOP(), _emit_STZ()
|
||
and _emit_WFE() are not used. Delete them.
|
||
|
||
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit d43674ecc002b49926f216cb414cff2d230ca3fb)
|
||
---
|
||
drivers/dma/pl330.c | 67 -----------------------------------------------------
|
||
1 file changed, 67 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index f6a4a89ae8aa..bd4a0c3deaf6 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -538,11 +538,6 @@ struct _xfer_spec {
|
||
struct dma_pl330_desc *desc;
|
||
};
|
||
|
||
-static inline bool _queue_empty(struct pl330_thread *thrd)
|
||
-{
|
||
- return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL;
|
||
-}
|
||
-
|
||
static inline bool _queue_full(struct pl330_thread *thrd)
|
||
{
|
||
return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL;
|
||
@@ -564,23 +559,6 @@ static inline u32 get_revision(u32 periph_id)
|
||
return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
|
||
}
|
||
|
||
-static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
|
||
- enum pl330_dst da, u16 val)
|
||
-{
|
||
- if (dry_run)
|
||
- return SZ_DMAADDH;
|
||
-
|
||
- buf[0] = CMD_DMAADDH;
|
||
- buf[0] |= (da << 1);
|
||
- buf[1] = val;
|
||
- buf[2] = val >> 8;
|
||
-
|
||
- PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
|
||
- da == 1 ? "DA" : "SA", val);
|
||
-
|
||
- return SZ_DMAADDH;
|
||
-}
|
||
-
|
||
static inline u32 _emit_END(unsigned dry_run, u8 buf[])
|
||
{
|
||
if (dry_run)
|
||
@@ -738,18 +716,6 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
|
||
return SZ_DMAMOV;
|
||
}
|
||
|
||
-static inline u32 _emit_NOP(unsigned dry_run, u8 buf[])
|
||
-{
|
||
- if (dry_run)
|
||
- return SZ_DMANOP;
|
||
-
|
||
- buf[0] = CMD_DMANOP;
|
||
-
|
||
- PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n");
|
||
-
|
||
- return SZ_DMANOP;
|
||
-}
|
||
-
|
||
static inline u32 _emit_RMB(unsigned dry_run, u8 buf[])
|
||
{
|
||
if (dry_run)
|
||
@@ -817,39 +783,6 @@ static inline u32 _emit_STP(unsigned dry_run, u8 buf[],
|
||
return SZ_DMASTP;
|
||
}
|
||
|
||
-static inline u32 _emit_STZ(unsigned dry_run, u8 buf[])
|
||
-{
|
||
- if (dry_run)
|
||
- return SZ_DMASTZ;
|
||
-
|
||
- buf[0] = CMD_DMASTZ;
|
||
-
|
||
- PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n");
|
||
-
|
||
- return SZ_DMASTZ;
|
||
-}
|
||
-
|
||
-static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev,
|
||
- unsigned invalidate)
|
||
-{
|
||
- if (dry_run)
|
||
- return SZ_DMAWFE;
|
||
-
|
||
- buf[0] = CMD_DMAWFE;
|
||
-
|
||
- ev &= 0x1f;
|
||
- ev <<= 3;
|
||
- buf[1] = ev;
|
||
-
|
||
- if (invalidate)
|
||
- buf[1] |= (1 << 1);
|
||
-
|
||
- PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n",
|
||
- ev >> 3, invalidate ? ", I" : "");
|
||
-
|
||
- return SZ_DMAWFE;
|
||
-}
|
||
-
|
||
static inline u32 _emit_WFP(unsigned dry_run, u8 buf[],
|
||
enum pl330_cond cond, u8 peri)
|
||
{
|
||
|
||
From 5d7da5fbd04fb60500162c823056b836c78ba397 Mon Sep 17 00:00:00 2001
|
||
From: Arvind Yadav <arvind.yadav.cs@gmail.com>
|
||
Date: Wed, 23 Aug 2017 21:57:31 +0530
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: constify amba_id
|
||
|
||
amba_id are not supposed to change at runtime. All functions
|
||
working with const amba_id. So mark the non-const structs as const.
|
||
|
||
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit b753351ec8f4c6a25c6d9b5c4eccce62e448a571)
|
||
---
|
||
drivers/dma/pl330.c | 2 +-
|
||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index bd4a0c3deaf6..63ffb8d1f885 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -2976,7 +2976,7 @@ static int pl330_remove(struct amba_device *adev)
|
||
return 0;
|
||
}
|
||
|
||
-static struct amba_id pl330_ids[] = {
|
||
+static const struct amba_id pl330_ids[] = {
|
||
{
|
||
.id = 0x00041330,
|
||
.mask = 0x000fffff,
|
||
|
||
From 79dd0f02e59662d1f1ce0b118280356ed9e63d65 Mon Sep 17 00:00:00 2001
|
||
From: Alexander Kochetkov <al.kochet@gmail.com>
|
||
Date: Wed, 4 Oct 2017 14:37:23 +0300
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix descriptor allocation fail
|
||
|
||
If two concurrent threads call pl330_get_desc() when DMAC descriptor
|
||
pool is empty it is possible that allocation for one of threads will fail
|
||
with message:
|
||
|
||
kernel: dma-pl330 20078000.dma-controller: pl330_get_desc:2469 ALERT!
|
||
|
||
Here how that can happen. Thread A calls pl330_get_desc() to get
|
||
descriptor. If DMAC descriptor pool is empty pl330_get_desc() allocates
|
||
new descriptor on shared pool using add_desc() and then get newly
|
||
allocated descriptor using pluck_desc(). At the same time thread B calls
|
||
pluck_desc() and take newly allocated descriptor. In that case descriptor
|
||
allocation for thread A will fail.
|
||
|
||
Using on-stack pool for new descriptor allow avoid the issue described.
|
||
The patch modify pl330_get_desc() to use on-stack pool for allocation
|
||
new descriptors.
|
||
|
||
Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
|
||
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
|
||
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
||
(cherry picked from commit e588710311ee5bece284871d613418831d56f2bd)
|
||
---
|
||
drivers/dma/pl330.c | 39 ++++++++++++++++++++-------------------
|
||
1 file changed, 20 insertions(+), 19 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 63ffb8d1f885..257492238cea 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -2344,7 +2344,8 @@ static inline void _init_desc(struct dma_pl330_desc *desc)
|
||
}
|
||
|
||
/* Returns the number of descriptors added to the DMAC pool */
|
||
-static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
|
||
+static int add_desc(struct list_head *pool, spinlock_t *lock,
|
||
+ gfp_t flg, int count)
|
||
{
|
||
struct dma_pl330_desc *desc;
|
||
unsigned long flags;
|
||
@@ -2354,27 +2355,28 @@ static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
|
||
if (!desc)
|
||
return 0;
|
||
|
||
- spin_lock_irqsave(&pl330->pool_lock, flags);
|
||
+ spin_lock_irqsave(lock, flags);
|
||
|
||
for (i = 0; i < count; i++) {
|
||
_init_desc(&desc[i]);
|
||
- list_add_tail(&desc[i].node, &pl330->desc_pool);
|
||
+ list_add_tail(&desc[i].node, pool);
|
||
}
|
||
|
||
- spin_unlock_irqrestore(&pl330->pool_lock, flags);
|
||
+ spin_unlock_irqrestore(lock, flags);
|
||
|
||
return count;
|
||
}
|
||
|
||
-static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
|
||
+static struct dma_pl330_desc *pluck_desc(struct list_head *pool,
|
||
+ spinlock_t *lock)
|
||
{
|
||
struct dma_pl330_desc *desc = NULL;
|
||
unsigned long flags;
|
||
|
||
- spin_lock_irqsave(&pl330->pool_lock, flags);
|
||
+ spin_lock_irqsave(lock, flags);
|
||
|
||
- if (!list_empty(&pl330->desc_pool)) {
|
||
- desc = list_entry(pl330->desc_pool.next,
|
||
+ if (!list_empty(pool)) {
|
||
+ desc = list_entry(pool->next,
|
||
struct dma_pl330_desc, node);
|
||
|
||
list_del_init(&desc->node);
|
||
@@ -2383,7 +2385,7 @@ static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
|
||
desc->txd.callback = NULL;
|
||
}
|
||
|
||
- spin_unlock_irqrestore(&pl330->pool_lock, flags);
|
||
+ spin_unlock_irqrestore(lock, flags);
|
||
|
||
return desc;
|
||
}
|
||
@@ -2395,20 +2397,18 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
|
||
struct dma_pl330_desc *desc;
|
||
|
||
/* Pluck one desc from the pool of DMAC */
|
||
- desc = pluck_desc(pl330);
|
||
+ desc = pluck_desc(&pl330->desc_pool, &pl330->pool_lock);
|
||
|
||
/* If the DMAC pool is empty, alloc new */
|
||
if (!desc) {
|
||
- if (!add_desc(pl330, GFP_ATOMIC, 1))
|
||
- return NULL;
|
||
+ DEFINE_SPINLOCK(lock);
|
||
+ LIST_HEAD(pool);
|
||
|
||
- /* Try again */
|
||
- desc = pluck_desc(pl330);
|
||
- if (!desc) {
|
||
- dev_err(pch->dmac->ddma.dev,
|
||
- "%s:%d ALERT!\n", __func__, __LINE__);
|
||
+ if (!add_desc(&pool, &lock, GFP_ATOMIC, 1))
|
||
return NULL;
|
||
- }
|
||
+
|
||
+ desc = pluck_desc(&pool, &lock);
|
||
+ WARN_ON(!desc || !list_empty(&pool));
|
||
}
|
||
|
||
/* Initialize the descriptor */
|
||
@@ -2821,7 +2821,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
spin_lock_init(&pl330->pool_lock);
|
||
|
||
/* Create a descriptor pool of default size */
|
||
- if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
|
||
+ if (!add_desc(&pl330->desc_pool, &pl330->pool_lock,
|
||
+ GFP_KERNEL, NR_DEFAULT_DESC))
|
||
dev_warn(&adev->dev, "unable to allocate desc\n");
|
||
|
||
INIT_LIST_HEAD(&pd->channels);
|
||
|
||
From a285cd8b8945bbe899f23e90c98d54249903e7bf Mon Sep 17 00:00:00 2001
|
||
From: Frank Mori Hess <fmh6jj@gmail.com>
|
||
Date: Wed, 18 Apr 2018 20:31:06 -0400
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: flush before wait, and add dev
|
||
burst support.
|
||
|
||
Do DMAFLUSHP _before_ the first DMAWFP to ensure controller
|
||
and peripheral are in agreement about dma request state before first
|
||
transfer. Add support for burst transfers to/from peripherals. In the new
|
||
scheme, the controller does as many burst transfers as it can then
|
||
transfers the remaining dregs with either single transfers for
|
||
peripherals, or with a reduced size burst for memory-to-memory transfers.
|
||
|
||
Signed-off-by: Frank Mori Hess <fmh6jj@gmail.com>
|
||
Tested-by: Frank Mori Hess <fmh6jj@gmail.com>
|
||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||
(cherry picked from commit 1d48745b192a7a45bbdd3557b4c039609569ca41)
|
||
---
|
||
drivers/dma/pl330.c | 209 +++++++++++++++++++++++++++++++++++++++-------------
|
||
1 file changed, 159 insertions(+), 50 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 257492238cea..fd48c031ead8 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -27,6 +27,7 @@
|
||
#include <linux/of_dma.h>
|
||
#include <linux/err.h>
|
||
#include <linux/pm_runtime.h>
|
||
+#include <linux/bug.h>
|
||
|
||
#include "dmaengine.h"
|
||
#define PL330_MAX_CHAN 8
|
||
@@ -1095,51 +1096,96 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
|
||
return off;
|
||
}
|
||
|
||
-static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
|
||
- u8 buf[], const struct _xfer_spec *pxs,
|
||
- int cyc)
|
||
+static u32 _emit_load(unsigned int dry_run, u8 buf[],
|
||
+ enum pl330_cond cond, enum dma_transfer_direction direction,
|
||
+ u8 peri)
|
||
{
|
||
int off = 0;
|
||
- enum pl330_cond cond;
|
||
|
||
- if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
|
||
- cond = BURST;
|
||
- else
|
||
- cond = SINGLE;
|
||
+ switch (direction) {
|
||
+ case DMA_MEM_TO_MEM:
|
||
+ /* fall through */
|
||
+ case DMA_MEM_TO_DEV:
|
||
+ off += _emit_LD(dry_run, &buf[off], cond);
|
||
+ break;
|
||
|
||
- while (cyc--) {
|
||
- off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
- off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
- off += _emit_ST(dry_run, &buf[off], ALWAYS);
|
||
+ case DMA_DEV_TO_MEM:
|
||
+ if (cond == ALWAYS) {
|
||
+ off += _emit_LDP(dry_run, &buf[off], SINGLE,
|
||
+ peri);
|
||
+ off += _emit_LDP(dry_run, &buf[off], BURST,
|
||
+ peri);
|
||
+ } else {
|
||
+ off += _emit_LDP(dry_run, &buf[off], cond,
|
||
+ peri);
|
||
+ }
|
||
+ break;
|
||
|
||
- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
- off += _emit_FLUSHP(dry_run, &buf[off],
|
||
- pxs->desc->peri);
|
||
+ default:
|
||
+ /* this code should be unreachable */
|
||
+ WARN_ON(1);
|
||
+ break;
|
||
}
|
||
|
||
return off;
|
||
}
|
||
|
||
-static inline int _ldst_memtodev(struct pl330_dmac *pl330,
|
||
+static inline u32 _emit_store(unsigned int dry_run, u8 buf[],
|
||
+ enum pl330_cond cond, enum dma_transfer_direction direction,
|
||
+ u8 peri)
|
||
+{
|
||
+ int off = 0;
|
||
+
|
||
+ switch (direction) {
|
||
+ case DMA_MEM_TO_MEM:
|
||
+ /* fall through */
|
||
+ case DMA_DEV_TO_MEM:
|
||
+ off += _emit_ST(dry_run, &buf[off], cond);
|
||
+ break;
|
||
+
|
||
+ case DMA_MEM_TO_DEV:
|
||
+ if (cond == ALWAYS) {
|
||
+ off += _emit_STP(dry_run, &buf[off], SINGLE,
|
||
+ peri);
|
||
+ off += _emit_STP(dry_run, &buf[off], BURST,
|
||
+ peri);
|
||
+ } else {
|
||
+ off += _emit_STP(dry_run, &buf[off], cond,
|
||
+ peri);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ /* this code should be unreachable */
|
||
+ WARN_ON(1);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return off;
|
||
+}
|
||
+
|
||
+static inline int _ldst_peripheral(struct pl330_dmac *pl330,
|
||
unsigned dry_run, u8 buf[],
|
||
- const struct _xfer_spec *pxs, int cyc)
|
||
+ const struct _xfer_spec *pxs, int cyc,
|
||
+ enum pl330_cond cond)
|
||
{
|
||
int off = 0;
|
||
- enum pl330_cond cond;
|
||
|
||
if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
|
||
cond = BURST;
|
||
- else
|
||
- cond = SINGLE;
|
||
|
||
+ /*
|
||
+ * do FLUSHP at beginning to clear any stale dma requests before the
|
||
+ * first WFP.
|
||
+ */
|
||
+ if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
+ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri);
|
||
while (cyc--) {
|
||
off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
- off += _emit_LD(dry_run, &buf[off], ALWAYS);
|
||
- off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri);
|
||
-
|
||
- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
|
||
- off += _emit_FLUSHP(dry_run, &buf[off],
|
||
- pxs->desc->peri);
|
||
+ off += _emit_load(dry_run, &buf[off], cond, pxs->desc->rqtype,
|
||
+ pxs->desc->peri);
|
||
+ off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype,
|
||
+ pxs->desc->peri);
|
||
}
|
||
|
||
return off;
|
||
@@ -1149,19 +1195,65 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
|
||
const struct _xfer_spec *pxs, int cyc)
|
||
{
|
||
int off = 0;
|
||
+ enum pl330_cond cond = BRST_LEN(pxs->ccr) > 1 ? BURST : SINGLE;
|
||
|
||
switch (pxs->desc->rqtype) {
|
||
case DMA_MEM_TO_DEV:
|
||
- off += _ldst_memtodev(pl330, dry_run, &buf[off], pxs, cyc);
|
||
- break;
|
||
+ /* fall through */
|
||
case DMA_DEV_TO_MEM:
|
||
- off += _ldst_devtomem(pl330, dry_run, &buf[off], pxs, cyc);
|
||
+ off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, cyc,
|
||
+ cond);
|
||
break;
|
||
+
|
||
case DMA_MEM_TO_MEM:
|
||
off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
|
||
break;
|
||
+
|
||
+ default:
|
||
+ /* this code should be unreachable */
|
||
+ WARN_ON(1);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return off;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * transfer dregs with single transfers to peripheral, or a reduced size burst
|
||
+ * for mem-to-mem.
|
||
+ */
|
||
+static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
|
||
+ const struct _xfer_spec *pxs, int transfer_length)
|
||
+{
|
||
+ int off = 0;
|
||
+ int dregs_ccr;
|
||
+
|
||
+ if (transfer_length == 0)
|
||
+ return off;
|
||
+
|
||
+ switch (pxs->desc->rqtype) {
|
||
+ case DMA_MEM_TO_DEV:
|
||
+ /* fall through */
|
||
+ case DMA_DEV_TO_MEM:
|
||
+ off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs,
|
||
+ transfer_length, SINGLE);
|
||
+ break;
|
||
+
|
||
+ case DMA_MEM_TO_MEM:
|
||
+ dregs_ccr = pxs->ccr;
|
||
+ dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) |
|
||
+ (0xf << CC_DSTBRSTLEN_SHFT));
|
||
+ dregs_ccr |= (((transfer_length - 1) & 0xf) <<
|
||
+ CC_SRCBRSTLEN_SHFT);
|
||
+ dregs_ccr |= (((transfer_length - 1) & 0xf) <<
|
||
+ CC_DSTBRSTLEN_SHFT);
|
||
+ off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr);
|
||
+ off += _ldst_memtomem(dry_run, &buf[off], pxs, 1);
|
||
+ break;
|
||
+
|
||
default:
|
||
- off += 0x40000000; /* Scare off the Client */
|
||
+ /* this code should be unreachable */
|
||
+ WARN_ON(1);
|
||
break;
|
||
}
|
||
|
||
@@ -1257,6 +1349,8 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||
struct pl330_xfer *x = &pxs->desc->px;
|
||
u32 ccr = pxs->ccr;
|
||
unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
|
||
+ int num_dregs = (x->bytes - BURST_TO_BYTE(bursts, ccr)) /
|
||
+ BRST_SIZE(ccr);
|
||
int off = 0;
|
||
|
||
while (bursts) {
|
||
@@ -1264,6 +1358,7 @@ static inline int _setup_loops(struct pl330_dmac *pl330,
|
||
off += _loop(pl330, dry_run, &buf[off], &c, pxs);
|
||
bursts -= c;
|
||
}
|
||
+ off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs);
|
||
|
||
return off;
|
||
}
|
||
@@ -1295,7 +1390,6 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
struct _xfer_spec *pxs)
|
||
{
|
||
struct _pl330_req *req = &thrd->req[index];
|
||
- struct pl330_xfer *x;
|
||
u8 *buf = req->mc_cpu;
|
||
int off = 0;
|
||
|
||
@@ -1304,11 +1398,6 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run,
|
||
/* DMAMOV CCR, ccr */
|
||
off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
|
||
|
||
- x = &pxs->desc->px;
|
||
- /* Error if xfer length is not aligned at burst size */
|
||
- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
|
||
- return -EINVAL;
|
||
-
|
||
off += _setup_xfer(pl330, dry_run, &buf[off], pxs);
|
||
|
||
/* DMASEV peripheral/event */
|
||
@@ -1366,6 +1455,20 @@ static int pl330_submit_req(struct pl330_thread *thrd,
|
||
u32 ccr;
|
||
int ret = 0;
|
||
|
||
+ switch (desc->rqtype) {
|
||
+ case DMA_MEM_TO_DEV:
|
||
+ break;
|
||
+
|
||
+ case DMA_DEV_TO_MEM:
|
||
+ break;
|
||
+
|
||
+ case DMA_MEM_TO_MEM:
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ return -ENOTSUPP;
|
||
+ }
|
||
+
|
||
if (pl330->state == DYING
|
||
|| pl330->dmac_tbd.reset_chan & (1 << thrd->id)) {
|
||
dev_info(thrd->dmac->ddma.dev, "%s:%d\n",
|
||
@@ -2060,6 +2163,18 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
|
||
return 1;
|
||
}
|
||
|
||
+static int fixup_burst_len(int max_burst_len, int quirks)
|
||
+{
|
||
+ if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
|
||
+ return 1;
|
||
+ else if (max_burst_len > PL330_MAX_BURST)
|
||
+ return PL330_MAX_BURST;
|
||
+ else if (max_burst_len < 1)
|
||
+ return 1;
|
||
+ else
|
||
+ return max_burst_len;
|
||
+}
|
||
+
|
||
static int pl330_config(struct dma_chan *chan,
|
||
struct dma_slave_config *slave_config)
|
||
{
|
||
@@ -2070,15 +2185,15 @@ static int pl330_config(struct dma_chan *chan,
|
||
pch->fifo_addr = slave_config->dst_addr;
|
||
if (slave_config->dst_addr_width)
|
||
pch->burst_sz = __ffs(slave_config->dst_addr_width);
|
||
- if (slave_config->dst_maxburst)
|
||
- pch->burst_len = slave_config->dst_maxburst;
|
||
+ pch->burst_len = fixup_burst_len(slave_config->dst_maxburst,
|
||
+ pch->dmac->quirks);
|
||
} else if (slave_config->direction == DMA_DEV_TO_MEM) {
|
||
if (slave_config->src_addr)
|
||
pch->fifo_addr = slave_config->src_addr;
|
||
if (slave_config->src_addr_width)
|
||
pch->burst_sz = __ffs(slave_config->src_addr_width);
|
||
- if (slave_config->src_maxburst)
|
||
- pch->burst_len = slave_config->src_maxburst;
|
||
+ pch->burst_len = fixup_burst_len(slave_config->src_maxburst,
|
||
+ pch->dmac->quirks);
|
||
}
|
||
|
||
return 0;
|
||
@@ -2471,14 +2586,8 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
|
||
burst_len >>= desc->rqcfg.brst_size;
|
||
|
||
/* src/dst_burst_len can't be more than 16 */
|
||
- if (burst_len > 16)
|
||
- burst_len = 16;
|
||
-
|
||
- while (burst_len > 1) {
|
||
- if (!(len % (burst_len << desc->rqcfg.brst_size)))
|
||
- break;
|
||
- burst_len--;
|
||
- }
|
||
+ if (burst_len > PL330_MAX_BURST)
|
||
+ burst_len = PL330_MAX_BURST;
|
||
|
||
return burst_len;
|
||
}
|
||
@@ -2547,7 +2656,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||
|
||
desc->rqtype = direction;
|
||
desc->rqcfg.brst_size = pch->burst_sz;
|
||
- desc->rqcfg.brst_len = 1;
|
||
+ desc->rqcfg.brst_len = pch->burst_len;
|
||
desc->bytes_requested = period_len;
|
||
fill_px(&desc->px, dst, src, period_len);
|
||
|
||
@@ -2692,7 +2801,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||
}
|
||
|
||
desc->rqcfg.brst_size = pch->burst_sz;
|
||
- desc->rqcfg.brst_len = 1;
|
||
+ desc->rqcfg.brst_len = pch->burst_len;
|
||
desc->rqtype = direction;
|
||
desc->bytes_requested = sg_dma_len(sg);
|
||
}
|
||
|
||
From 058373c4d717d3a353bca1345ea90f8ca6531136 Mon Sep 17 00:00:00 2001
|
||
From: Marek Szyprowski <m.szyprowski@samsung.com>
|
||
Date: Tue, 19 Jun 2018 15:20:50 +0200
|
||
Subject: [PATCH] UPSTREAM: dmaengine: pl330: report BURST residue granularity
|
||
|
||
The reported residue is already calculated in BURST unit granularity, so
|
||
advertise this capability properly to other devices in the system.
|
||
|
||
Fixes: aee4d1fac887 ("dmaengine: pl330: improve pl330_tx_status() function")
|
||
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
|
||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||
(cherry picked from commit e3f329c600033f011a978a8bc4ddb1e2e94c4f4d)
|
||
---
|
||
drivers/dma/pl330.c | 2 +-
|
||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index fd48c031ead8..029bd0444137 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -2984,7 +2984,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
||
pd->src_addr_widths = PL330_DMA_BUSWIDTHS;
|
||
pd->dst_addr_widths = PL330_DMA_BUSWIDTHS;
|
||
pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
|
||
- pd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
|
||
+ pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
|
||
pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ?
|
||
1 : PL330_MAX_BURST);
|
||
|
||
|
||
From 05fa0eafd6eda3e61ac5d4a9511eb4d1bb1924f9 Mon Sep 17 00:00:00 2001
|
||
From: Vinod Koul <vkoul@kernel.org>
|
||
Date: Mon, 9 Jul 2018 17:09:58 +0530
|
||
Subject: [PATCH] dmaengine: pl330: Mark expected switch fall-through
|
||
|
||
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
|
||
where we are expecting to fall through.
|
||
|
||
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
|
||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||
(cherry picked from commit bbcb87555869cb6c249bf00d13d3bc400c476c84)
|
||
---
|
||
drivers/dma/pl330.c | 3 +++
|
||
1 file changed, 3 insertions(+)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index 029bd0444137..c3bd238b0c22 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1047,13 +1047,16 @@ static bool _start(struct pl330_thread *thrd)
|
||
|
||
if (_state(thrd) == PL330_STATE_KILLING)
|
||
UNTIL(thrd, PL330_STATE_STOPPED)
|
||
+ /* fall through */
|
||
|
||
case PL330_STATE_FAULTING:
|
||
_stop(thrd);
|
||
+ /* fall through */
|
||
|
||
case PL330_STATE_KILLING:
|
||
case PL330_STATE_COMPLETING:
|
||
UNTIL(thrd, PL330_STATE_STOPPED)
|
||
+ /* fall through */
|
||
|
||
case PL330_STATE_STOPPED:
|
||
return _trigger(thrd);
|
||
|
||
From b654bf6ca9ee98bab1a3c55ebd359f251b9c1a61 Mon Sep 17 00:00:00 2001
|
||
From: Vinod Koul <vkoul@kernel.org>
|
||
Date: Mon, 9 Jul 2018 20:08:48 +0530
|
||
Subject: [PATCH] dmaengine: pl330: remove set but unused variable
|
||
MIME-Version: 1.0
|
||
Content-Type: text/plain; charset=UTF-8
|
||
Content-Transfer-Encoding: 8bit
|
||
|
||
Compiler complains (with W=1):
|
||
drivers/dma/pl330.c: In function ‘pl330_release_channel’:
|
||
drivers/dma/pl330.c:1782:21: warning:
|
||
variable ‘pl330’ set but not used [-Wunused-but-set-variable]
|
||
struct pl330_dmac *pl330;
|
||
^~~~~
|
||
|
||
Remove the pl330 variable in pl330_release_channel as it is set but
|
||
never used.
|
||
|
||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||
(cherry picked from commit 2f903bab92dea8dec8c93e4fa3c7c5295ef0a0fe)
|
||
---
|
||
drivers/dma/pl330.c | 4 ----
|
||
1 file changed, 4 deletions(-)
|
||
|
||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
|
||
index c3bd238b0c22..a25ab357b87c 100644
|
||
--- a/drivers/dma/pl330.c
|
||
+++ b/drivers/dma/pl330.c
|
||
@@ -1783,8 +1783,6 @@ static inline void _free_event(struct pl330_thread *thrd, int ev)
|
||
|
||
static void pl330_release_channel(struct pl330_thread *thrd)
|
||
{
|
||
- struct pl330_dmac *pl330;
|
||
-
|
||
if (!thrd || thrd->free)
|
||
return;
|
||
|
||
@@ -1793,8 +1791,6 @@ static void pl330_release_channel(struct pl330_thread *thrd)
|
||
dma_pl330_rqcb(thrd->req[1 - thrd->lstenq].desc, PL330_ERR_ABORT);
|
||
dma_pl330_rqcb(thrd->req[thrd->lstenq].desc, PL330_ERR_ABORT);
|
||
|
||
- pl330 = thrd->dmac;
|
||
-
|
||
_free_event(thrd, thrd->ev);
|
||
thrd->free = true;
|
||
}
|
||
|