Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp5629256pxb; Mon, 28 Mar 2022 15:11:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyBt/y80He5JBOwG464tTBvmfudV3ENjbke02dzWZ7HbXnkGVqGMqkEkC3Ngowb88TMMGkU X-Received: by 2002:a9f:356c:0:b0:359:5bee:d1f8 with SMTP id o99-20020a9f356c000000b003595beed1f8mr13997905uao.60.1648505504622; Mon, 28 Mar 2022 15:11:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1648505504; cv=none; d=google.com; s=arc-20160816; b=DIMFJNbZvZ3AdCr/ApXyFzOXb15/UdA8lHJZU2AUu4fs4Rm/wRSfgFmPQqiJu+Yvm/ mxfiSsG1UfJ962CDLcy32/qzxa0oM8IQKXi7zOjl8RlsMyqz6wPSS/WTCIA89G00+Hgr TxQoOiZhikwmyi/xU5+vAVaPUEHcOjpnw3OdMdJed3Pizqfn5JKEa0sJZ3+pIaxrqGJC cTFi0NU/XS21gzkYxTpJLK2YROLdtSXcJewbKq5oMRyvTUO1o/v74p3ztcsgLjo8tTdm a21RE/5zI1lIFC3rqIP4zqZc1Kjr3LkiScqE2qAOGqCHbcsan2gjzcPFz8B8jjXAASWt 7rbA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=0spQ+va0mupBxaDFYwsZDcGVtjhUmIgaGDAqHeg+qeI=; b=fkVuva1GkwmQ2HUcdAEajzGjI4GeFUthCr5+IdBbDgdJMOG70/XHMaFMWtwVtk+4Dr mglogd9zDbGzdRgEONMTlKqeP7KdGuqctGy5dl1lz4AD1lXHPaseJx429+A/ub0Dl2nd VbDlVwe1JBJjtYl1D7wR8mdQwzO01q1gRXVMFRAAsDQ7P2CdPWWOGWtLZuaZTqAWDL1k 2xJ3YMuMX6Vwxy9RJ+eP1N+qNmCqsX2/3V5PLdZY7cJ8sNaohRKe0Crw9NDAuKpyvnRl C98BWi0X0um2++RgD4AadtOwA0GlTk2m7arJuda58bnLkZ6f6LW67qZ4vrGgi7IYOLSy 9hlA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@foss.st.com header.s=selector1 header.b=rqTgfTo3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=foss.st.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id u13-20020ab0298d000000b0035a07f0f42asi1817638uap.38.2022.03.28.15.11.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 15:11:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@foss.st.com header.s=selector1 header.b=rqTgfTo3; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=foss.st.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DC84C169B02; Mon, 28 Mar 2022 14:31:47 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244089AbiC1OxY (ORCPT + 99 others); Mon, 28 Mar 2022 10:53:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244083AbiC1OxV (ORCPT ); Mon, 28 Mar 2022 10:53:21 -0400 Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [185.132.182.106]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9F0455DE56; Mon, 28 Mar 2022 07:51:39 -0700 (PDT) Received: from pps.filterd (m0241204.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.1.2/8.16.1.2) with ESMTP id 22SDaGbc023704; Mon, 28 Mar 2022 16:51:25 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foss.st.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding : content-type; s=selector1; bh=0spQ+va0mupBxaDFYwsZDcGVtjhUmIgaGDAqHeg+qeI=; b=rqTgfTo3U5WC7XloVhuPl6Z355ocyoda1qjCaIgQ0dmXUNrz3Yz5ewYvAYh9GM0vVo1h yba4vH8fZ813j6OXkeMVdoIiUVdQILrO6c/z4iZR5SQtOdS6qUdyFce3VSOrqlmP/XHT KbWGXKA0sEUFy9l+UZwjPg8WsZGMsrn2WNhW6EvDAPQaNCH9RMW3rvmUNxuaZXNIQN7z +S0aeLrNWlKxepwUO5KgvAbG+HgXedB/CcmRd1VRoB2z8LgkjAIUKcBit43/6p3myyYX w8cxBb+LXJOctJCJ3XDOf9G1vlp/3m7QigNgsKBeq8PQhAoh+TQ71qB0LDhi1T1gYHlz /A== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com (PPS) with ESMTPS id 3f1u2422rs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 28 Mar 2022 16:51:24 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 526FF100034; Mon, 28 Mar 2022 16:51:24 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag2node2.st.com [10.75.127.5]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 484B9233C81; Mon, 28 Mar 2022 16:51:24 +0200 (CEST) Received: from localhost (10.75.127.48) by SFHDAG2NODE2.st.com (10.75.127.5) with Microsoft SMTP Server (TLS) id 15.0.1497.26; Mon, 28 Mar 2022 16:51:23 +0200 From: Yann Gautier To: Ulf Hansson CC: Christophe Kerello , Ludovic Barre , Maxime Coquelin , Alexandre Torgue , Philipp Zabel , Linus Walleij , , , , , Yann Gautier Subject: [PATCH v2] mmc: mmci: stm32: use a buffer for unaligned DMA requests Date: Mon, 28 Mar 2022 16:51:14 +0200 Message-ID: <20220328145114.334577-1-yann.gautier@foss.st.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG2NODE1.st.com (10.75.127.4) To SFHDAG2NODE2.st.com (10.75.127.5) X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.850,Hydra:6.0.425,FMLib:17.11.64.514 definitions=2022-03-28_06,2022-03-28_01,2022-02-23_01 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- Changes since v1: - allocate bounce buffer in sdmmc_idma_validate_data() - realign on top of mmc/devel branch (25e14a52d35928a1831ca98889a8a25ac3017990) drivers/mmc/host/mmci_stm32_sdmmc.c | 88 +++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c index 4566d7fc9055..60bca78a72b1 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,8 @@ 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 device *dev = mmc_dev(host->mmc); struct scatterlist *sg; int i; @@ -61,41 +66,69 @@ 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; + goto use_bounce_buffer; } } 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; + goto use_bounce_buffer; } + return 0; + +use_bounce_buffer: + if (!idma->bounce_buf) { + 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; + } + } + + idma->use_bounce_buffer = true; + return 0; } 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 +145,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 +181,8 @@ 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; } else { host->mmc->max_segs = 1; host->mmc->max_seg_size = host->mmc->max_req_size; @@ -154,8 +200,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); -- 2.25.1