17126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/kernel.h> 27126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/module.h> 37126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/list.h> 47126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/random.h> 57126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/string.h> 67126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/bitops.h> 77126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/jiffies.h> 87126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/mtd/nand_ecc.h> 97126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 107126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE) 117126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 127126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic void inject_single_bit_error(void *data, size_t size) 137126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{ 147126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita unsigned long offset = random32() % (size * BITS_PER_BYTE); 157126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 167126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita __change_bit(offset, data); 177126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita} 187126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 197126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic unsigned char data[512]; 207126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic unsigned char error_data[512]; 217126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 227126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic int nand_ecc_test(const size_t size) 237126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{ 247126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita unsigned char code[3]; 257126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita unsigned char error_code[3]; 267126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita char testname[30]; 277126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 287126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita BUG_ON(sizeof(data) < size); 297126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 307126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita sprintf(testname, "nand-ecc-%zu", size); 317126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 327126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita get_random_bytes(data, size); 337126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 347126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita memcpy(error_data, data, size); 357126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita inject_single_bit_error(error_data, size); 367126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 377126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita __nand_calculate_ecc(data, size, code); 387126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita __nand_calculate_ecc(error_data, size, error_code); 397126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita __nand_correct_data(error_data, code, error_code, size); 407126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 417126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita if (!memcmp(data, error_data, size)) { 427126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita printk(KERN_INFO "mtd_nandecctest: ok - %s\n", testname); 437126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita return 0; 447126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita } 457126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 467126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita printk(KERN_ERR "mtd_nandecctest: not ok - %s\n", testname); 477126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 487126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita printk(KERN_DEBUG "hexdump of data:\n"); 497126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4, 507126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita data, size, false); 517126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita printk(KERN_DEBUG "hexdump of error data:\n"); 527126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4, 537126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita error_data, size, false); 547126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 557126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita return -1; 567126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita} 577126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 587126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#else 597126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 607126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic int nand_ecc_test(const size_t size) 617126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{ 627126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita return 0; 637126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita} 647126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 657126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#endif 667126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 677126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic int __init ecc_test_init(void) 687126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{ 697126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita srandom32(jiffies); 707126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 717126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita nand_ecc_test(256); 727126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita nand_ecc_test(512); 737126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 747126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita return 0; 757126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita} 767126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 777126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic void __exit ecc_test_exit(void) 787126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{ 797126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita} 807126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 817126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitamodule_init(ecc_test_init); 827126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitamodule_exit(ecc_test_exit); 837126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita 847126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu MitaMODULE_DESCRIPTION("NAND ECC function test module"); 857126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu MitaMODULE_AUTHOR("Akinobu Mita"); 867126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu MitaMODULE_LICENSE("GPL"); 87