From patchwork Mon Apr 28 20:19:48 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kamal Dasu X-Patchwork-Id: 343581 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id ECA8214008B for ; Tue, 29 Apr 2014 06:27:29 +1000 (EST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wes7w-0006y2-HU; Mon, 28 Apr 2014 20:26:12 +0000 Received: from mail-gw2-out.broadcom.com ([216.31.210.63]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wes7u-0006ph-E2 for linux-mtd@lists.infradead.org; Mon, 28 Apr 2014 20:26:10 +0000 X-IronPort-AV: E=Sophos;i="4.97,946,1389772800"; d="scan'208";a="26730756" Received: from irvexchcas08.broadcom.com (HELO IRVEXCHCAS08.corp.ad.broadcom.com) ([10.9.208.57]) by mail-gw2-out.broadcom.com with ESMTP; 28 Apr 2014 13:45:34 -0700 Received: from IRVEXCHSMTP1.corp.ad.broadcom.com (10.9.207.51) by IRVEXCHCAS08.corp.ad.broadcom.com (10.9.208.57) with Microsoft SMTP Server (TLS) id 14.3.174.1; Mon, 28 Apr 2014 13:20:30 -0700 Received: from mail-irva-13.broadcom.com (10.10.10.20) by IRVEXCHSMTP1.corp.ad.broadcom.com (10.9.207.51) with Microsoft SMTP Server id 14.3.174.1; Mon, 28 Apr 2014 13:20:30 -0700 Received: from kdasu-ltmht-linux.and.broadcom.com (dhcp-mhtb-6-217.and.broadcom.com [10.28.6.217]) by mail-irva-13.broadcom.com (Postfix) with ESMTP id 3EE0951E84; Mon, 28 Apr 2014 13:20:21 -0700 (PDT) From: Kamal Dasu To: Subject: [PATCH v3] mtd: nand: Add support to use nand_base poi databuf as bounce buffer Date: Mon, 28 Apr 2014 16:19:48 -0400 Message-ID: <1398716388-14317-1-git-send-email-kdasu.kdev@gmail.com> X-Mailer: git-send-email 1.9.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140428_132610_509881_662638B9 X-CRM114-Status: GOOD ( 16.18 ) X-Spam-Score: 2.2 (++) X-Spam-Report: SpamAssassin version 3.3.2 on bombadil.infradead.org summary: Content analysis details: (2.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (kdasu.kdev[at]gmail.com) 0.0 DKIM_ADSP_CUSTOM_MED No valid author signature, adsp_override is CUSTOM_MED 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) 1.2 NML_ADSP_CUSTOM_MED ADSP custom_med hit, and not from a mailing list Cc: Kamal Dasu X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org nand_base can be passed a kmap()'d buffers from highmem by filesystems like jffs2. This results in failure to map the physical address of the DMA buffer on various contoller driver on different platforms. This change adds a chip option to use preallocated databuf as bounce buffers used in nand_do_read_ops() and nand_do_write_ops(). This allows for specific nand controller driver to set this option as needed. Signed-off-by: Kamal Dasu --- Changes since v2: * fix ARM build by including linux/mm.h * print highmem buffer address in pr_debug drivers/mtd/nand/nand_base.c | 31 ++++++++++++++++++++++++------- include/linux/mtd/nand.h | 5 +++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 9d01c4d..27505cd 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -1501,6 +1502,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, mtd->oobavail : mtd->oobsize; uint8_t *bufpoi, *oob, *buf; + int use_bufpoi; unsigned int max_bitflips = 0; int retry_mode = 0; bool ecc_fail = false; @@ -1522,10 +1524,17 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, bytes = min(mtd->writesize - col, readlen); aligned = (bytes == mtd->writesize); + use_bufpoi = (chip->options & NAND_USE_BOUNCE_BUFFER) ? + !virt_addr_valid(buf) : 0; /* Is the current page in the buffer? */ if (realpage != chip->pagebuf || oob) { - bufpoi = aligned ? buf : chip->buffers->databuf; + bufpoi = (aligned && !use_bufpoi) ? buf : + chip->buffers->databuf; + + if (use_bufpoi && aligned) + pr_debug("%s: using bounce buffer for buf@%p\n", + __func__, bufpoi); read_retry: chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); @@ -1547,7 +1556,7 @@ read_retry: ret = chip->ecc.read_page(mtd, chip, bufpoi, oob_required, page); if (ret < 0) { - if (!aligned) + if (!aligned || use_bufpoi) /* Invalidate page cache */ chip->pagebuf = -1; break; @@ -1556,7 +1565,7 @@ read_retry: max_bitflips = max_t(unsigned int, max_bitflips, ret); /* Transfer not aligned data */ - if (!aligned) { + if (!aligned || use_bufpoi) { if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && !(mtd->ecc_stats.failed - ecc_failures) && (ops->mode != MTD_OPS_RAW)) { @@ -2376,11 +2385,19 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, int bytes = mtd->writesize; int cached = writelen > bytes && page != blockmask; uint8_t *wbuf = buf; - - /* Partial page write? */ - if (unlikely(column || writelen < (mtd->writesize - 1))) { + int use_bufpoi = (chip->options & NAND_USE_BOUNCE_BUFFER ? + !virt_addr_valid(buf) : 0); + int part_pagewr = unlikely(column || + writelen < (mtd->writesize - 1)); + + /* Partial page write?, or need to use bounce buffer */ + if (part_pagewr || use_bufpoi) { + pr_debug("%s: using write bounce buffer for buf@%p\n", + __func__, buf); cached = 0; - bytes = min_t(int, bytes - column, (int) writelen); + if (part_pagewr) + bytes = min_t(int, + bytes - column, (int) writelen); chip->pagebuf = -1; memset(chip->buffers->databuf, 0xff, mtd->writesize); memcpy(&chip->buffers->databuf[column], buf, bytes); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 450d61e..bb3e064 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -176,6 +176,11 @@ typedef enum { /* Chip may not exist, so silence any errors in scan */ #define NAND_SCAN_SILENT_NODEV 0x00040000 /* + * This option is defined to protect against kmapped buffers + * being passed from highmem when using DMA + */ +#define NAND_USE_BOUNCE_BUFFER 0x00080000 +/* * Autodetect nand buswidth with readid/onfi. * This suppose the driver will configure the hardware in 8 bits mode * when calling nand_scan_ident, and update its configuration