From: Joel Fernandes <joelf@ti.com>
To: Tony Lindgren <tony@atomide.com>, Sekhar Nori <nsekhar@ti.com>,
Santosh Shilimkar <santosh.shilimkar@ti.com>,
Sricharan R <r.sricharan@ti.com>, Rajendra Nayak <rnayak@ti.com>,
Lokesh Vutla <lokeshvutla@ti.com>,
Matt Porter <matt@ohporter.com>,
Grant Likely <grant.likely@secretlab.ca>,
Rob Herring <rob.herring@calxeda.com>,
Vinod Koul <vinod.koul@intel.com>, Dan Williams <djbw@fb.com>,
Mark Brown <broonie@linaro.org>,
Benoit Cousson <benoit.cousson@linaro.org>,
Russell King <linux@arm.linux.org.uk>,
Arnd Bergmann <arnd@arndb.de>, Olof Johansson <olof@lixom.net>,
Balaji TK <balajitk@ti.com>,
Gururaja Hebbar <gururaja.hebbar@ti.com>,
Chris Ball <cjb@laptop.org>,
Jason Kridner <jkridner@beagleboard.org>
Cc: Linux OMAP List <linux-omap@vger.kernel.org>,
Linux ARM Kernel List <linux-arm-kernel@lists.infradead.org>,
Linux DaVinci Kernel List
<davinci-linux-open-source@linux.davincidsp.com>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Linux MMC List <linux-mmc@vger.kernel.org>,
Joel Fernandes <joelf@ti.com>
Subject: [PATCH v3 09/12] dma: edma: Implement multiple linked sets for continuity
Date: Mon, 5 Aug 2013 11:14:54 -0500 [thread overview]
Message-ID: <1375719297-12871-10-git-send-email-joelf@ti.com> (raw)
In-Reply-To: <1375719297-12871-1-git-send-email-joelf@ti.com>
Here we implement splitting up of the total MAX number of slots
available for a channel into 2 cyclically linked sets. Transfer
completion Interrupts are enabled on both linked sets and respective
handler recycles them on completion to process the next linked set.
Both linked sets are cyclically linked to each other to ensure
continuity of DMA operations. Interrupt handlers execute asynchronously
to the EDMA events and recycles the linked sets at the right time,
as a result EDMA is not blocked or dependent on interrupts and DMA
continues till the end of the SG-lists without any interruption.
Suggested-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Joel Fernandes <joelf@ti.com>
---
drivers/dma/edma.c | 157 +++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 118 insertions(+), 39 deletions(-)
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index df50a04..70923a2 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -48,6 +48,7 @@
/* Max of 16 segments per channel to conserve PaRAM slots */
#define MAX_NR_SG 16
+#define MAX_NR_LS (MAX_NR_SG >> 1)
#define EDMA_MAX_SLOTS (MAX_NR_SG+1)
#define EDMA_DESCRIPTORS 16
@@ -57,6 +58,7 @@ struct edma_desc {
int absync;
int pset_nr;
int total_processed;
+ int next_setup_linkset;
struct edmacc_param pset[0];
};
@@ -140,7 +142,9 @@ static void edma_execute(struct edma_chan *echan)
struct edma_desc *edesc;
struct device *dev = echan->vchan.chan.device->dev;
- int i, j, total_left, total_process;
+ int i, total_left, total_link_set;
+ int ls_cur_off, ls_next_off, slot_off;
+ struct edmacc_param tmp_param;
/* If either we processed all psets or we're still not started */
if (!echan->edesc ||
@@ -159,48 +163,121 @@ static void edma_execute(struct edma_chan *echan)
/* Find out how many left */
total_left = edesc->pset_nr - edesc->total_processed;
- total_process = total_left > MAX_NR_SG ? MAX_NR_SG : total_left;
-
-
- /* Write descriptor PaRAM set(s) */
- for (i = 0; i < total_process; i++) {
- j = i + edesc->total_processed;
- edma_write_slot(echan->slot[i], &edesc->pset[j]);
- dev_dbg(echan->vchan.chan.device->dev,
- "\n pset[%d]:\n"
- " chnum\t%d\n"
- " slot\t%d\n"
- " opt\t%08x\n"
- " src\t%08x\n"
- " dst\t%08x\n"
- " abcnt\t%08x\n"
- " ccnt\t%08x\n"
- " bidx\t%08x\n"
- " cidx\t%08x\n"
- " lkrld\t%08x\n",
- j, echan->ch_num, echan->slot[i],
- edesc->pset[j].opt,
- edesc->pset[j].src,
- edesc->pset[j].dst,
- edesc->pset[j].a_b_cnt,
- edesc->pset[j].ccnt,
- edesc->pset[j].src_dst_bidx,
- edesc->pset[j].src_dst_cidx,
- edesc->pset[j].link_bcntrld);
- /* Link to the previous slot if not the last set */
- if (i != (total_process - 1))
+ total_link_set = total_left > MAX_NR_LS ? MAX_NR_LS : total_left;
+
+ /* First time, setup 2 cyclically linked sets, each containing half
+ the slots allocated for this channel */
+ if (edesc->total_processed == 0) {
+ for (i = 0; i < total_link_set; i++) {
+ edma_write_slot(echan->slot[i+1], &edesc->pset[i]);
+
+ if (i != total_link_set - 1) {
+ edma_link(echan->slot[i+1], echan->slot[i+2]);
+ dump_pset(echan, echan->slot[i+1],
+ edesc->pset, i);
+ }
+ }
+
+ edesc->total_processed += total_link_set;
+
+ total_left = edesc->pset_nr - edesc->total_processed;
+
+ total_link_set = total_left > MAX_NR_LS ?
+ MAX_NR_LS : total_left;
+
+ if (total_link_set) {
+ /* Don't setup interrupt for first linked set for cases
+ where total pset_nr is strictly within MAX_NR size */
+ if (total_left > total_link_set)
+ edma_enable_interrupt(echan->slot[i]);
+
+ /* Setup link between linked set 0 to set 1 */
edma_link(echan->slot[i], echan->slot[i+1]);
- /* Final pset links to the dummy pset */
- else
+
+ dump_pset(echan, echan->slot[i], edesc->pset, i-1);
+
+ /* Write out linked set 1 */
+ for (; i < total_link_set + MAX_NR_LS; i++) {
+ edma_write_slot(echan->slot[i+1],
+ &edesc->pset[i]);
+
+ if (i != total_link_set + MAX_NR_LS - 1) {
+ edma_link(echan->slot[i+1],
+ echan->slot[i+2]);
+ dump_pset(echan, echan->slot[i+1],
+ edesc->pset, i);
+ }
+ }
+
+ edesc->total_processed += total_link_set;
+ total_left = edesc->pset_nr - edesc->total_processed;
+
+ if (total_left)
+ /* Setup a link from linked set 1 to set 0 */
+ edma_link(echan->slot[i], echan->slot[1]);
+ else
+ /* Setup a link between linked set 1 to dummy */
+ edma_link(echan->slot[i], echan->ecc->dummy_slot);
+ } else {
+ /* First linked set was enough, simply link to dummy */
edma_link(echan->slot[i], echan->ecc->dummy_slot);
- }
+ }
+
+ edma_enable_interrupt(echan->slot[i]);
+ dump_pset(echan, echan->slot[i], edesc->pset, i-1);
- edesc->total_processed += total_process;
+ edesc->next_setup_linkset = 0;
- if (edesc->total_processed <= MAX_NR_SG) {
+ /* Start the ball rolling... */
dev_dbg(dev, "first transfer starting %d\n", echan->ch_num);
+
+ edma_read_slot(echan->slot[1], &tmp_param);
+ edma_write_slot(echan->slot[0], &tmp_param);
edma_start(echan->ch_num);
+
+ return;
+ }
+
+ /* We got called in the middle of an SG-list transaction as one of the
+ linked sets completed */
+
+ /* Setup offsets into echan_slot, +1 is as slot 0 is for chan */
+ if (edesc->next_setup_linkset == 1) {
+ edesc->next_setup_linkset = 0;
+ ls_cur_off = MAX_NR_LS + 1;
+ ls_next_off = 1;
+ } else {
+ edesc->next_setup_linkset = 1;
+ ls_cur_off = 1;
+ ls_next_off = MAX_NR_LS + 1;
+ }
+
+ for (i = 0; i < total_link_set; i++) {
+ edma_write_slot(echan->slot[i + ls_cur_off],
+ &edesc->pset[i + edesc->total_processed]);
+
+ if (i != total_link_set - 1) {
+ edma_link(echan->slot[i + ls_cur_off],
+ echan->slot[i + ls_cur_off + 1]);
+
+ dump_pset(echan, echan->slot[i + ls_cur_off],
+ edesc->pset, i + edesc->total_processed);
+ }
}
+
+ edesc->total_processed += total_link_set;
+
+ slot_off = total_link_set + ls_cur_off - 1;
+
+ if (edesc->total_processed == edesc->pset_nr)
+ edma_link(echan->slot[slot_off], echan->ecc->dummy_slot);
+ else
+ edma_link(echan->slot[slot_off], echan->slot[ls_next_off]);
+
+ edma_enable_interrupt(echan->slot[slot_off]);
+
+ dump_pset(echan, echan->slot[slot_off],
+ edesc->pset, edesc->total_processed-1);
}
static int edma_terminate_all(struct edma_chan *echan)
@@ -417,15 +494,17 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
spin_lock_irqsave(&echan->vchan.lock, flags);
edesc = echan->edesc;
+
if (edesc) {
if (edesc->total_processed == edesc->pset_nr) {
- dev_dbg(dev, "transfer complete." \
+ dev_dbg(dev, "Transfer complete,"
" stopping channel %d\n", ch_num);
edma_stop(echan->ch_num);
vchan_cookie_complete(&edesc->vdesc);
} else {
- dev_dbg(dev, "Intermediate transfer complete" \
- " on channel %d\n", ch_num);
+ dev_dbg(dev, "Intermediate transfer "
+ "complete, setup next linked set on "
+ "%d\n ", ch_num);
}
edma_execute(echan);
--
1.7.9.5
next prev parent reply other threads:[~2013-08-05 16:14 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-05 16:14 [PATCH v3 00/12] edma: Add support for SG lists of any length Joel Fernandes
[not found] ` <1375719297-12871-1-git-send-email-joelf-l0cyMroinI0@public.gmane.org>
2013-08-05 16:14 ` [PATCH v3 01/12] dma: edma: Setup parameters to DMA MAX_NR_SG at a time Joel Fernandes
[not found] ` <1375719297-12871-2-git-send-email-joelf-l0cyMroinI0@public.gmane.org>
2013-08-12 7:15 ` Sekhar Nori
[not found] ` <52088B8B.9040000-l0cyMroinI0@public.gmane.org>
2013-08-12 23:55 ` Joel Fernandes
[not found] ` <52097604.7010503-l0cyMroinI0@public.gmane.org>
2013-08-13 0:19 ` Joel Fernandes
2013-08-13 0:05 ` Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 02/12] ARM: edma: Don't clear EMR of channel in edma_stop Joel Fernandes
[not found] ` <1375719297-12871-3-git-send-email-joelf-l0cyMroinI0@public.gmane.org>
2013-08-08 11:49 ` Sekhar Nori
[not found] ` <520385D3.1060408-l0cyMroinI0@public.gmane.org>
2013-08-12 4:25 ` Sekhar Nori
2013-08-12 4:29 ` Joel Fernandes
2013-08-12 6:24 ` Sekhar Nori
2013-08-16 5:57 ` [PATCH v3 00/12] edma: Add support for SG lists of any length Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 03/12] dma: edma: remove limits on number of slots Joel Fernandes
[not found] ` <1375719297-12871-4-git-send-email-joelf-l0cyMroinI0@public.gmane.org>
2013-08-12 7:17 ` Sekhar Nori
2013-08-05 16:14 ` [PATCH v3 04/12] dma: edma: Write out and handle MAX_NR_SG at a given time Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 05/12] ARM: edma: Add function to enable interrupt for a PaRAM slot Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 06/12] ARM: edma: Add pr_debug in edma_link Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 07/12] dma: edma: Add function to dump a PaRAM set from PaRAM Joel Fernandes
[not found] ` <1375719297-12871-8-git-send-email-joelf-l0cyMroinI0@public.gmane.org>
2013-08-12 5:52 ` Sekhar Nori
[not found] ` <52087824.60002-l0cyMroinI0@public.gmane.org>
2013-08-13 1:06 ` Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 08/12] dma: edma: Add one more required slot to MAX slots Joel Fernandes
2013-08-12 5:56 ` Sekhar Nori
2013-08-12 13:31 ` Mark Brown
[not found] ` <20130812133111.GZ6427-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-08-12 18:19 ` Joel Fernandes
[not found] ` <52087921.8040101-l0cyMroinI0@public.gmane.org>
2013-08-13 1:08 ` Joel Fernandes
2013-08-05 16:14 ` Joel Fernandes [this message]
[not found] ` <1375719297-12871-10-git-send-email-joelf-l0cyMroinI0@public.gmane.org>
2013-08-12 18:56 ` [PATCH v3 09/12] dma: edma: Implement multiple linked sets for continuity Sekhar Nori
[not found] ` <52092FF7.7040508-l0cyMroinI0@public.gmane.org>
2013-08-13 1:00 ` Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 10/12] dma: edma: Check if MAX_NR_SG is even in prep function Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 11/12] dma: edma: Keep tracking of Pending interrupts (pending_acks) Joel Fernandes
2013-08-05 16:14 ` [PATCH v3 12/12] dma: edma: Return if nothing left todo in edma_execute Joel Fernandes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1375719297-12871-10-git-send-email-joelf@ti.com \
--to=joelf@ti.com \
--cc=arnd@arndb.de \
--cc=balajitk@ti.com \
--cc=benoit.cousson@linaro.org \
--cc=broonie@linaro.org \
--cc=cjb@laptop.org \
--cc=davinci-linux-open-source@linux.davincidsp.com \
--cc=djbw@fb.com \
--cc=grant.likely@secretlab.ca \
--cc=gururaja.hebbar@ti.com \
--cc=jkridner@beagleboard.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mmc@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=lokeshvutla@ti.com \
--cc=matt@ohporter.com \
--cc=nsekhar@ti.com \
--cc=olof@lixom.net \
--cc=r.sricharan@ti.com \
--cc=rnayak@ti.com \
--cc=rob.herring@calxeda.com \
--cc=santosh.shilimkar@ti.com \
--cc=tony@atomide.com \
--cc=vinod.koul@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).