From patchwork Wed Apr 23 22:16:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kamal Dasu X-Patchwork-Id: 342020 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 36531140084 for ; Thu, 24 Apr 2014 08:19:02 +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 1Wd5Tn-0006vu-JF; Wed, 23 Apr 2014 22:17:23 +0000 Received: from mail-vc0-x231.google.com ([2607:f8b0:400c:c03::231]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Wd5Tl-0006tH-Vd for linux-mtd@lists.infradead.org; Wed, 23 Apr 2014 22:17:22 +0000 Received: by mail-vc0-f177.google.com with SMTP id if17so1953428vcb.22 for ; Wed, 23 Apr 2014 15:17:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=mje0siRJqPrzi+KD2nFOadggKMBncv0l1MOfYC8R1uE=; b=c45sO4DTAhLmp6DWiATqGKFKfefO7Rsymke8WqQY+LEaqPI84ZMknd1iEm0vrQTJQR XzZjqbwM4lYxs6LgnEVn5QV8yVsC4nyB/auElCeQJXKNv0Ypttf+vB55bbHIvhecTTfP rpO7yvlR3I0FLP3masxbViHzVebdjh2bD3HBR6yz0FFDgOZ1fGxKDyCjDw4GdsOZIxYR Oah/5NqPMLufb5Y6Yz7kmJD/6nX0fDytR9x5qO+QuV6ie5buG9gOvMOViuGDAQayrql6 ItYnIXJtVEs1idYkXHHS1G0CAuZM7PGta8/7uPWrF46QcQWnvnKNoStQe9yLsSMOkWAb D1Hw== MIME-Version: 1.0 X-Received: by 10.52.138.112 with SMTP id qp16mr1561764vdb.40.1398291419814; Wed, 23 Apr 2014 15:16:59 -0700 (PDT) Received: by 10.220.52.194 with HTTP; Wed, 23 Apr 2014 15:16:59 -0700 (PDT) In-Reply-To: <1398286150-1590-1-git-send-email-kdasu.kdev@gmail.com> References: <1398286150-1590-1-git-send-email-kdasu.kdev@gmail.com> Date: Wed, 23 Apr 2014 18:16:59 -0400 Message-ID: Subject: Fwd: [PATCH] mtd: nand: Add support to use nand_base poi databuf as bounce buffer From: Kamal Dasu To: linux-mtd@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140423_151722_132137_06E488C8 X-CRM114-Status: GOOD ( 19.10 ) X-Spam-Score: -0.1 (/) X-Spam-Report: SpamAssassin version 3.3.2 on bombadil.infradead.org summary: Content analysis details: (-0.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (kdasu.kdev[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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 --- drivers/mtd/nand/nand_base.c | 27 +++++++++++++++++++++------ include/linux/mtd/nand.h | 5 +++++ 2 files changed, 26 insertions(+), 6 deletions(-) -- 1.9.2 diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 9d01c4d..37d7315 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1501,6 +1501,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 +1523,16 @@ 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\n", __func__); read_retry: chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); @@ -1547,7 +1554,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 +1563,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 +2383,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\n", __func__); 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