From patchwork Mon Feb 27 12:08:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Raghavendra, Vignesh" X-Patchwork-Id: 732791 X-Patchwork-Delegate: cyrille.pitchen@atmel.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vX0t40m1pz9s9r for ; Mon, 27 Feb 2017 23:11:08 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="A7TjRX3U"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=kTeVmxKlQWQg9e4hMCwdkt49S3/ZiAgER2Gh1BQeNPE=; b=A7TjRX3UHez4TW jPVU3FfsM95csaDNK2DYr1itxoy9fbV6bsE5t+R9q3ylcD/iprQFL0WYF+OoJeIbEVW546IlfFwam duCxxeE/Eesz3e1Mb8q1DCnLnbogr7D79zoJ/s7YZ8oJMHyuw2apAxEughaN6wPHGfCIQ43ZGbiGp Us4LJVyd+KBO+CKwlJBUkFTLs1h5f2Yc/Hqdgv9Mbu8Itj5nfxhm7NGfuXC/TP7QJKZivz2pnMVQK EBZTdeiGOmDrTfOap53olfh0J+oH8PF1GJ9+PAmnvgLiJXNFAlmKvzcwxsYjRFlmcD68dh/RsYHfG fCSMY/WAK6apGEv0kLoQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1ciK8s-00083L-1x; Mon, 27 Feb 2017 12:11:02 +0000 Received: from lelnx193.ext.ti.com ([198.47.27.77]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1ciK80-0006Px-5q for linux-mtd@lists.infradead.org; Mon, 27 Feb 2017 12:10:11 +0000 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by lelnx193.ext.ti.com (8.15.1/8.15.1) with ESMTP id v1RC99gk032506; Mon, 27 Feb 2017 06:09:09 -0600 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id v1RC98m5013995; Mon, 27 Feb 2017 06:09:08 -0600 Received: from dlep33.itg.ti.com (157.170.170.75) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.294.0; Mon, 27 Feb 2017 06:09:08 -0600 Received: from a0132425.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id v1RC90lL014396; Mon, 27 Feb 2017 06:09:05 -0600 From: Vignesh R To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , Cyrille Pitchen Subject: [RFC PATCH 1/2] mtd: spi-nor: Introduce bounce buffer to handle vmalloc'd buffers Date: Mon, 27 Feb 2017 17:38:38 +0530 Message-ID: <20170227120839.16545-2-vigneshr@ti.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170227120839.16545-1-vigneshr@ti.com> References: <20170227120839.16545-1-vigneshr@ti.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170227_041008_456926_232B2314 X-CRM114-Status: GOOD ( 14.27 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Frode Isaksen , Vignesh R , linux-kernel@vger.kernel.org, linux-spi@vger.kernel.org, linux-mtd@lists.infradead.org, linux-omap@vger.kernel.org Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Filesystems like UBIFS may pass vmalloc'd buffers to SPI NOR layer which will end up in SPI layer. SPI core does try to handle such buffers (see spi_map_buf()) by doing vmalloc_to_page() and creating scatterlist. But, its known that this does not work well with VIVT/aliasing cache architectures. This also fails when buffers are addressed using LPAE (buffers in region higher than 32 bit addressable region), if DMA is 32bit only. Introduce bounce buffers support in SPI NOR framework to handle vmalloc'd buffers. Use a pre-allocated per flash bounce buffer equal to the sector size of the flash. Flash drivers can enable this feature by setting SNOR_F_USE_BOUNCE_BUFFER flag. This would also enable SPI NOR drivers to safely use DMA in their read/write callbacks. Signed-off-by: Vignesh R --- drivers/mtd/spi-nor/spi-nor.c | 30 +++++++++++++++++++++++++++--- include/linux/mtd/spi-nor.h | 4 ++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 747645c74134..c241fefa5aff 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1205,11 +1206,21 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, while (len) { loff_t addr = from; + bool use_bb = false; + u_char *dst_buf = buf; + size_t buf_len = len; if (nor->flags & SNOR_F_S3AN_ADDR_DEFAULT) addr = spi_nor_s3an_addr_convert(nor, addr); - ret = nor->read(nor, addr, len, buf); + if (!virt_addr_valid(buf) && nor->bounce_buf) { + use_bb = true; + dst_buf = nor->bounce_buf; + if (len > mtd->erasesize) + buf_len = mtd->erasesize; + } + + ret = nor->read(nor, from, buf_len, dst_buf); if (ret == 0) { /* We shouldn't see 0-length reads */ ret = -EIO; @@ -1217,7 +1228,8 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, } if (ret < 0) goto read_err; - + if (use_bb) + memcpy(buf, dst_buf, ret); WARN_ON(ret > len); *retlen += ret; buf += ret; @@ -1329,6 +1341,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, return ret; for (i = 0; i < len; ) { + const u_char *src_buf = buf + i; ssize_t written; loff_t addr = to + i; @@ -1354,8 +1367,13 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, if (nor->flags & SNOR_F_S3AN_ADDR_DEFAULT) addr = spi_nor_s3an_addr_convert(nor, addr); + if (!virt_addr_valid(buf) && nor->bounce_buf) { + memcpy(nor->bounce_buf, buf + i, page_remain); + src_buf = nor->bounce_buf; + } + write_enable(nor); - ret = nor->write(nor, addr, page_remain, buf + i); + ret = nor->write(nor, addr, page_remain, src_buf); if (ret < 0) goto write_err; written = ret; @@ -1720,6 +1738,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) return -EINVAL; } + if (nor->flags & SNOR_F_USE_BOUNCE_BUFFER) { + nor->bounce_buf = devm_kmalloc(dev, mtd->erasesize, GFP_KERNEL); + if (!nor->bounce_buf) + dev_err(dev, "unable to allocated bounce buffer\n"); + } + nor->read_dummy = spi_nor_read_dummy_cycles(nor); if (info->flags & SPI_S3AN) { diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index f2a718030476..3846ff5fa011 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -141,6 +141,7 @@ enum spi_nor_option_flags { SNOR_F_NO_OP_CHIP_ERASE = BIT(2), SNOR_F_S3AN_ADDR_DEFAULT = BIT(3), SNOR_F_READY_XSR_RDY = BIT(4), + SNOR_F_USE_BOUNCE_BUFFER = BIT(5), }; /** @@ -173,6 +174,8 @@ enum spi_nor_option_flags { * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is * completely locked + * @bounce_buf bounce buffer to use incase of vmalloc'd buffers, + * for drivers that may use DMA. * @priv: the private data */ struct spi_nor { @@ -205,6 +208,7 @@ struct spi_nor { int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); + void *bounce_buf; void *priv; };