From patchwork Mon Nov 5 23:04:01 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Warren X-Patchwork-Id: 197358 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3B4372C04E2 for ; Tue, 6 Nov 2012 10:04:41 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 628EA4A44A; Tue, 6 Nov 2012 00:04:37 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id sKrDNTx7Gaeg; Tue, 6 Nov 2012 00:04:37 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 014704A44B; Tue, 6 Nov 2012 00:04:28 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A6F824A43F for ; Tue, 6 Nov 2012 00:04:24 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aX23iBAhC2ue for ; Tue, 6 Nov 2012 00:04:22 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from avon.wwwdotorg.org (avon.wwwdotorg.org [70.85.31.133]) by theia.denx.de (Postfix) with ESMTPS id 79F9E4A441 for ; Tue, 6 Nov 2012 00:04:21 +0100 (CET) Received: from severn.wwwdotorg.org (unknown [192.168.65.5]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by avon.wwwdotorg.org (Postfix) with ESMTPS id 56AE56234; Mon, 5 Nov 2012 16:05:06 -0700 (MST) Received: from localhost.localdomain (localhost [127.0.0.1]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by severn.wwwdotorg.org (Postfix) with ESMTPSA id 3A87CE4622; Mon, 5 Nov 2012 16:04:18 -0700 (MST) From: Stephen Warren To: u-boot@lists.denx.de, Tom Rini Date: Mon, 5 Nov 2012 16:04:01 -0700 Message-Id: <1352156642-7975-2-git-send-email-swarren@wwwdotorg.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1352156642-7975-1-git-send-email-swarren@wwwdotorg.org> References: <1352156642-7975-1-git-send-email-swarren@wwwdotorg.org> X-NVConfidentiality: public X-Virus-Scanned: clamav-milter 0.96.5 at avon.wwwdotorg.org X-Virus-Status: Clean Cc: Andy Fleming , Stephen Warren , Tom Warren Subject: [U-Boot] [PATCH 2/3] common: rework bouncebuf implementation X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Stephen Warren The current bouncebuf API requires all parameters to be passed to both bounce_buffer_start() and bounce_buffer_stop(). This works fine when both functions are called from the same place. However, Tegra's MMC driver splits the data setup and post-processing steps between two functions, and passing all that state around separately would be painful. Modify the bouncebuf API to accept a state structure as a parameter, so that only a single struct needs to be passed to both APIs. Also, don't modify the data pointer, but rather store the temporary buffer in this state struct. This also avoids passing the buffer pointer all over the place. The bouncebuf code ensures that client code can always use a single buffer pointer in the state structure, irrespective of whether a bounce buffer actually had to be allocated. Finally, store the aligned/rounded length in the state structure too, so that client code doesn't need to duplicate the size alignment/rounding code, and hence have to guess at the value it was aligned/rounded to. Update the MXS MMC driver for this change. Signed-off-by: Stephen Warren --- common/bouncebuf.c | 41 ++++++++++++++++------------------------- drivers/mmc/mxsmmc.c | 25 ++++++++++++++----------- include/bouncebuf.h | 36 +++++++++++++++++++++++------------- 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/common/bouncebuf.c b/common/bouncebuf.c index ffd3c90..210d70d 100644 --- a/common/bouncebuf.c +++ b/common/bouncebuf.c @@ -50,44 +50,35 @@ static int addr_aligned(void *data, size_t len) return 1; } -int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags) +int bounce_buffer_start(struct bounce_buffer_state *state, void *data, + size_t len, uint8_t flags) { - void *tmp; - size_t alen; + state->user_buffer = data; + state->bounce_buffer = data; + state->len = len; + state->len_aligned = roundup(len, ARCH_DMA_MINALIGN); + state->flags = flags; - if (addr_aligned(*data, len)) { - *backup = NULL; + if (addr_aligned(data, len)) return 0; - } - - alen = roundup(len, ARCH_DMA_MINALIGN); - tmp = memalign(ARCH_DMA_MINALIGN, alen); - if (!tmp) + state->bounce_buffer = memalign(ARCH_DMA_MINALIGN, state->len_aligned); + if (!state->bounce_buffer) return -ENOMEM; - if (flags & GEN_BB_READ) - memcpy(tmp, *data, len); - - *backup = *data; - *data = tmp; + if (state->flags & GEN_BB_READ) + memcpy(state->bounce_buffer, state->user_buffer, state->len); return 0; } -int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags) +int bounce_buffer_stop(struct bounce_buffer_state *state) { - void *tmp = *data; - - /* The buffer was already aligned, since "backup" is NULL. */ - if (!*backup) + if (state->bounce_buffer == state->user_buffer) return 0; - if (flags & GEN_BB_WRITE) - memcpy(*backup, *data, len); - - *data = *backup; - free(tmp); + if (state->flags & GEN_BB_WRITE) + memcpy(state->user_buffer, state->bounce_buffer, state->len); return 0; } diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 109acbf..d314d7d 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -96,11 +96,11 @@ static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data) static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data) { uint32_t data_count = data->blocksize * data->blocks; - uint32_t cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN); int dmach; struct mxs_dma_desc *desc = priv->desc; - void *addr, *backup; + void *addr; uint8_t flags; + struct bounce_buffer_state bbstate; memset(desc, 0, sizeof(struct mxs_dma_desc)); desc->address = (dma_addr_t)desc; @@ -115,19 +115,21 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data) flags = GEN_BB_READ; } - bounce_buffer_start(&addr, data_count, &backup, flags); + bounce_buffer_start(&bbstate, addr, data_count, flags); - priv->desc->cmd.address = (dma_addr_t)addr; + priv->desc->cmd.address = (dma_addr_t)bbstate.bounce_buffer; if (data->flags & MMC_DATA_WRITE) { /* Flush data to DRAM so DMA can pick them up */ - flush_dcache_range((uint32_t)addr, - (uint32_t)(addr) + cache_data_count); + flush_dcache_range((uint32_t)bbstate.bounce_buffer, + (uint32_t)(bbstate.bounce_buffer) + + bbstate.len_aligned); } /* Invalidate the area, so no writeback into the RAM races with DMA */ invalidate_dcache_range((uint32_t)priv->desc->cmd.address, - (uint32_t)(priv->desc->cmd.address + cache_data_count)); + (uint32_t)(priv->desc->cmd.address + + bbstate.len_aligned)); priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM | (data_count << MXS_DMA_DESC_BYTES_OFFSET); @@ -135,17 +137,18 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data) dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id; mxs_dma_desc_append(dmach, priv->desc); if (mxs_dma_go(dmach)) { - bounce_buffer_stop(&addr, data_count, &backup, flags); + bounce_buffer_stop(&bbstate); return COMM_ERR; } /* The data arrived into DRAM, invalidate cache over them */ if (data->flags & MMC_DATA_READ) { - invalidate_dcache_range((uint32_t)addr, - (uint32_t)(addr) + cache_data_count); + invalidate_dcache_range((uint32_t)bbstate.bounce_buffer, + (uint32_t)(bbstate.bounce_buffer) + + bbstate.len_aligned); } - bounce_buffer_stop(&addr, data_count, &backup, flags); + bounce_buffer_stop(&bbstate); return 0; } diff --git a/include/bouncebuf.h b/include/bouncebuf.h index 31021c5..205a1ed 100644 --- a/include/bouncebuf.h +++ b/include/bouncebuf.h @@ -52,33 +52,43 @@ #define GEN_BB_RW (GEN_BB_READ | GEN_BB_WRITE) #ifdef CONFIG_BOUNCE_BUFFER +struct bounce_buffer_state { + void *user_buffer; + void *bounce_buffer; + size_t len; + size_t len_aligned; + uint8_t flags; +}; + /** * bounce_buffer_start() -- Start the bounce buffer session + * state: stores state passed between bounce_buffer_{start,stop} * data: pointer to buffer to be aligned * len: length of the buffer - * backup: pointer to backup buffer (the original value is stored here if - * needed * flags: flags describing the transaction, see above. */ -int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags); +int bounce_buffer_start(struct bounce_buffer_state *state, void *data, + size_t len, uint8_t flags); /** * bounce_buffer_stop() -- Finish the bounce buffer session - * data: pointer to buffer that was aligned - * len: length of the buffer - * backup: pointer to backup buffer (the original value is stored here if - * needed - * flags: flags describing the transaction, see above. + * state: stores state passed between bounce_buffer_{start,stop} */ -int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags); +int bounce_buffer_stop(struct bounce_buffer_state *state); #else -static inline int bounce_buffer_start(void **data, size_t len, void **backup, - uint8_t flags) +struct bounce_buffer_state { + void *bounce_buffer; + size_t len_aligned; +}; + +static inline int bounce_buffer_start(struct bounce_buffer_state *state, + void *data, size_t len, uint8_t flags) { + state->bounce_buffer = data; + state->len_aligned = len; return 0; } -static inline int bounce_buffer_stop(void **data, size_t len, void **backup, - uint8_t flags) +static inline int bounce_buffer_stop(struct bounce_buffer_state *state) { return 0; }