From patchwork Thu Apr 17 14:40:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 4009101 X-Patchwork-Delegate: vinod.koul@intel.com Return-Path: X-Original-To: patchwork-dmaengine@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A342BBFF02 for ; Thu, 17 Apr 2014 14:40:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C9ACC20395 for ; Thu, 17 Apr 2014 14:40:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0BA8520397 for ; Thu, 17 Apr 2014 14:40:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751180AbaDQOke (ORCPT ); Thu, 17 Apr 2014 10:40:34 -0400 Received: from www.linutronix.de ([62.245.132.108]:49289 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751029AbaDQOkd (ORCPT ); Thu, 17 Apr 2014 10:40:33 -0400 Received: from localhost ([127.0.0.1] helo=ionos.tec.linutronix.de) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1WanUO-0004kL-9S; Thu, 17 Apr 2014 16:40:32 +0200 Message-Id: <20140417143249.889774979@linutronix.de> User-Agent: quilt/0.60-1 Date: Thu, 17 Apr 2014 14:40:46 -0000 From: Thomas Gleixner To: dmaengine@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, dan.j.williams@intel.com, vinod.koul@intel.com, nsekhar@ti.com, joelf@ti.com, Peter Ujfalusi Subject: [patch 5/6] edma: Make reading the position of active channels work References: <20140417133737.892475126@linutronix.de> Content-Disposition: inline; filename=arm-edma-make-read-position-useful.patch X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1, SHORTCIRCUIT=-0.0001 Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Reading destination and source is pointless. In DEV_TO_MEM transfers we are only interested in the destination, in MEM_TO_DEV we care about the source. In MEM_TO_MEM it really does not matter which one you read. Remove the extra pointer and select dest/source via a bool. Reading the src/dst data from an active parameter set in the EDMA parameter RAM is not reliable, as there might be a concurrent update from the controller. But experimentation showed, that a double readout with comparing the results and a limited loop works nicely. I've actually never found a case where the loop limit triggered, but we have it there for sanity reasons. In case it triggers we return -EBUSY and let the caller deal with it. Remove the export of this function while at it. The only potential user is the dmaengine and that's always builtin. Signed-off-by: Thomas Gleixner --- arch/arm/common/edma.c | 48 ++++++++++++++++++++++++++----------- include/linux/platform_data/edma.h | 2 - 2 files changed, 35 insertions(+), 15 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: linux/arch/arm/common/edma.c =================================================================== --- linux.orig/arch/arm/common/edma.c +++ linux/arch/arm/common/edma.c @@ -994,29 +994,49 @@ void edma_set_dest(unsigned slot, dma_ad EXPORT_SYMBOL(edma_set_dest); /** - * edma_get_position - returns the current transfer points + * edma_get_position - returns the current transfer point * @slot: parameter RAM slot being examined - * @src: pointer to source port position - * @dst: pointer to destination port position + * @pos: where to store the data + * @dst: true selects the dest position, false the source * - * Returns current source and destination addresses for a particular - * parameter RAM slot. Its channel should not be active when this is called. + * Return 0 indicates a stable readout. -EBUSY indicates that the + * readout failed due to concurrent updates. + * + * Call this on active channels with care. For inactive channels this + * never fails. */ -void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst) +int edma_get_position(unsigned slot, dma_addr_t *pos, bool dst) { - struct edmacc_param temp; - unsigned ctlr; + u32 dat, ctlr, offs; + int i; ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp); - if (src != NULL) - *src = temp.src; - if (dst != NULL) - *dst = temp.dst; + if (slot >= edma_cc[ctlr]->num_slots) + return -EINVAL; + + offs = PARM_OFFSET(slot); + offs += dst ? PARM_DST : PARM_SRC; + + /* + * If the channel is active, we need to double read as we + * might see half updated data. We limit this to 5 + * attempts. If that fails we return -EBUSY and let the caller + * deal with it. + */ + dat = edma_read(ctlr, offs); + for (i = 0; i < 5; i++) { + u32 tmp = edma_read(ctlr, offs); + + if (tmp == dat) { + *pos = dat; + return 0; + } + dat = tmp; + } + return -EBUSY; } -EXPORT_SYMBOL(edma_get_position); /** * edma_set_src_index - configure DMA source address indexing Index: linux/include/linux/platform_data/edma.h =================================================================== --- linux.orig/include/linux/platform_data/edma.h +++ linux/include/linux/platform_data/edma.h @@ -130,7 +130,7 @@ void edma_set_src(unsigned slot, dma_add 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); -void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst); +int __must_check edma_get_position(unsigned slot, dma_addr_t *pos, 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); void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,