Received: by 2002:ab2:710b:0:b0:1ef:a325:1205 with SMTP id z11csp1873608lql; Wed, 13 Mar 2024 10:23:59 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUTISp4QWl77R+wc5otdy3lSKq1+o5gRhmr78dpwhMBW3Q77Lx6pvgaIUd/wmw+yDRUnQWfzrwxw65eV+pUjPJAsdbjPKDUkKb5L4JV0Q== X-Google-Smtp-Source: AGHT+IHUT0U3eAJT47etQa10oQm74PqxY3ObCok62R6dFCKtp+/ARoFg6zc4OI0e8JAppmiGwmIY X-Received: by 2002:a17:906:bf47:b0:a46:22a3:4798 with SMTP id ps7-20020a170906bf4700b00a4622a34798mr7190274ejb.46.1710350639057; Wed, 13 Mar 2024 10:23:59 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1710350639; cv=pass; d=google.com; s=arc-20160816; b=HM4/YfAP3+VAHLZM5NkIfwac/UIivaxAIsvGtnzsszEjyaiZbYpKY/2t1BDJoqwwQG xvq1bloo27yG6qWd++NjUOS51IzOf2ysYKyN3gI1b9ES6T5ZAJW87R5GNowz+rMaLpMi /eyUu+kbVIIAVev4J2d8Zs+ONBkCBVpRVGrSAsE93zwDxVoyD0yHBctY1FQBXZTAUynN WEHtD42en7AkLJNPfDmXu+JIaZSLdLxD6CeoFc9JpXqVsI1/CGacoX4ms5VtYgkrpUvJ VLmIUya1UvCZFBR8j0G5W22boLxbbCxnN4jL878CtxGPjM+SE+sQHXFLpRboD/HWwmP/ TlKQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=vTj54pgwOsOkwZ5vg7Tzi5OMR+EXGU31FObdOoFueCg=; fh=HEEdW9va7hSxbNuwcvKENjHzLpiEKqw0MvJTna+hcao=; b=vAEXjrrUKQpZRgv7fFsQ8GZKwcV1biUFZsx+9vgWPXpBEArNzJs/xUQX9HCIwBk0JN WQsn/WChCz0Zl3IJy9s7+zXa/Lvl4bC7UmNjdRoxTHs8lGpjeb5J9aqg2ozFmvYynrHy Sr7+wlJCgBKfeFGB+BeNRA+5iwZQNS7SK6IpgMkCWKmPHhevnmuXv9vllF3/B97GfpF3 O9w3/r5Rs0TXzbxqeentVROmiS5T+6eTpxMA/qUgIE0KOyAPGwb81oiF7uDPluOKKhjJ kpO8rPYWwybD3UGP16fizW0JRKfa+dFeU+UGcKebsH5MBph4AanRv21K+umR3C84kDyV WmHw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=P5n7akvF; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-101941-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-101941-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id x13-20020a170906b08d00b00a441e6636c6si4609476ejy.251.2024.03.13.10.23.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 10:23:59 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-101941-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=P5n7akvF; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-101941-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-101941-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 5503F1F24811 for ; Wed, 13 Mar 2024 17:21:10 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4B572626BC; Wed, 13 Mar 2024 16:42:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="P5n7akvF" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 35A7662177; Wed, 13 Mar 2024 16:42:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710348148; cv=none; b=G0+F2WJ4t3NYkD2Tl8KPvbRi6dYjajJzfYzoUt3axH61a3+H+pZADyBDzTPuyJhWHypxVRXc93JwTFuvWsZMvq12OrMxY2ZPROfvOra0bXuoO3pRwZGkrBe5aW0YERsLwh9UM4Mg3HBbEznEXsx6mMzWaBratnZgnU0sR0RRyLY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710348148; c=relaxed/simple; bh=IdN3gYeyWAVlGPzwpeyM5dTBSOISdvZ318vw8Bk+/9w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uqJEochHxLJvEmPRvVo9wmIarDZpc90SJX5moG/0G6pP+DG00wphbzfk2CCPu9FtPHWEZCRrF0u6zqbePMv4NluEILpUVXk3GVsC5wljbOwERQGXGCmjcILZ5OqpjUDPQ5v48+DANC4sOXGDdPoUAcegi/JRoZvp3Uh0H0Cd/sM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=P5n7akvF; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 178EAC43394; Wed, 13 Mar 2024 16:42:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1710348147; bh=IdN3gYeyWAVlGPzwpeyM5dTBSOISdvZ318vw8Bk+/9w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P5n7akvFAb60dniAxSygVLRftsmwFrHHXCzL3VY4EwrW6uJ5Lo5R/aOX+F7llvY3U KZDdzk3WX4VaYGMS5P3sQG4qsQn2+wz0mtLqhzMfZmSNy6MvFCuanjomsdDnJdXMF+ DGkizFNXa/GUEzmtsGmzHT3w05K0W7b1LYcUc5x72wv5KvjRimQdxaDxckgE8KaYat 5/M3DbqPIExaL2yFn7jZ93RWdnoXb7XSz9Oin32cH/5PzJyG7fdBByWtYcz3JCPpaa ID0U/VCuk7KGHj1RRKkJtFG4caCUYG8MIn7glLaGr3njw9Vz77EFEz3BwKibE7GZxi rJU9/v/Aapo1Q== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Yann Gautier , Ulf Hansson , Sasha Levin Subject: [PATCH 5.15 01/76] mmc: mmci: stm32: use a buffer for unaligned DMA requests Date: Wed, 13 Mar 2024 12:41:08 -0400 Message-ID: <20240313164223.615640-2-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313164223.615640-1-sashal@kernel.org> References: <20240313164223.615640-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-KernelTest-Patch: http://kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.152-rc1.gz X-KernelTest-Tree: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git X-KernelTest-Branch: linux-5.15.y X-KernelTest-Patches: git://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git X-KernelTest-Version: 5.15.152-rc1 X-KernelTest-Deadline: 2024-03-15T16:42+00:00 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit From: Yann Gautier [ Upstream commit 970dc9c11a17994ab878016b536612ab00d1441d ] 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 Link: https://lore.kernel.org/r/20220328145114.334577-1-yann.gautier@foss.st.com Signed-off-by: Ulf Hansson Stable-dep-of: 6b1ba3f9040b ("mmc: mmci: stm32: fix DMA API overlapping mappings warning") Signed-off-by: Sasha Levin --- 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 4cceb9bab0361..11ae0cb479239 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.43.0