From: John Ogness <john.ogness@linutronix.de> To: linux-kernel@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: dmaengine@vger.kernel.org Subject: [PATCH] ARM: edma: fix residue race for cyclic Date: Thu, 15 Oct 2015 12:46:26 +0200 [thread overview] Message-ID: <87io68s931.fsf@linutronix.de> (raw) When retrieving the residue value for cyclic transfers, the DST field of the active PaRAM is read. However, the AM335x Technical Reference Manual states: 11.3.3.6 Parameter Set Updates After the TR is read from the PaRAM (and is in the process of being submitted to the EDMA3TC), the following fields are updated as needed: ... DST This means the DST is incremented even though the DMA transfer may not have started yet or is in progress. Thus if the reader of the residue accesses the DMA buffer too quickly, the CPU will read where data is not yet written. The CCSTAT.ACTV register is a boolean that is set if any TR is being processed by either the EMDA3CC or EDMA3TC. By polling this register it is possible to ensure that the residue value returned is valid for immediate processing. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- arch/arm/common/edma.c | 17 +++++++++++++++++ drivers/dma/edma.c | 8 ++++++++ include/linux/platform_data/edma.h | 1 + 3 files changed, 26 insertions(+) diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c index 873dbfc..86ce980 100644 --- a/arch/arm/common/edma.c +++ b/arch/arm/common/edma.c @@ -995,6 +995,23 @@ void edma_set_dest(unsigned slot, dma_addr_t dest_port, } EXPORT_SYMBOL(edma_set_dest); +#define EDMA_CCSTAT_ACTV (1 << 4) + +/** + * edma_is_actv - report if any transfer requests are active + * @slot: parameter RAM slot being examined + * + * Returns true if any transfer requests are active on the slot + */ +bool edma_is_actv(unsigned slot) +{ + u32 ctlr = EDMA_CTLR(slot); + unsigned int ccstat; + + ccstat = edma_read(ctlr, EDMA_CCSTAT); + return (ccstat & EDMA_CCSTAT_ACTV); +} + /** * edma_get_position - returns the current transfer point * @slot: parameter RAM slot being examined diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 3e5d4f1..493c774 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -891,6 +891,14 @@ static u32 edma_residue(struct edma_desc *edesc) pos = edma_get_position(edesc->echan->slot[0], dst); /* + * "pos" may represent a transfer request that is still being + * processed by the EDMACC or EDMATC. Wait until all transfer + * requests on the active slot are finished before proceeding. + */ + while (edma_is_actv(edesc->echan->slot[0])) + cpu_relax(); + + /* * Cyclic is simple. Just subtract pset[0].addr from pos. * * We never update edesc->residue in the cyclic case, so we diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h index bdb2710..20c50e2 100644 --- a/include/linux/platform_data/edma.h +++ b/include/linux/platform_data/edma.h @@ -130,6 +130,7 @@ void edma_set_src(unsigned slot, dma_addr_t src_port, enum address_mode mode, enum fifo_width); void edma_set_dest(unsigned slot, dma_addr_t dest_port, enum address_mode mode, enum fifo_width); +bool edma_is_actv(unsigned slot); dma_addr_t edma_get_position(unsigned slot, bool dst); void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx); void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx); -- 1.7.10.4
WARNING: multiple messages have this Message-ID (diff)
From: john.ogness@linutronix.de (John Ogness) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] ARM: edma: fix residue race for cyclic Date: Thu, 15 Oct 2015 12:46:26 +0200 [thread overview] Message-ID: <87io68s931.fsf@linutronix.de> (raw) When retrieving the residue value for cyclic transfers, the DST field of the active PaRAM is read. However, the AM335x Technical Reference Manual states: 11.3.3.6 Parameter Set Updates After the TR is read from the PaRAM (and is in the process of being submitted to the EDMA3TC), the following fields are updated as needed: ... DST This means the DST is incremented even though the DMA transfer may not have started yet or is in progress. Thus if the reader of the residue accesses the DMA buffer too quickly, the CPU will read where data is not yet written. The CCSTAT.ACTV register is a boolean that is set if any TR is being processed by either the EMDA3CC or EDMA3TC. By polling this register it is possible to ensure that the residue value returned is valid for immediate processing. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- arch/arm/common/edma.c | 17 +++++++++++++++++ drivers/dma/edma.c | 8 ++++++++ include/linux/platform_data/edma.h | 1 + 3 files changed, 26 insertions(+) diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c index 873dbfc..86ce980 100644 --- a/arch/arm/common/edma.c +++ b/arch/arm/common/edma.c @@ -995,6 +995,23 @@ void edma_set_dest(unsigned slot, dma_addr_t dest_port, } EXPORT_SYMBOL(edma_set_dest); +#define EDMA_CCSTAT_ACTV (1 << 4) + +/** + * edma_is_actv - report if any transfer requests are active + * @slot: parameter RAM slot being examined + * + * Returns true if any transfer requests are active on the slot + */ +bool edma_is_actv(unsigned slot) +{ + u32 ctlr = EDMA_CTLR(slot); + unsigned int ccstat; + + ccstat = edma_read(ctlr, EDMA_CCSTAT); + return (ccstat & EDMA_CCSTAT_ACTV); +} + /** * edma_get_position - returns the current transfer point * @slot: parameter RAM slot being examined diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 3e5d4f1..493c774 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -891,6 +891,14 @@ static u32 edma_residue(struct edma_desc *edesc) pos = edma_get_position(edesc->echan->slot[0], dst); /* + * "pos" may represent a transfer request that is still being + * processed by the EDMACC or EDMATC. Wait until all transfer + * requests on the active slot are finished before proceeding. + */ + while (edma_is_actv(edesc->echan->slot[0])) + cpu_relax(); + + /* * Cyclic is simple. Just subtract pset[0].addr from pos. * * We never update edesc->residue in the cyclic case, so we diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h index bdb2710..20c50e2 100644 --- a/include/linux/platform_data/edma.h +++ b/include/linux/platform_data/edma.h @@ -130,6 +130,7 @@ void edma_set_src(unsigned slot, dma_addr_t src_port, enum address_mode mode, enum fifo_width); void edma_set_dest(unsigned slot, dma_addr_t dest_port, enum address_mode mode, enum fifo_width); +bool edma_is_actv(unsigned slot); dma_addr_t edma_get_position(unsigned slot, bool dst); void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx); void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx); -- 1.7.10.4
next reply other threads:[~2015-10-15 10:46 UTC|newest] Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-10-15 10:46 John Ogness [this message] 2015-10-15 10:46 ` [PATCH] ARM: edma: fix residue race for cyclic John Ogness 2015-10-15 10:55 ` Peter Ujfalusi 2015-10-15 10:55 ` Peter Ujfalusi 2015-10-16 10:26 ` [PATCH v2] " John Ogness 2015-10-16 10:26 ` John Ogness 2015-10-16 11:46 ` Peter Ujfalusi 2015-10-16 11:46 ` Peter Ujfalusi 2015-10-16 12:28 ` John Ogness 2015-10-16 12:28 ` John Ogness 2015-10-16 13:46 ` Peter Ujfalusi 2015-10-16 13:46 ` Peter Ujfalusi 2015-10-16 13:58 ` Peter Ujfalusi 2015-10-16 13:58 ` Peter Ujfalusi
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=87io68s931.fsf@linutronix.de \ --to=john.ogness@linutronix.de \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.