static int nand_ecc_test(const size_t size) { unsigned char code[3]; unsigned char error_code[3]; char testname[30]; BUG_ON(sizeof(data) < size); sprintf(testname, "nand-ecc-%zu", size); get_random_bytes(data, size); memcpy(error_data, data, size); inject_single_bit_error(error_data, size); __nand_calculate_ecc(data, size, code); __nand_calculate_ecc(error_data, size, error_code); __nand_correct_data(error_data, code, error_code, size); if (!memcmp(data, error_data, size)) { printk(KERN_INFO "mtd_nandecctest: ok - %s\n", testname); return 0; } printk(KERN_ERR "mtd_nandecctest: not ok - %s\n", testname); printk(KERN_DEBUG "hexdump of data:\n"); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4, data, size, false); printk(KERN_DEBUG "hexdump of error data:\n"); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4, error_data, size, false); return -1; }
static int double_bit_error_detect(void *error_data, void *error_ecc, void *correct_data, const size_t size) { unsigned char calc_ecc[3]; int ret; __nand_calculate_ecc(error_data, size, calc_ecc); ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size); return (ret == -EBADMSG) ? 0 : -EINVAL; }
static int single_bit_error_correct(void *error_data, void *error_ecc, void *correct_data, const size_t size) { unsigned char calc_ecc[3]; int ret; __nand_calculate_ecc(error_data, size, calc_ecc); ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size); if (ret == 1 && !memcmp(correct_data, error_data, size)) return 0; return -EINVAL; }
static int nand_ecc_test_run(const size_t size) { int i; int err = 0; void *error_data; void *error_ecc; void *correct_data; void *correct_ecc; error_data = kmalloc(size, GFP_KERNEL); error_ecc = kmalloc(3, GFP_KERNEL); correct_data = kmalloc(size, GFP_KERNEL); correct_ecc = kmalloc(3, GFP_KERNEL); if (!error_data || !error_ecc || !correct_data || !correct_ecc) { err = -ENOMEM; goto error; } prandom_bytes(correct_data, size); __nand_calculate_ecc(correct_data, size, correct_ecc); for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) { nand_ecc_test[i].prepare(error_data, error_ecc, correct_data, correct_ecc, size); err = nand_ecc_test[i].verify(error_data, error_ecc, correct_data, size); if (err) { pr_err("not ok - %s-%zd\n", nand_ecc_test[i].name, size); dump_data_ecc(error_data, error_ecc, correct_data, correct_ecc, size); break; } pr_info("ok - %s-%zd\n", nand_ecc_test[i].name, size); err = mtdtest_relax(); if (err) break; } error: kfree(error_data); kfree(error_ecc); kfree(correct_data); kfree(correct_ecc); return err; }