mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	nand: atmel: Correct bitflips in erased pages
Not correcting anything in case of empty ECC data area is not an appropriate strategy, because an uncorrected bit-flip in an empty sector may cause upper layers (namely UBI) fail to work properly. Therefore the approach chosen in Linux kernel and other u-boot mtd drivers has been adopted, where a heuristic implemented by nand_check_erased_ecc_chunk() is used in order to detect and correct empty sectors. Tested with sama5d3_xplained and sam9x60-ek. Signed-off-by: Kai Stuhlemmer (ebee Engineering) <kai.stuhlemmer@ebee.de> Tested-by: Tudor Ambarus <tudor.ambarus@microchip.com> [ta: reorder if conditions, change commit subject, s/uint8_t/u8.] Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
This commit is contained in:
		
							parent
							
								
									55661ee0e3
								
							
						
					
					
						commit
						32cc2368f8
					
				@ -493,21 +493,9 @@ static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
 | 
			
		||||
{
 | 
			
		||||
	struct nand_chip *nand_chip = mtd_to_nand(mtd);
 | 
			
		||||
	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 | 
			
		||||
	int i, err_nbr, eccbytes;
 | 
			
		||||
	uint8_t *buf_pos;
 | 
			
		||||
	int i, err_nbr;
 | 
			
		||||
	u8 *buf_pos, *ecc_pos;
 | 
			
		||||
 | 
			
		||||
	/* SAMA5D4 PMECC IP can correct errors for all 0xff page */
 | 
			
		||||
	if (host->pmecc_version >= PMECC_VERSION_SAMA5D4)
 | 
			
		||||
		goto normal_check;
 | 
			
		||||
 | 
			
		||||
	eccbytes = nand_chip->ecc.bytes;
 | 
			
		||||
	for (i = 0; i < eccbytes; i++)
 | 
			
		||||
		if (ecc[i] != 0xff)
 | 
			
		||||
			goto normal_check;
 | 
			
		||||
	/* Erased page, return OK */
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
normal_check:
 | 
			
		||||
	for (i = 0; i < host->pmecc_sector_number; i++) {
 | 
			
		||||
		err_nbr = 0;
 | 
			
		||||
		if (pmecc_stat & 0x1) {
 | 
			
		||||
@ -518,15 +506,26 @@ normal_check:
 | 
			
		||||
			pmecc_get_sigma(mtd);
 | 
			
		||||
 | 
			
		||||
			err_nbr = pmecc_err_location(mtd);
 | 
			
		||||
			if (err_nbr == -1) {
 | 
			
		||||
			if (err_nbr >= 0) {
 | 
			
		||||
				pmecc_correct_data(mtd, buf_pos, ecc, i,
 | 
			
		||||
						   host->pmecc_bytes_per_sector,
 | 
			
		||||
						   err_nbr);
 | 
			
		||||
			} else if (host->pmecc_version < PMECC_VERSION_SAMA5D4) {
 | 
			
		||||
				ecc_pos = ecc + i * host->pmecc_bytes_per_sector;
 | 
			
		||||
 | 
			
		||||
				err_nbr = nand_check_erased_ecc_chunk(
 | 
			
		||||
					buf_pos, host->pmecc_sector_size,
 | 
			
		||||
					ecc_pos, host->pmecc_bytes_per_sector,
 | 
			
		||||
					NULL, 0, host->pmecc_corr_cap);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (err_nbr < 0) {
 | 
			
		||||
				dev_err(mtd->dev, "PMECC: Too many errors\n");
 | 
			
		||||
				mtd->ecc_stats.failed++;
 | 
			
		||||
				return -EBADMSG;
 | 
			
		||||
			} else {
 | 
			
		||||
				pmecc_correct_data(mtd, buf_pos, ecc, i,
 | 
			
		||||
					host->pmecc_bytes_per_sector, err_nbr);
 | 
			
		||||
				mtd->ecc_stats.corrected += err_nbr;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			mtd->ecc_stats.corrected += err_nbr;
 | 
			
		||||
		}
 | 
			
		||||
		pmecc_stat >>= 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user