From patchwork Tue Jan 26 06:42:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 573083 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 8A6291402C9 for ; Tue, 26 Jan 2016 17:44:15 +1100 (AEDT) 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 1aNxKy-0005A7-2D; Tue, 26 Jan 2016 06:42:48 +0000 Received: from down.free-electrons.com ([37.187.137.238] helo=mail.free-electrons.com) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aNxKs-00056Z-IH for linux-mtd@lists.infradead.org; Tue, 26 Jan 2016 06:42:43 +0000 Received: by mail.free-electrons.com (Postfix, from userid 110) id CBC86263; Tue, 26 Jan 2016 07:42:21 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (unknown [82.117.210.186]) by mail.free-electrons.com (Postfix) with ESMTPSA id 6FA2A22B; Tue, 26 Jan 2016 07:42:21 +0100 (CET) From: Boris Brezillon To: Han Xu Subject: [PATCH] Adapt raw page accesses to match the new raw_read/write implementation Date: Tue, 26 Jan 2016 07:42:17 +0100 Message-Id: <1453790537-20566-2-git-send-email-boris.brezillon@free-electrons.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1453790537-20566-1-git-send-email-boris.brezillon@free-electrons.com> References: <1453790537-20566-1-git-send-email-boris.brezillon@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160125_224243_009359_BCAF1E44 X-CRM114-Status: GOOD ( 17.81 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [37.187.137.238 listed in list.dnswl.org] -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.20 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Huang Shijie , Boris BREZILLON , Brian Norris , linux-mtd@lists.infradead.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Boris BREZILLON The old raw access implementation (in GPMI driver) was considering that data and OOB data were separated in their respective regions (the data area and the OOB area of the page), which is not true. They are actually interleaved this way: METADATA + ((DATA + ECCBYTES) * N) The new raw access implementation (in the GPMI driver) is hiding this weird layout to MTD users by exposing a more common layout: DATA + METADATA + (N * ECCBYTES) Here METADATA + (N * ECCBYTES) are exposed as if they were stored in the OOB area. Unfortunately kobs-ng rely on this weird layout when accessing the NAND in raw mode. This patch take the new layout into account. Signed-off-by: Boris BREZILLON --- src/mtd.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 5 deletions(-) diff --git a/src/mtd.c b/src/mtd.c index 02af33b..f6fa962 100644 --- a/src/mtd.c +++ b/src/mtd.c @@ -254,14 +254,26 @@ int mtd_read_page(struct mtd_data *md, int chip, loff_t ofs, int ecc) mtd_set_ecc_mode(md, ecc); - data = md->buf; + if (ecc) { + data = md->buf; + } else { + data = malloc(mtd_writesize(md) + mtd_oobsize(md)); + if (!data) { + fprintf(stderr, "mtd: %s failed to allocate buffer\n", __func__); + return -1; + } + } + oobdata = data + mtd_writesize(md); /* make sure it's aligned to a page */ - if ((ofs % mtd_writesize(md)) != 0) + if ((ofs % mtd_writesize(md)) != 0) { + if (!ecc) + free(data); return -1; + } - memset(md->buf, 0, mtd_writesize(md) + mtd_oobsize(md)); + memset(data, 0, mtd_writesize(md) + mtd_oobsize(md)); size = mtd_writesize(md); @@ -269,6 +281,33 @@ int mtd_read_page(struct mtd_data *md, int chip, loff_t ofs, int ecc) r = pread(md->part[chip].fd, data, size, ofs); } while (r == -1 && (errno == EAGAIN || errno == EBUSY)); + if (!ecc) { + int i; + struct nfc_geometry *nfc_geo = &md->nfc_geometry; + int eccbytes = ((nfc_geo->ecc_strength * nfc_geo->gf_len) + 7) / 8; + int chunksize = nfc_geo->ecc_chunk_size_in_bytes; + int dst_offset = 0; + + memcpy(md->buf, oobdata, nfc_geo->metadata_size_in_bytes); + dst_offset += nfc_geo->metadata_size_in_bytes; + for (i = 0; i < nfc_geo->ecc_chunk_count; i++) { + memcpy(md->buf + dst_offset, data + (i * chunksize), chunksize); + dst_offset += chunksize; + memcpy(md->buf + dst_offset, + oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes), + eccbytes); + dst_offset += eccbytes; + } + + if (mtd_writesize(md) + mtd_oobsize(md) > dst_offset) { + memcpy(md->buf + dst_offset, + oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes), + mtd_writesize(md) + mtd_oobsize(md) - dst_offset); + } + + free(data); + } + /* end of partition? */ if (r == 0) return 0; @@ -329,23 +368,71 @@ int mtd_write_page(struct mtd_data *md, int chip, loff_t ofs, int ecc) int r; const void *data; const void *oobdata; + struct mtd_write_req ops; mtd_set_ecc_mode(md, ecc); - data = md->buf; - oobdata = data + mtd_oobsize(md); + if (ecc) { + data = md->buf; + oobdata = data + mtd_writesize(md); + } else { + int i; + struct nfc_geometry *nfc_geo = &md->nfc_geometry; + int eccbytes = ((nfc_geo->ecc_strength * nfc_geo->gf_len) + 7) / 8; + int chunksize = nfc_geo->ecc_chunk_size_in_bytes; + int src_offset = 0; + + data = malloc(mtd_writesize(md) + mtd_oobsize(md)); + if (!data) { + fprintf(stderr, "mtd: %s failed to allocate buffer\n", __func__); + return -1; + } + oobdata = data + mtd_writesize(md); + memset(data, 0, mtd_writesize(md) + mtd_oobsize(md)); + memcpy(oobdata, md->buf, nfc_geo->metadata_size_in_bytes); + src_offset += nfc_geo->metadata_size_in_bytes; + for (i = 0; i < nfc_geo->ecc_chunk_count; i++) { + memcpy(data + (i * chunksize), md->buf + src_offset, chunksize); + src_offset += chunksize; + memcpy(oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes), + md->buf + src_offset, eccbytes); + src_offset += eccbytes; + } + + if (mtd_writesize(md) + mtd_oobsize(md) > src_offset) { + memcpy(oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes), + md->buf + src_offset, + mtd_writesize(md) + mtd_oobsize(md) - src_offset); + } + } /* make sure it's aligned to a page */ if ((ofs % mtd_writesize(md)) != 0) { fprintf(stderr, "mtd: %s failed\n", __func__); + if (!ecc) + free(data); return -1; } size = mtd_writesize(md); + ops.start = ofs; + ops.len = size; + ops.ooblen = ecc ? 0 : mtd_oobsize(md); + ops.usr_oob = (uint64_t)(unsigned long)oobdata; + ops.usr_data = (uint64_t)(unsigned long)data; + ops.mode = ecc ? MTD_OPS_AUTO_OOB : MTD_OPS_RAW; + r = ioctl(md->part[chip].fd, MEMWRITE, &ops); + if (!r) + r = size; + /* do { r = pwrite(md->part[chip].fd, data, size, ofs); } while (r == -1 && (errno == EAGAIN || errno == EBUSY)); + */ + + if (!ecc) + free(data); /* end of partition? */ if (r == 0) {