From patchwork Fri Oct 16 03:45:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3638 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id C70DD1C288F for ; Fri, 16 Oct 2026 05:47:08 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-26683-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-26683-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 8C7D72B73C for ; Fri, 16 Oct 2026 03:46:09 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EDA7D3B4E80; Fri, 16 Oct 2026 03:45:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jZNRSDV3" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f45.google.com (mail-ot1-f45.google.com [209.85.210.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E25803B3C12 for ; Fri, 16 Oct 2026 03:45:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122343; cv=none; b=ZinhuBf4c97BquondIHQgjSyO0uxywpejB8OdZPeyGZekqub3Ky0bIbUEy6rxHg0Z80Xjq4OMrA4vcBo3lDeISznBvoxqXgIA2zvXx8PgV64frRy7/DQgF8rlL50NBR7zhrOJUeWYGkf371Rx1X/s3kXEbsPtx7CiVYUvheBFR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122343; c=relaxed/simple; bh=KL2itoqI1FRgl/wkdyzI6omghofE7iWi1HQCV9M7LQ4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WN2ze7JaCA6rQrySnejI9DBraGe1Csdgd6CdyrIvntRd7zefJoCf85GBp+IBEGkK73le0tysmJk9D3NJ4ehAZn5Cdv2aSmnJ7qsLCA2dA6hr1S1P2Z5VWR0VzAEzQUY3ebrj1zuA0gtOgZDF9mm3mzrsCUo9++TTJc0fPNS3FAw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=jZNRSDV3; arc=none smtp.client-ip=209.85.210.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f45.google.com with SMTP id 46e09a7af769-823e4047037so4571215a34.2 for ; Thu, 15 Oct 2026 20:45:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122341; x=1792727141; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=jq/NuCCaL8gKhO+mvfil1XtSoT7M57C6sxsBn3oDvGc=; b=jZNRSDV37T+JTWbL3DxHXPXq5G5lXGjZezMRZDrvS3wO3iKzBJ1dUKInAd9qHwAo12 yKHo/I4GjB24y0NP2+pa0y9r0twJ2KptgXSzJe7vRr07dSlmgHh3Tp64P83F4l5ESluD dxl1blW8Ad3F0YOVfGR4YfOi97IcU/dcqib/CR11CGjI1rLFQHx0askA4yr3mvdgr0i4 pSmTBVcynllHLPp7FD8NCMYfZdNcG0vSCfKNzSIzdrSpP8NefJgJSQn9ot/vwHa62WVx MK6uZwGdBpAisI7hXuRFEtXOa4HGui06wBM7qrRdirVXwYOa/qIjB1COzOhYPvvMqvWv xGaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122341; x=1792727141; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=jq/NuCCaL8gKhO+mvfil1XtSoT7M57C6sxsBn3oDvGc=; b=qeMlFMU2Jjldiy6vKtIFlvUASF22wII1PGFtACglp0/pRUll/xIjsChBbwg5dUXtTC OttXslh8FZ2xd/PP7zr7lVUsH3eFLqo2X44inz1obcVVyfBnmFvLs5IMIFWZu8dyTS1+ /84vQvk/VrgY+BGpiJg83sGU5oy5NbQCSVLHZVPpX8bc9jDr9kQZjFpMVwawKYIYR7WX bPkbMMADKyXNpley7+//rfUU1Ezsbu7Hhb8lnqrCWWQK++q1GgGtbxHfrp04D53NnpDo HPMTaP9ZJyENzR1tY7MrzSQZ66Iw4h0H/J0Zny843se2XMO2FCmqAr2zqGoAXCRCi2RM r8Rg== X-Forwarded-Encrypted: i=1; AKwUvBxTyWJJZmYr8NgkTOUJYFInQ2tNEsee/WQ+6fTgG7zfPvOXgeJfQiJ4zZnA5QlOhrEFSezehJcEZSIJEA==@lists.linux.dev X-Gm-Message-State: AFq9FYLHuKIVuV2qYBVAviTBN1Ztxv94aUyZSZHCBa/98VzMWL3qvJuU bFKSQzE5acknHoitHrOLXClIL2pB1ROaIje6Ucxef815PEKsbTHQi4Py X-Gm-Gg: AYBFou3dIUu3QCdK1/IXMl1XDMKvGzazRSUSnfNypMq5fvBj76Vkm5Gn25AkIYMN0Pk C/HhJPwMAirTxHCMdu40wliaraKSRnquG5/eXHCKnylQ9q0mIH49qRDPfkYE8RnC1dyWOIUGICL iT3WMcjr3zaO5WvZk7cJ+V18wLsgceoWK4lh0aaAq6SIrYMEWAuhtZWPj25l39zfha16Ct1a+YO +Lhe/AJuBkUoJ14MqDAnE1cgkM5XnrM+U2/PkMr77KwHaCqqxRkOMY1R1TnUEn5z3YrIiNlJJXp 3XJ8qIU5uti8VDlylsZP7yak7cfhTuoucs/yzrrNpncT+3exqUTE9ImUSbt4E8ycZJY78bWtUv6 sCNp67LfEnMnWXFhNbmcX/7DDu1uqI1KQrnalPB0dCzEkuPY6dkFcpLjS1QckR4enR47HwkioCR cY4jZI4pE/HBDTj6ur7HFdg7xEU98J9K16/FsBog17B77pqyLFeMKOwn+A7vacnnDB1Xj4lBq9U 1nD4nhJSCdKX5IeeCIjIE3gP8UWEx9D+Pk1seK3xagDLTFk3NBO3tYw/U46Fa0WzJt8cxZiDksK REaoPjJXPwUYnr1iNa0OOqkm6biTu7V5W9kKOQmgl+I181rZ13vs0Cl7BJZoGk15p3AihR7jd8W I1JkJfyefG/97FpbSw/O6PQ== X-Received: by 2002:a05:6830:2b23:b0:7dc:dbe4:3f21 with SMTP id 46e09a7af769-83090e20c67mr20939261a34.1.1792122340590; Thu, 15 Oct 2026 20:45:40 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-8429b57870fsm834402a34.0.2026.10.15.20.45.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:40 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:23 -0600 Subject: [PATCH v8 08/17] mtd: rawnand: sunxi: propagate buffer and column transfer errors Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-8-8ba4881fbee8@gmail.com> References: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com> In-Reply-To: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= sunxi_nfc_read_buf() and sunxi_nfc_write_buf() move data through controller SRAM, waiting for FIFO space and transfer completion. On timeout they stop their loop but return void, so their callers cannot distinguish a complete transfer from a partial one. The hardware-ECC paths also ignore some NAND column-change errors, including extra-OOB transfers performed after DMA. Reads can thus succeed with incomplete data or bytes from the wrong column; writes can issue PAGEPROG after failing to transfer all the intended bytes. Return the transfer status through the randomizer and OOB helpers to the page callbacks. A read with a NULL destination still fills controller SRAM for ECC and must report errors even though it does not copy to memory. Disable the randomizer after either transfer outcome, and use the page callbacks' error exits to disable ECC and skip program-end. Update a tracked OOB column only after the requested transfer succeeds. Keep transport status separate from the maximum corrected-bit count: zero from a successful OOB read must not erase a positive correction result. If an OOB read after DMA fails, restore that attempt's corrected/failed counters before the caller retries the page in PIO. Leave successful command sequences and the returned OOB representation unchanged. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 170 +++++++++++++++++++++++++------------- 1 file changed, 113 insertions(+), 57 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index a244d2158d76..fcb017f048db 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -670,7 +670,7 @@ static void sunxi_nfc_select_chip(struct nand_chip *nand, unsigned int cs) writel(ctl, nfc->regs + NFC_REG_CTL); } -static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) +static int sunxi_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); @@ -686,7 +686,7 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; writel(cnt, nfc->regs + NFC_REG_CNT); tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD; @@ -698,17 +698,19 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; if (buf) memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE, cnt); offs += cnt; } + + return 0; } -static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, - int len) +static int sunxi_nfc_write_buf(struct nand_chip *nand, const u8 *buf, + int len) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); @@ -724,7 +726,7 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) - break; + return ret; writel(cnt, nfc->regs + NFC_REG_CNT); memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt); @@ -738,10 +740,12 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0); if (ret) - break; + return ret; offs += cnt; } + + return 0; } /* These seed values have been extracted from Allwinner's BSP */ @@ -891,23 +895,31 @@ static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *bbm) bbm[1] ^= sunxi_nfc_randomizer_step(state, 8); } -static void sunxi_nfc_randomizer_write_buf(struct nand_chip *nand, - const uint8_t *buf, int len, - bool ecc, int page) +static int sunxi_nfc_randomizer_write_buf(struct nand_chip *nand, + const u8 *buf, int len, + bool ecc, int page) { + int ret; + sunxi_nfc_randomizer_config(nand, page, ecc); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_write_buf(nand, buf, len); + ret = sunxi_nfc_write_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } -static void sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, uint8_t *buf, - int len, bool ecc, int page) +static int sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, u8 *buf, + int len, bool ecc, int page) { + int ret; + sunxi_nfc_randomizer_config(nand, page, ecc); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_read_buf(nand, buf, len); + ret = sunxi_nfc_read_buf(nand, buf, len); sunxi_nfc_randomizer_disable(nand); + + return ret; } static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand) @@ -1157,31 +1169,39 @@ static int sunxi_get_ecc_offset(struct sunxi_nand_chip *sunxi_nand, sunxi_nfc_user_data_sz(sunxi_nand, step); } -static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, - u8 *oob, int *cur_off, - bool randomize, int page) +static int sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, + u8 *oob, int *cur_off, + bool randomize, int page) { struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct mtd_info *mtd = nand_to_mtd(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len = mtd->oobsize - offset; + int ret; if (len <= 0) - return; + return 0; - if (!cur_off || *cur_off != (offset + mtd->writesize)) - nand_change_read_column_op(nand, mtd->writesize + offset, - NULL, 0, false); + if (!cur_off || *cur_off != (offset + mtd->writesize)) { + ret = nand_change_read_column_op(nand, mtd->writesize + offset, + NULL, 0, false); + if (ret) + return ret; + } if (!randomize) - sunxi_nfc_read_buf(nand, oob + offset, len); + ret = sunxi_nfc_read_buf(nand, oob + offset, len); else - sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, - false, page); + ret = sunxi_nfc_randomizer_read_buf(nand, oob + offset, len, + false, page); + if (ret) + return ret; if (cur_off) *cur_off = mtd->oobsize + mtd->writesize; + + return 0; } /* Interpret one PIO step or a completed DMA batch before reusing its status. */ @@ -1230,15 +1250,19 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, if (read->oob_required) { /* Keep the existing PIO and DMA representations of parity. */ - nand_change_read_column_op(nand, mtd->writesize + oob_off, - read->dma ? oob : NULL, - read->dma ? ecc->bytes + user_data_sz : 0, - false); + ret = nand_change_read_column_op(nand, mtd->writesize + oob_off, + read->dma ? oob : NULL, + read->dma ? ecc->bytes + user_data_sz : 0, + false); + if (ret) + return ret; if (!read->dma) { - sunxi_nfc_randomizer_read_buf(nand, oob, - ecc->bytes + user_data_sz, - true, read->page); + ret = sunxi_nfc_randomizer_read_buf(nand, oob, + ecc->bytes + user_data_sz, + true, read->page); + if (ret) + return ret; } sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, reg_index, !step, @@ -1278,9 +1302,14 @@ static int sunxi_nfc_oob_read_batch(struct nand_chip *nand, static int sunxi_nfc_oob_finish_read(struct nand_chip *nand, struct sunxi_nfc_ecc_read *read, int *cur_off) { - if (read->oob_required) - sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off, - !read->has_erased_chunk, read->page); + int ret; + + if (read->oob_required) { + ret = sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, cur_off, + !read->has_erased_chunk, read->page); + if (ret) + return ret; + } return read->max_bitflips; } @@ -1299,13 +1328,21 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, u32 pattern_found; int ret; - if (*cur_off != data_off) - nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (*cur_off != data_off) { + ret = nand_change_read_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } - sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + ret = sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page); + if (ret) + return ret; - if (data_off + ecc->size != oob_off) - nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size != oob_off) { + ret = nand_change_read_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1428,13 +1465,21 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, /* From the controller point of view, we are at step 0 */ const int nfc_step = 0; - if (data_off != *cur_off) - nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (data_off != *cur_off) { + ret = nand_change_write_column_op(nand, data_off, NULL, 0, false); + if (ret) + return ret; + } - sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); + ret = sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page); + if (ret) + return ret; - if (data_off + ecc->size != oob_off) - nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (data_off + ecc->size != oob_off) { + ret = nand_change_write_column_op(nand, oob_off, NULL, 0, false); + if (ret) + return ret; + } ret = sunxi_nfc_wait_cmd_fifo_empty(nfc); if (ret) @@ -1460,27 +1505,35 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, return 0; } -static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand, - u8 *oob, int *cur_off, - int page) +static int sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand, + u8 *oob, int *cur_off, + int page) { struct mtd_info *mtd = nand_to_mtd(nand); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc = &nand->ecc; int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len = mtd->oobsize - offset; + int ret; if (len <= 0) - return; + return 0; - if (!cur_off || *cur_off != offset) - nand_change_write_column_op(nand, offset + mtd->writesize, - NULL, 0, false); + if (!cur_off || *cur_off != offset) { + ret = nand_change_write_column_op(nand, offset + mtd->writesize, + NULL, 0, false); + if (ret) + return ret; + } - sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page); + ret = sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page); + if (ret) + return ret; if (cur_off) *cur_off = mtd->oobsize + mtd->writesize; + + return 0; } static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, @@ -1628,8 +1681,8 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand, } if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) - sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, - &cur_off, page); + ret = sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + &cur_off, page); out: sunxi_nfc_hw_ecc_disable(nand); @@ -1754,10 +1807,13 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, if (ret) return ret; - if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) + if (oob_required || (nand->options & NAND_NEED_SCRAMBLING)) { /* TODO: use DMA to transfer extra OOB bytes ? */ - sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, - NULL, page); + ret = sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi, + NULL, page); + if (ret) + return ret; + } return nand_prog_page_end_op(nand);