diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2013-08-03 05:52:12 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2013-08-30 16:34:19 -0400 |
commit | 59b0816d7c7de3c14d6dd59da3baa3deffb973da (patch) | |
tree | 8a6c50fd8d9c316604bf25e52c780a79909f399f /drivers/mtd/tests | |
parent | bf9c223664e6f5fdf538919c715c45c26dbb4268 (diff) |
mtd: mtd_speedtest: use mtd_test helpers
Use mtdtest_write(), mtdtest_read(), mtdtest_scan_for_bad_eraseblocks(),
mtdtest_erase_good_eraseblocks() in mtd_test helpers.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Vikram Narayanan <vikram186@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/tests')
-rw-r--r-- | drivers/mtd/tests/speedtest.c | 180 |
1 files changed, 36 insertions, 144 deletions
diff --git a/drivers/mtd/tests/speedtest.c b/drivers/mtd/tests/speedtest.c index 20b63d1ad494..457c45c6a704 100644 --- a/drivers/mtd/tests/speedtest.c +++ b/drivers/mtd/tests/speedtest.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/random.h> | 31 | #include <linux/random.h> |
32 | 32 | ||
33 | #include "mtd_test.h" | ||
34 | |||
33 | static int dev = -EINVAL; | 35 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 36 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 37 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -49,33 +51,6 @@ static int pgcnt; | |||
49 | static int goodebcnt; | 51 | static int goodebcnt; |
50 | static struct timeval start, finish; | 52 | static struct timeval start, finish; |
51 | 53 | ||
52 | |||
53 | static int erase_eraseblock(int ebnum) | ||
54 | { | ||
55 | int err; | ||
56 | struct erase_info ei; | ||
57 | loff_t addr = ebnum * mtd->erasesize; | ||
58 | |||
59 | memset(&ei, 0, sizeof(struct erase_info)); | ||
60 | ei.mtd = mtd; | ||
61 | ei.addr = addr; | ||
62 | ei.len = mtd->erasesize; | ||
63 | |||
64 | err = mtd_erase(mtd, &ei); | ||
65 | if (err) { | ||
66 | pr_err("error %d while erasing EB %d\n", err, ebnum); | ||
67 | return err; | ||
68 | } | ||
69 | |||
70 | if (ei.state == MTD_ERASE_FAILED) { | ||
71 | pr_err("some erase error occurred at EB %d\n", | ||
72 | ebnum); | ||
73 | return -EIO; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int multiblock_erase(int ebnum, int blocks) | 54 | static int multiblock_erase(int ebnum, int blocks) |
80 | { | 55 | { |
81 | int err; | 56 | int err; |
@@ -103,52 +78,29 @@ static int multiblock_erase(int ebnum, int blocks) | |||
103 | return 0; | 78 | return 0; |
104 | } | 79 | } |
105 | 80 | ||
106 | static int erase_whole_device(void) | ||
107 | { | ||
108 | int err; | ||
109 | unsigned int i; | ||
110 | |||
111 | for (i = 0; i < ebcnt; ++i) { | ||
112 | if (bbt[i]) | ||
113 | continue; | ||
114 | err = erase_eraseblock(i); | ||
115 | if (err) | ||
116 | return err; | ||
117 | cond_resched(); | ||
118 | } | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int write_eraseblock(int ebnum) | 81 | static int write_eraseblock(int ebnum) |
123 | { | 82 | { |
124 | size_t written; | 83 | int err; |
125 | int err = 0; | ||
126 | loff_t addr = ebnum * mtd->erasesize; | 84 | loff_t addr = ebnum * mtd->erasesize; |
127 | 85 | ||
128 | err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf); | 86 | err = mtdtest_write(mtd, addr, mtd->erasesize, iobuf); |
129 | if (err || written != mtd->erasesize) { | 87 | if (err) |
130 | pr_err("error: write failed at %#llx\n", addr); | 88 | pr_err("error: write failed at %#llx\n", addr); |
131 | if (!err) | ||
132 | err = -EINVAL; | ||
133 | } | ||
134 | 89 | ||
135 | return err; | 90 | return err; |
136 | } | 91 | } |
137 | 92 | ||
138 | static int write_eraseblock_by_page(int ebnum) | 93 | static int write_eraseblock_by_page(int ebnum) |
139 | { | 94 | { |
140 | size_t written; | ||
141 | int i, err = 0; | 95 | int i, err = 0; |
142 | loff_t addr = ebnum * mtd->erasesize; | 96 | loff_t addr = ebnum * mtd->erasesize; |
143 | void *buf = iobuf; | 97 | void *buf = iobuf; |
144 | 98 | ||
145 | for (i = 0; i < pgcnt; i++) { | 99 | for (i = 0; i < pgcnt; i++) { |
146 | err = mtd_write(mtd, addr, pgsize, &written, buf); | 100 | err = mtdtest_write(mtd, addr, pgsize, buf); |
147 | if (err || written != pgsize) { | 101 | if (err) { |
148 | pr_err("error: write failed at %#llx\n", | 102 | pr_err("error: write failed at %#llx\n", |
149 | addr); | 103 | addr); |
150 | if (!err) | ||
151 | err = -EINVAL; | ||
152 | break; | 104 | break; |
153 | } | 105 | } |
154 | addr += pgsize; | 106 | addr += pgsize; |
@@ -160,30 +112,26 @@ static int write_eraseblock_by_page(int ebnum) | |||
160 | 112 | ||
161 | static int write_eraseblock_by_2pages(int ebnum) | 113 | static int write_eraseblock_by_2pages(int ebnum) |
162 | { | 114 | { |
163 | size_t written, sz = pgsize * 2; | 115 | size_t sz = pgsize * 2; |
164 | int i, n = pgcnt / 2, err = 0; | 116 | int i, n = pgcnt / 2, err = 0; |
165 | loff_t addr = ebnum * mtd->erasesize; | 117 | loff_t addr = ebnum * mtd->erasesize; |
166 | void *buf = iobuf; | 118 | void *buf = iobuf; |
167 | 119 | ||
168 | for (i = 0; i < n; i++) { | 120 | for (i = 0; i < n; i++) { |
169 | err = mtd_write(mtd, addr, sz, &written, buf); | 121 | err = mtdtest_write(mtd, addr, sz, buf); |
170 | if (err || written != sz) { | 122 | if (err) { |
171 | pr_err("error: write failed at %#llx\n", | 123 | pr_err("error: write failed at %#llx\n", |
172 | addr); | 124 | addr); |
173 | if (!err) | ||
174 | err = -EINVAL; | ||
175 | return err; | 125 | return err; |
176 | } | 126 | } |
177 | addr += sz; | 127 | addr += sz; |
178 | buf += sz; | 128 | buf += sz; |
179 | } | 129 | } |
180 | if (pgcnt % 2) { | 130 | if (pgcnt % 2) { |
181 | err = mtd_write(mtd, addr, pgsize, &written, buf); | 131 | err = mtdtest_write(mtd, addr, pgsize, buf); |
182 | if (err || written != pgsize) { | 132 | if (err) { |
183 | pr_err("error: write failed at %#llx\n", | 133 | pr_err("error: write failed at %#llx\n", |
184 | addr); | 134 | addr); |
185 | if (!err) | ||
186 | err = -EINVAL; | ||
187 | } | 135 | } |
188 | } | 136 | } |
189 | 137 | ||
@@ -192,40 +140,27 @@ static int write_eraseblock_by_2pages(int ebnum) | |||
192 | 140 | ||
193 | static int read_eraseblock(int ebnum) | 141 | static int read_eraseblock(int ebnum) |
194 | { | 142 | { |
195 | size_t read; | 143 | int err; |
196 | int err = 0; | ||
197 | loff_t addr = ebnum * mtd->erasesize; | 144 | loff_t addr = ebnum * mtd->erasesize; |
198 | 145 | ||
199 | err = mtd_read(mtd, addr, mtd->erasesize, &read, iobuf); | 146 | err = mtdtest_read(mtd, addr, mtd->erasesize, iobuf); |
200 | /* Ignore corrected ECC errors */ | 147 | if (err) |
201 | if (mtd_is_bitflip(err)) | ||
202 | err = 0; | ||
203 | if (err || read != mtd->erasesize) { | ||
204 | pr_err("error: read failed at %#llx\n", addr); | 148 | pr_err("error: read failed at %#llx\n", addr); |
205 | if (!err) | ||
206 | err = -EINVAL; | ||
207 | } | ||
208 | 149 | ||
209 | return err; | 150 | return err; |
210 | } | 151 | } |
211 | 152 | ||
212 | static int read_eraseblock_by_page(int ebnum) | 153 | static int read_eraseblock_by_page(int ebnum) |
213 | { | 154 | { |
214 | size_t read; | ||
215 | int i, err = 0; | 155 | int i, err = 0; |
216 | loff_t addr = ebnum * mtd->erasesize; | 156 | loff_t addr = ebnum * mtd->erasesize; |
217 | void *buf = iobuf; | 157 | void *buf = iobuf; |
218 | 158 | ||
219 | for (i = 0; i < pgcnt; i++) { | 159 | for (i = 0; i < pgcnt; i++) { |
220 | err = mtd_read(mtd, addr, pgsize, &read, buf); | 160 | err = mtdtest_read(mtd, addr, pgsize, buf); |
221 | /* Ignore corrected ECC errors */ | 161 | if (err) { |
222 | if (mtd_is_bitflip(err)) | ||
223 | err = 0; | ||
224 | if (err || read != pgsize) { | ||
225 | pr_err("error: read failed at %#llx\n", | 162 | pr_err("error: read failed at %#llx\n", |
226 | addr); | 163 | addr); |
227 | if (!err) | ||
228 | err = -EINVAL; | ||
229 | break; | 164 | break; |
230 | } | 165 | } |
231 | addr += pgsize; | 166 | addr += pgsize; |
@@ -237,53 +172,32 @@ static int read_eraseblock_by_page(int ebnum) | |||
237 | 172 | ||
238 | static int read_eraseblock_by_2pages(int ebnum) | 173 | static int read_eraseblock_by_2pages(int ebnum) |
239 | { | 174 | { |
240 | size_t read, sz = pgsize * 2; | 175 | size_t sz = pgsize * 2; |
241 | int i, n = pgcnt / 2, err = 0; | 176 | int i, n = pgcnt / 2, err = 0; |
242 | loff_t addr = ebnum * mtd->erasesize; | 177 | loff_t addr = ebnum * mtd->erasesize; |
243 | void *buf = iobuf; | 178 | void *buf = iobuf; |
244 | 179 | ||
245 | for (i = 0; i < n; i++) { | 180 | for (i = 0; i < n; i++) { |
246 | err = mtd_read(mtd, addr, sz, &read, buf); | 181 | err = mtdtest_read(mtd, addr, sz, buf); |
247 | /* Ignore corrected ECC errors */ | 182 | if (err) { |
248 | if (mtd_is_bitflip(err)) | ||
249 | err = 0; | ||
250 | if (err || read != sz) { | ||
251 | pr_err("error: read failed at %#llx\n", | 183 | pr_err("error: read failed at %#llx\n", |
252 | addr); | 184 | addr); |
253 | if (!err) | ||
254 | err = -EINVAL; | ||
255 | return err; | 185 | return err; |
256 | } | 186 | } |
257 | addr += sz; | 187 | addr += sz; |
258 | buf += sz; | 188 | buf += sz; |
259 | } | 189 | } |
260 | if (pgcnt % 2) { | 190 | if (pgcnt % 2) { |
261 | err = mtd_read(mtd, addr, pgsize, &read, buf); | 191 | err = mtdtest_read(mtd, addr, pgsize, buf); |
262 | /* Ignore corrected ECC errors */ | 192 | if (err) { |
263 | if (mtd_is_bitflip(err)) | ||
264 | err = 0; | ||
265 | if (err || read != pgsize) { | ||
266 | pr_err("error: read failed at %#llx\n", | 193 | pr_err("error: read failed at %#llx\n", |
267 | addr); | 194 | addr); |
268 | if (!err) | ||
269 | err = -EINVAL; | ||
270 | } | 195 | } |
271 | } | 196 | } |
272 | 197 | ||
273 | return err; | 198 | return err; |
274 | } | 199 | } |
275 | 200 | ||
276 | static int is_block_bad(int ebnum) | ||
277 | { | ||
278 | loff_t addr = ebnum * mtd->erasesize; | ||
279 | int ret; | ||
280 | |||
281 | ret = mtd_block_isbad(mtd, addr); | ||
282 | if (ret) | ||
283 | pr_info("block %d is bad\n", ebnum); | ||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | static inline void start_timing(void) | 201 | static inline void start_timing(void) |
288 | { | 202 | { |
289 | do_gettimeofday(&start); | 203 | do_gettimeofday(&start); |
@@ -308,30 +222,6 @@ static long calc_speed(void) | |||
308 | return k; | 222 | return k; |
309 | } | 223 | } |
310 | 224 | ||
311 | static int scan_for_bad_eraseblocks(void) | ||
312 | { | ||
313 | int i, bad = 0; | ||
314 | |||
315 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
316 | if (!bbt) | ||
317 | return -ENOMEM; | ||
318 | |||
319 | if (!mtd_can_have_bb(mtd)) | ||
320 | goto out; | ||
321 | |||
322 | pr_info("scanning for bad eraseblocks\n"); | ||
323 | for (i = 0; i < ebcnt; ++i) { | ||
324 | bbt[i] = is_block_bad(i) ? 1 : 0; | ||
325 | if (bbt[i]) | ||
326 | bad += 1; | ||
327 | cond_resched(); | ||
328 | } | ||
329 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
330 | out: | ||
331 | goodebcnt = ebcnt - bad; | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int __init mtd_speedtest_init(void) | 225 | static int __init mtd_speedtest_init(void) |
336 | { | 226 | { |
337 | int err, i, blocks, j, k; | 227 | int err, i, blocks, j, k; |
@@ -387,11 +277,18 @@ static int __init mtd_speedtest_init(void) | |||
387 | 277 | ||
388 | prandom_bytes(iobuf, mtd->erasesize); | 278 | prandom_bytes(iobuf, mtd->erasesize); |
389 | 279 | ||
390 | err = scan_for_bad_eraseblocks(); | 280 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
281 | if (!bbt) | ||
282 | goto out; | ||
283 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); | ||
391 | if (err) | 284 | if (err) |
392 | goto out; | 285 | goto out; |
286 | for (i = 0; i < ebcnt; i++) { | ||
287 | if (!bbt[i]) | ||
288 | goodebcnt++; | ||
289 | } | ||
393 | 290 | ||
394 | err = erase_whole_device(); | 291 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
395 | if (err) | 292 | if (err) |
396 | goto out; | 293 | goto out; |
397 | 294 | ||
@@ -425,7 +322,7 @@ static int __init mtd_speedtest_init(void) | |||
425 | speed = calc_speed(); | 322 | speed = calc_speed(); |
426 | pr_info("eraseblock read speed is %ld KiB/s\n", speed); | 323 | pr_info("eraseblock read speed is %ld KiB/s\n", speed); |
427 | 324 | ||
428 | err = erase_whole_device(); | 325 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
429 | if (err) | 326 | if (err) |
430 | goto out; | 327 | goto out; |
431 | 328 | ||
@@ -459,7 +356,7 @@ static int __init mtd_speedtest_init(void) | |||
459 | speed = calc_speed(); | 356 | speed = calc_speed(); |
460 | pr_info("page read speed is %ld KiB/s\n", speed); | 357 | pr_info("page read speed is %ld KiB/s\n", speed); |
461 | 358 | ||
462 | err = erase_whole_device(); | 359 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
463 | if (err) | 360 | if (err) |
464 | goto out; | 361 | goto out; |
465 | 362 | ||
@@ -496,14 +393,9 @@ static int __init mtd_speedtest_init(void) | |||
496 | /* Erase all eraseblocks */ | 393 | /* Erase all eraseblocks */ |
497 | pr_info("Testing erase speed\n"); | 394 | pr_info("Testing erase speed\n"); |
498 | start_timing(); | 395 | start_timing(); |
499 | for (i = 0; i < ebcnt; ++i) { | 396 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
500 | if (bbt[i]) | 397 | if (err) |
501 | continue; | 398 | goto out; |
502 | err = erase_eraseblock(i); | ||
503 | if (err) | ||
504 | goto out; | ||
505 | cond_resched(); | ||
506 | } | ||
507 | stop_timing(); | 399 | stop_timing(); |
508 | speed = calc_speed(); | 400 | speed = calc_speed(); |
509 | pr_info("erase speed is %ld KiB/s\n", speed); | 401 | pr_info("erase speed is %ld KiB/s\n", speed); |