aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2012-09-07 12:48:07 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-09-29 10:47:37 -0400
commit6060fb42a0bf93015d05c1a857b94894936f40ee (patch)
tree4b28d8730eba19b6f61692b520c7529039fd3605
parentc092b43906098a6879d0fa9f74e5141516b9b856 (diff)
mtd: mtd_nandecctest: rewrite the test routine
This rewrites the entire test routine in order to make it easy to add more tests by later changes and minimize duplication of each tests as much as possible. Now that each test is described by the members of struct nand_ecc_test: - name: descriptive testname - prepare: function to prepare data block and ecc with artifical corruption - verify: function to verify the result of correcting data block Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/tests/mtd_nandecctest.c93
1 files changed, 70 insertions, 23 deletions
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c
index d90daf879c46..204f796ed3e7 100644
--- a/drivers/mtd/tests/mtd_nandecctest.c
+++ b/drivers/mtd/tests/mtd_nandecctest.c
@@ -7,8 +7,24 @@
7#include <linux/slab.h> 7#include <linux/slab.h>
8#include <linux/mtd/nand_ecc.h> 8#include <linux/mtd/nand_ecc.h>
9 9
10/*
11 * Test the implementation for software ECC
12 *
13 * No actual MTD device is needed, So we don't need to warry about losing
14 * important data by human error.
15 *
16 * This covers possible patterns of corruption which can be reliably corrected
17 * or detected.
18 */
19
10#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE) 20#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE)
11 21
22struct nand_ecc_test {
23 const char *name;
24 void (*prepare)(void *, void *, void *, void *, const size_t);
25 int (*verify)(void *, void *, void *, const size_t);
26};
27
12/* 28/*
13 * The reason for this __change_bit_le() instead of __change_bit() is to inject 29 * The reason for this __change_bit_le() instead of __change_bit() is to inject
14 * bit error properly within the region which is not a multiple of 30 * bit error properly within the region which is not a multiple of
@@ -23,13 +39,44 @@
23#error "Unknown byte order" 39#error "Unknown byte order"
24#endif 40#endif
25 41
26static void inject_single_bit_error(void *data, size_t size) 42static void single_bit_error_data(void *error_data, void *correct_data,
43 size_t size)
27{ 44{
28 unsigned int offset = random32() % (size * BITS_PER_BYTE); 45 unsigned int offset = random32() % (size * BITS_PER_BYTE);
29 46
30 __change_bit_le(offset, data); 47 memcpy(error_data, correct_data, size);
48 __change_bit_le(offset, error_data);
49}
50
51static void single_bit_error_in_data(void *error_data, void *error_ecc,
52 void *correct_data, void *correct_ecc, const size_t size)
53{
54 single_bit_error_data(error_data, correct_data, size);
55 memcpy(error_ecc, correct_ecc, 3);
56}
57
58static int single_bit_error_correct(void *error_data, void *error_ecc,
59 void *correct_data, const size_t size)
60{
61 unsigned char calc_ecc[3];
62 int ret;
63
64 __nand_calculate_ecc(error_data, size, calc_ecc);
65 ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size);
66 if (ret == 1 && !memcmp(correct_data, error_data, size))
67 return 0;
68
69 return -EINVAL;
31} 70}
32 71
72static const struct nand_ecc_test nand_ecc_test[] = {
73 {
74 .name = "single-bit-error-in-data-correct",
75 .prepare = single_bit_error_in_data,
76 .verify = single_bit_error_correct,
77 },
78};
79
33static void dump_data_ecc(void *error_data, void *error_ecc, void *correct_data, 80static void dump_data_ecc(void *error_data, void *error_ecc, void *correct_data,
34 void *correct_ecc, const size_t size) 81 void *correct_ecc, const size_t size)
35{ 82{
@@ -46,14 +93,14 @@ static void dump_data_ecc(void *error_data, void *error_ecc, void *correct_data,
46 DUMP_PREFIX_NONE, 16, 1, correct_ecc, 3, false); 93 DUMP_PREFIX_NONE, 16, 1, correct_ecc, 3, false);
47} 94}
48 95
49static int nand_ecc_test(const size_t size) 96static int nand_ecc_test_run(const size_t size)
50{ 97{
98 int i;
51 int err = 0; 99 int err = 0;
52 void *error_data; 100 void *error_data;
53 void *error_ecc; 101 void *error_ecc;
54 void *correct_data; 102 void *correct_data;
55 void *correct_ecc; 103 void *correct_ecc;
56 char testname[30];
57 104
58 error_data = kmalloc(size, GFP_KERNEL); 105 error_data = kmalloc(size, GFP_KERNEL);
59 error_ecc = kmalloc(3, GFP_KERNEL); 106 error_ecc = kmalloc(3, GFP_KERNEL);
@@ -65,25 +112,25 @@ static int nand_ecc_test(const size_t size)
65 goto error; 112 goto error;
66 } 113 }
67 114
68 sprintf(testname, "nand-ecc-%zu", size);
69
70 get_random_bytes(correct_data, size); 115 get_random_bytes(correct_data, size);
71
72 memcpy(error_data, correct_data, size);
73 inject_single_bit_error(error_data, size);
74
75 __nand_calculate_ecc(correct_data, size, correct_ecc); 116 __nand_calculate_ecc(correct_data, size, correct_ecc);
76 __nand_calculate_ecc(error_data, size, error_ecc); 117
77 __nand_correct_data(error_data, correct_ecc, error_ecc, size); 118 for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) {
78 119 nand_ecc_test[i].prepare(error_data, error_ecc,
79 if (memcmp(correct_data, error_data, size)) { 120 correct_data, correct_ecc, size);
80 pr_err("mtd_nandecctest: not ok - %s\n", testname); 121 err = nand_ecc_test[i].verify(error_data, error_ecc,
81 dump_data_ecc(error_data, error_ecc, correct_data, correct_ecc, 122 correct_data, size);
82 size); 123
83 err = -EINVAL; 124 if (err) {
84 goto error; 125 pr_err("mtd_nandecctest: not ok - %s-%zd\n",
126 nand_ecc_test[i].name, size);
127 dump_data_ecc(error_data, error_ecc,
128 correct_data, correct_ecc, size);
129 break;
130 }
131 pr_info("mtd_nandecctest: ok - %s-%zd\n",
132 nand_ecc_test[i].name, size);
85 } 133 }
86 pr_info("mtd_nandecctest: ok - %s\n", testname);
87error: 134error:
88 kfree(error_data); 135 kfree(error_data);
89 kfree(error_ecc); 136 kfree(error_ecc);
@@ -95,7 +142,7 @@ error:
95 142
96#else 143#else
97 144
98static int nand_ecc_test(const size_t size) 145static int nand_ecc_test_run(const size_t size)
99{ 146{
100 return 0; 147 return 0;
101} 148}
@@ -106,11 +153,11 @@ static int __init ecc_test_init(void)
106{ 153{
107 int err; 154 int err;
108 155
109 err = nand_ecc_test(256); 156 err = nand_ecc_test_run(256);
110 if (err) 157 if (err)
111 return err; 158 return err;
112 159
113 return nand_ecc_test(512); 160 return nand_ecc_test_run(512);
114} 161}
115 162
116static void __exit ecc_test_exit(void) 163static void __exit ecc_test_exit(void)