From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BAFB44E9C11; Fri, 9 Oct 2026 14:44:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791557073; cv=none; b=KqpO1GoYuNuN/A2/l3MxCF8Zn74kdlvHaWEWZmRTSam0LxhHur8Loz8GhzcTrnTJ28zwKWOFeRw9Ovtry1Ts9xim1IzBtwZlG22FEYbRS8jcAWg3DSy6d9F8xcNevleAYuzJDlVySCMnvCFgZm2drc7dzXt/fRhb+uchB2boZyw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791557073; c=relaxed/simple; bh=P8aPVf7ki5QOSTqXx+21yhqVYrIveT6So/rOSy9JnxI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fc3xs1jDnW8aTPGIyfjMoa5gfP2uc3SZjNGSIbrwruLd+FRdkp4V8pKAkJgkf6XrLFT2MqsTOFf5BKvl0EXI1m+9wQqf1q+9S8b156ianYqyNHlfClLLKx8YAWAxzorjj9D+OjPYRSoo57oblYVGnpRHc6hhbMUb4rAdu2UJinA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=ymVxBkcM; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="ymVxBkcM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25B931F000FF; Fri, 9 Oct 2026 14:44:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1791557072; bh=MIt0iSU2RB7U3Ac0/pF57Ek3GKjGbaj5qdA6fL05kp0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ymVxBkcMVnZ/8+Qpb/+FxTl9lvgpiq8aL/pWCyJ1wxCxyTfQOiFM2Sx/t5hna/fxm znuYgFH3mtw/lkPeRv4CN3ubyicWcACqgDOE43TRfWguHSfNkrSIsQDMpunDFRtMXd QFyIDrpFt3BS3XxjECyfh9SaQqNWVgz41fMt9bbY= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Edward Karpicz , Mehmet Fide , Miquel Raynal , Sasha Levin Subject: [PATCH 6.18 342/403] mtd: rawnand: vf610_nfc: fix false bitflips on reads of erased pages Date: Fri, 9 Oct 2026 16:11:43 +0200 Message-ID: <20261009141000.262827711@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261009140952.119038291@linuxfoundation.org> References: <20261009140952.119038291@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Mehmet Fide [ Upstream commit 68fe2faf5c69d0e21f94cd695d28f0ba677d484f ] When the ECC engine fails to decode a page, the driver re-reads the OOB area with the engine bypassed, but runs the erased-page check for the data area on the buffer left in the controller SRAM by the failed transfer. That buffer does not hold what is on the flash: the failing engine writes a bogus single-bit "correction" into it. In the 60-byte ECC mode the all-0xff content of an erased page always decodes to the same error location, so every erased page shows one stale zero bit at data offset 0x5FD, which the erased-page check then reports as a corrected bitflip. Edward Karpicz discovered this behaviour and identified the offset on a Colibri VF61; the analysis and the fix build on his finding. Measured with an instrumented driver on a Colibri VF50 (MX30LF1G18AC, 32-bit ECC): reading a 126 MiB partition with nanddump increased the corrected counter by 18035, exactly one per erased page, while raw reads of the same pages return clean 0xff. A v4.4 kernel on the VF61 (MX30LF4G28AC) accumulates the same false counts, so the behaviour follows the controller rather than the chip or the driver generation. Neither the Vybrid reference manual nor the published mask set errata (VFXXX_2N02G) document it. The 45-byte ECC mode is not affected. Restoring the known byte is not enough: on pages that fail to decode with content other than all-0xff the engine writes its correction wherever the syndrome points (measured at a different offset on such a page), so the check has to run on what the flash holds. Re-read the data area with the ECC engine bypassed, exactly as already done for the OOB area. The corrected counter then stays at zero on both boards. Reported-by: Edward Karpicz Link: https://community.toradex.com/t/colibri-vf50-vf61-on-the-current-bsp-mainline-u-boot-v2026-07-and-linux-6-18-lts/30735 Signed-off-by: Mehmet Fide Signed-off-by: Miquel Raynal Signed-off-by: Sasha Levin --- drivers/mtd/nand/raw/vf610_nfc.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index b6b443f7ffbbc..0f8f0337fde83 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -519,6 +519,7 @@ static inline int vf610_nfc_correct_data(struct nand_chip *chip, uint8_t *dat, u8 ecc_status; u8 ecc_count; int flips_threshold = nfc->chip.ecc.strength / 2; + int ret; ecc_status = vf610_nfc_read(nfc, ecc_status_off) & 0xff; ecc_count = ecc_status & ECC_STATUS_ERR_COUNT; @@ -526,15 +527,21 @@ static inline int vf610_nfc_correct_data(struct nand_chip *chip, uint8_t *dat, if (!(ecc_status & ECC_STATUS_MASK)) return ecc_count; + /* The failed decode leaves a bogus correction in SRAM; re-read without ECC */ nfc->data_access = true; - nand_read_oob_op(&nfc->chip, page, 0, oob, vf610_nfc_spare_size(mtd)); + ret = nand_read_page_op(&nfc->chip, page, 0, dat, mtd->writesize); + if (!ret) + ret = nand_read_oob_op(&nfc->chip, page, 0, oob, + vf610_nfc_spare_size(mtd)); nfc->data_access = false; + if (ret) + return ret; /* - * On an erased page, bit count (including OOB) should be zero or - * at least less then half of the ECC strength. + * Run the erased-page check with the driver's historic threshold + * of half the ECC strength. */ - return nand_check_erased_ecc_chunk(dat, nfc->chip.ecc.size, oob, + return nand_check_erased_ecc_chunk(dat, mtd->writesize, oob, vf610_nfc_spare_size(mtd), NULL, 0, flips_threshold); } -- 2.53.0