From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 61B2DC433F5 for ; Thu, 24 Mar 2022 11:57:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:Subject:Message-ID:Date:From: In-Reply-To:References:MIME-Version:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=KLRfHpqqYYxMAdi1RpY+UQo/LOOMFw0jjVDgUEnmAls=; b=Kyj4IzvgxyTQog Kg5xYWBfGZA7lrKPFLciWC/lebCFP8xWRsrhwoPxBYUeZJeTQGirXP5h1v6DZweSkv+BU7nYMS0Ny zQB8rGsUmJ5CrQC2WZoj8e0NQr3mTd2LcMDcn5Y792iCsvHrQb2ERcadwCE4t4YTO/bCvc1rreWTU x/sMPuCtFkyo5UkbySlfQ9Z04Y/Ysop0jJmetsdYRkgl7bk9WqXuuHmytYkSKNu/rsQY/rAmT2RDd vREmAT0yY0HMtaXLwgis4OQjnevJj8vC1u+dH9duLBRFTLx2rmfGMteY9naqAcPUegrkU/yJ4oB9X FMX5JhmE32PaobogThDA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nXM4g-00GP5r-7N; Thu, 24 Mar 2022 11:56:18 +0000 Received: from mail-lj1-x233.google.com ([2a00:1450:4864:20::233]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nXM4c-00GP4R-Hc for linux-arm-kernel@lists.infradead.org; Thu, 24 Mar 2022 11:56:16 +0000 Received: by mail-lj1-x233.google.com with SMTP id 17so5803187ljw.8 for ; Thu, 24 Mar 2022 04:56:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=20qzSFu8WfFwCVYdzmq5hRnnFKw8ZDXsTSDNJQxzips=; b=F29pMukvvs0UY7bTUtc1Tt9UgguPPK1AYFQx+T/yGyVZ+Y5Kzfd8qOBxFztYBt54Cn Ord0ThryohwhU38ZYzUtx2JM/TNVre58iFvSf6gz7nsFXurdeVbJsVGfn2Mzr5GfTACa trP9aVf/PauBXoHeuEzqVtqUaMxjGDOPzP9mJ0oOvgkjUN+kXI0BLq0XB/ONhoMIYEpy BopNgDvFptw0AiKJd4E1t3M0DWnXWV5g+5E1tZ/g/NLPLVv+yb//veNSaZCFdVKTVFtt 2D/jQhdtUH18hJDdEFI5bdzei/dowxx0vsllHWmQ6uMte3hIezf7/lLnebGbox7gBFVd 2ynQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=20qzSFu8WfFwCVYdzmq5hRnnFKw8ZDXsTSDNJQxzips=; b=OipN0vxg89Q3Y5ikZbc74zxpR+t7LzC2A98r20uom+zFfDH7YTgEC5iu5WepVfaY+C 2w8YGpJ78b9obE7CSsU5aKSzK4CHd/9cf8N8HxV3QEAXtJoAh2ZIAcOj9PrxvPdC+X9L x93i7V4Bs+X/ct+9zg0GeOGXhrfDOYW5Bupd1AG3cL4fwt1oBwLxyNgV0dFVux5HBQnT zkwQMAKAthqdQUliNPSE6UdKURYHvw6FuGiElS35fVw5bleejAhnMYYD2IUFqm/xT3Be jmAlflhVg7OqYEPnPh3kLWK6gSVdqx3KLvvgNAoTMCtZrlsNqqSBlyLoHEYvpQEvPNeP iDSQ== X-Gm-Message-State: AOAM530v9Top6t+NCmZkcd0H16ptR3YI2sGXqD7fDNnR8VqQrwUJljrs wkAEPDvDCsXsrU8u3Fw1NYjwRSBBMH9glYotUhnQKRHapRg= X-Google-Smtp-Source: ABdhPJw0GZRItCAMGMn5UV2L1PQyIs1R+7qQj5XrMCVRXWMeIg8BqBj3QSlStxt7HTPELqkp6gmVtw+jQBG/FeW7xHw= X-Received: by 2002:a2e:9cc5:0:b0:239:da6e:290d with SMTP id g5-20020a2e9cc5000000b00239da6e290dmr3744841ljj.4.1648122971468; Thu, 24 Mar 2022 04:56:11 -0700 (PDT) MIME-Version: 1.0 References: <20220317111944.116148-1-yann.gautier@foss.st.com> <20220317111944.116148-3-yann.gautier@foss.st.com> In-Reply-To: <20220317111944.116148-3-yann.gautier@foss.st.com> From: Ulf Hansson Date: Thu, 24 Mar 2022 12:55:35 +0100 Message-ID: Subject: Re: [PATCH 2/2] mmc: mmci: stm32: use a buffer for unaligned DMA requests To: Yann Gautier Cc: Christophe Kerello , Ludovic Barre , Maxime Coquelin , Alexandre Torgue , Philipp Zabel , Linus Walleij , linux-mmc@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220324_045614_619719_F3463274 X-CRM114-Status: GOOD ( 27.59 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org On Thu, 17 Mar 2022 at 12:19, Yann Gautier wrote: > > In SDIO mode, the sg list for requests can be unaligned with what the > STM32 SDMMC internal DMA can support. In that case, instead of failing, > use a temporary bounce buffer to copy from/to the sg list. > This buffer is limited to 1MB. But for that we need to also limit > max_req_size to 1MB. It has not shown any throughput penalties for > SD-cards or eMMC. > > Signed-off-by: Yann Gautier > --- > drivers/mmc/host/mmci_stm32_sdmmc.c | 80 +++++++++++++++++++++++------ > 1 file changed, 63 insertions(+), 17 deletions(-) > > diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c > index 4566d7fc9055..a4414e32800f 100644 > --- a/drivers/mmc/host/mmci_stm32_sdmmc.c > +++ b/drivers/mmc/host/mmci_stm32_sdmmc.c > @@ -43,6 +43,9 @@ struct sdmmc_lli_desc { > struct sdmmc_idma { > dma_addr_t sg_dma; > void *sg_cpu; > + dma_addr_t bounce_dma_addr; > + void *bounce_buf; > + bool use_bounce_buffer; > }; > > struct sdmmc_dlyb { > @@ -54,6 +57,7 @@ struct sdmmc_dlyb { > static int sdmmc_idma_validate_data(struct mmci_host *host, > struct mmc_data *data) > { > + struct sdmmc_idma *idma = host->dma_priv; > struct scatterlist *sg; > int i; > > @@ -61,21 +65,23 @@ static int sdmmc_idma_validate_data(struct mmci_host *host, > * idma has constraints on idmabase & idmasize for each element > * excepted the last element which has no constraint on idmasize > */ > + idma->use_bounce_buffer = false; > for_each_sg(data->sg, sg, data->sg_len - 1, i) { > if (!IS_ALIGNED(sg->offset, sizeof(u32)) || > !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) { > - dev_err(mmc_dev(host->mmc), > + dev_dbg(mmc_dev(host->mmc), > "unaligned scatterlist: ofst:%x length:%d\n", > data->sg->offset, data->sg->length); > - return -EINVAL; > + idma->use_bounce_buffer = true; > + return 0; > } > } > > if (!IS_ALIGNED(sg->offset, sizeof(u32))) { > - dev_err(mmc_dev(host->mmc), > + dev_dbg(mmc_dev(host->mmc), > "unaligned last scatterlist: ofst:%x length:%d\n", > data->sg->offset, data->sg->length); > - return -EINVAL; > + idma->use_bounce_buffer = true; > } > > return 0; > @@ -84,18 +90,29 @@ static int sdmmc_idma_validate_data(struct mmci_host *host, > static int _sdmmc_idma_prep_data(struct mmci_host *host, > struct mmc_data *data) > { > - int n_elem; > + struct sdmmc_idma *idma = host->dma_priv; > > - n_elem = dma_map_sg(mmc_dev(host->mmc), > - data->sg, > - data->sg_len, > - mmc_get_dma_dir(data)); > + if (idma->use_bounce_buffer) { > + if (data->flags & MMC_DATA_WRITE) { > + unsigned int xfer_bytes = data->blksz * data->blocks; > > - if (!n_elem) { > - dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n"); > - return -EINVAL; > - } > + sg_copy_to_buffer(data->sg, data->sg_len, > + idma->bounce_buf, xfer_bytes); > + dma_wmb(); > + } > + } else { > + int n_elem; > + > + n_elem = dma_map_sg(mmc_dev(host->mmc), > + data->sg, > + data->sg_len, > + mmc_get_dma_dir(data)); > > + if (!n_elem) { > + dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n"); > + return -EINVAL; > + } > + } > return 0; > } > > @@ -112,8 +129,19 @@ static int sdmmc_idma_prep_data(struct mmci_host *host, > static void sdmmc_idma_unprep_data(struct mmci_host *host, > struct mmc_data *data, int err) > { > - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, > - mmc_get_dma_dir(data)); > + struct sdmmc_idma *idma = host->dma_priv; > + > + if (idma->use_bounce_buffer) { > + if (data->flags & MMC_DATA_READ) { > + unsigned int xfer_bytes = data->blksz * data->blocks; > + > + sg_copy_from_buffer(data->sg, data->sg_len, > + idma->bounce_buf, xfer_bytes); > + } > + } else { > + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, > + mmc_get_dma_dir(data)); > + } > } > > static int sdmmc_idma_setup(struct mmci_host *host) > @@ -137,6 +165,16 @@ static int sdmmc_idma_setup(struct mmci_host *host) > host->mmc->max_segs = SDMMC_LLI_BUF_LEN / > sizeof(struct sdmmc_lli_desc); > host->mmc->max_seg_size = host->variant->stm32_idmabsize_mask; > + > + host->mmc->max_req_size = SZ_1M; > + idma->bounce_buf = dmam_alloc_coherent(dev, > + host->mmc->max_req_size, > + &idma->bounce_dma_addr, > + GFP_KERNEL); > + if (!idma->bounce_buf) { > + dev_err(dev, "Unable to map allocate DMA bounce buffer.\n"); > + return -ENOMEM; If we fail to allocate the 1M bounce buffer, then we end up always using a PIO based mode, right? Perhaps we can allow the above allocation to fail, but then limit us to use DMA only when the buffers are properly aligned? Would that work? > + } > } else { > host->mmc->max_segs = 1; > host->mmc->max_seg_size = host->mmc->max_req_size; > @@ -154,8 +192,16 @@ static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl) > struct scatterlist *sg; > int i; > > - if (!host->variant->dma_lli || data->sg_len == 1) { > - writel_relaxed(sg_dma_address(data->sg), > + if (!host->variant->dma_lli || data->sg_len == 1 || > + idma->use_bounce_buffer) { > + u32 dma_addr; > + > + if (idma->use_bounce_buffer) > + dma_addr = idma->bounce_dma_addr; > + else > + dma_addr = sg_dma_address(data->sg); > + > + writel_relaxed(dma_addr, > host->base + MMCI_STM32_IDMABASE0R); > writel_relaxed(MMCI_STM32_IDMAEN, > host->base + MMCI_STM32_IDMACTRLR); Kind regards Uffe _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel