Blame view

drivers/mtd/tests/subpagetest.c 10.6 KB
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   * Copyright (C) 2006-2007 Nokia Corporation
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 as published by
   * the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
   * more details.
   *
   * You should have received a copy of the GNU General Public License along with
   * this program; see the file COPYING. If not, write to the Free Software
   * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   *
   * Test sub-page read and write on MTD device.
   * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
   *
   */
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
21
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
22
23
24
25
26
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/err.h>
  #include <linux/mtd/mtd.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
27
  #include <linux/slab.h>
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
28
  #include <linux/sched.h>
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
29
  #include <linux/random.h>
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
30

725cd71c0   Akinobu Mita   mtd: mtd_subpaget...
31
  #include "mtd_test.h"
7406060e2   Wolfram Sang   mtd: tests: don't...
32
  static int dev = -EINVAL;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
33
34
35
36
37
38
39
40
41
42
43
44
45
  module_param(dev, int, S_IRUGO);
  MODULE_PARM_DESC(dev, "MTD device number to use");
  
  static struct mtd_info *mtd;
  static unsigned char *writebuf;
  static unsigned char *readbuf;
  static unsigned char *bbt;
  
  static int subpgsize;
  static int bufsize;
  static int ebcnt;
  static int pgcnt;
  static int errcnt;
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
46
  static struct rnd_state rnd_state;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
47
48
49
50
51
  
  static inline void clear_data(unsigned char *buf, size_t len)
  {
  	memset(buf, 0, len);
  }
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
52
53
  static int write_eraseblock(int ebnum)
  {
30fa98480   Artem Bityutskiy   mtd: remove extra...
54
  	size_t written;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
55
  	int err = 0;
1001ff7a4   Brian Norris   mtd: tests: fix i...
56
  	loff_t addr = (loff_t)ebnum * mtd->erasesize;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
57

a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
58
  	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
eda95cbf7   Artem Bityutskiy   mtd: introduce mt...
59
  	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
60
  	if (unlikely(err || written != subpgsize)) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
61
62
  		pr_err("error: write failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
63
64
  		       (long long)addr);
  		if (written != subpgsize) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
65
66
67
68
  			pr_err("  write size: %#x
  ", subpgsize);
  			pr_err("  written: %#zx
  ", written);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
69
70
71
72
73
  		}
  		return err ? err : -1;
  	}
  
  	addr += subpgsize;
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
74
  	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
eda95cbf7   Artem Bityutskiy   mtd: introduce mt...
75
  	err = mtd_write(mtd, addr, subpgsize, &written, writebuf);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
76
  	if (unlikely(err || written != subpgsize)) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
77
78
  		pr_err("error: write failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
79
80
  		       (long long)addr);
  		if (written != subpgsize) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
81
82
83
84
  			pr_err("  write size: %#x
  ", subpgsize);
  			pr_err("  written: %#zx
  ", written);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
85
86
87
88
89
90
91
92
93
  		}
  		return err ? err : -1;
  	}
  
  	return err;
  }
  
  static int write_eraseblock2(int ebnum)
  {
30fa98480   Artem Bityutskiy   mtd: remove extra...
94
  	size_t written;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
95
  	int err = 0, k;
1001ff7a4   Brian Norris   mtd: tests: fix i...
96
  	loff_t addr = (loff_t)ebnum * mtd->erasesize;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
97
98
99
100
  
  	for (k = 1; k < 33; ++k) {
  		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
  			break;
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
101
  		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
eda95cbf7   Artem Bityutskiy   mtd: introduce mt...
102
  		err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
103
  		if (unlikely(err || written != subpgsize * k)) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
104
105
  			pr_err("error: write failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
106
107
  			       (long long)addr);
  			if (written != subpgsize) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
108
109
  				pr_err("  write size: %#x
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
110
  				       subpgsize * k);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
111
112
  				pr_err("  written: %#08zx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  				       written);
  			}
  			return err ? err : -1;
  		}
  		addr += subpgsize * k;
  	}
  
  	return err;
  }
  
  static void print_subpage(unsigned char *p)
  {
  	int i, j;
  
  	for (i = 0; i < subpgsize; ) {
  		for (j = 0; i < subpgsize && j < 32; ++i, ++j)
  			printk("%02x", *p++);
  		printk("
  ");
  	}
  }
  
  static int verify_eraseblock(int ebnum)
  {
30fa98480   Artem Bityutskiy   mtd: remove extra...
137
  	size_t read;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
138
  	int err = 0;
1001ff7a4   Brian Norris   mtd: tests: fix i...
139
  	loff_t addr = (loff_t)ebnum * mtd->erasesize;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
140

a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
141
  	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
142
  	clear_data(readbuf, subpgsize);
329ad399a   Artem Bityutskiy   mtd: introduce mt...
143
  	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
144
  	if (unlikely(err || read != subpgsize)) {
d57f40544   Brian Norris   mtd: utilize `mtd...
145
  		if (mtd_is_bitflip(err) && read == subpgsize) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
146
147
  			pr_info("ECC correction at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
148
149
150
  			       (long long)addr);
  			err = 0;
  		} else {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
151
152
  			pr_err("error: read failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
153
154
155
156
157
  			       (long long)addr);
  			return err ? err : -1;
  		}
  	}
  	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
158
159
  		pr_err("error: verify failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
160
  		       (long long)addr);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
161
162
  		pr_info("------------- written----------------
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
163
  		print_subpage(writebuf);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
164
165
  		pr_info("------------- read ------------------
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
166
  		print_subpage(readbuf);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
167
168
  		pr_info("-------------------------------------
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
169
170
171
172
  		errcnt += 1;
  	}
  
  	addr += subpgsize;
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
173
  	prandom_bytes_state(&rnd_state, writebuf, subpgsize);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
174
  	clear_data(readbuf, subpgsize);
329ad399a   Artem Bityutskiy   mtd: introduce mt...
175
  	err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
176
  	if (unlikely(err || read != subpgsize)) {
d57f40544   Brian Norris   mtd: utilize `mtd...
177
  		if (mtd_is_bitflip(err) && read == subpgsize) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
178
179
  			pr_info("ECC correction at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
180
181
182
  			       (long long)addr);
  			err = 0;
  		} else {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
183
184
  			pr_err("error: read failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
185
186
187
188
189
  			       (long long)addr);
  			return err ? err : -1;
  		}
  	}
  	if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
190
191
  		pr_info("error: verify failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
192
  		       (long long)addr);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
193
194
  		pr_info("------------- written----------------
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
195
  		print_subpage(writebuf);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
196
197
  		pr_info("------------- read ------------------
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
198
  		print_subpage(readbuf);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
199
200
  		pr_info("-------------------------------------
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
201
202
203
204
205
206
207
208
  		errcnt += 1;
  	}
  
  	return err;
  }
  
  static int verify_eraseblock2(int ebnum)
  {
30fa98480   Artem Bityutskiy   mtd: remove extra...
209
  	size_t read;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
210
  	int err = 0, k;
1001ff7a4   Brian Norris   mtd: tests: fix i...
211
  	loff_t addr = (loff_t)ebnum * mtd->erasesize;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
212
213
214
215
  
  	for (k = 1; k < 33; ++k) {
  		if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
  			break;
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
216
  		prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
217
  		clear_data(readbuf, subpgsize * k);
329ad399a   Artem Bityutskiy   mtd: introduce mt...
218
  		err = mtd_read(mtd, addr, subpgsize * k, &read, readbuf);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
219
  		if (unlikely(err || read != subpgsize * k)) {
d57f40544   Brian Norris   mtd: utilize `mtd...
220
  			if (mtd_is_bitflip(err) && read == subpgsize * k) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
221
222
  				pr_info("ECC correction at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
223
224
225
  				       (long long)addr);
  				err = 0;
  			} else {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
226
  				pr_err("error: read failed at "
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
227
228
229
230
231
232
  				       "%#llx
  ", (long long)addr);
  				return err ? err : -1;
  			}
  		}
  		if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
233
234
  			pr_err("error: verify failed at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
235
236
237
238
239
240
241
242
243
244
245
246
  			       (long long)addr);
  			errcnt += 1;
  		}
  		addr += subpgsize * k;
  	}
  
  	return err;
  }
  
  static int verify_eraseblock_ff(int ebnum)
  {
  	uint32_t j;
30fa98480   Artem Bityutskiy   mtd: remove extra...
247
  	size_t read;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
248
  	int err = 0;
1001ff7a4   Brian Norris   mtd: tests: fix i...
249
  	loff_t addr = (loff_t)ebnum * mtd->erasesize;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
250
251
252
253
  
  	memset(writebuf, 0xff, subpgsize);
  	for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
  		clear_data(readbuf, subpgsize);
329ad399a   Artem Bityutskiy   mtd: introduce mt...
254
  		err = mtd_read(mtd, addr, subpgsize, &read, readbuf);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
255
  		if (unlikely(err || read != subpgsize)) {
d57f40544   Brian Norris   mtd: utilize `mtd...
256
  			if (mtd_is_bitflip(err) && read == subpgsize) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
257
258
  				pr_info("ECC correction at %#llx
  ",
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
259
260
261
  				       (long long)addr);
  				err = 0;
  			} else {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
262
  				pr_err("error: read failed at "
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
263
264
265
266
267
268
  				       "%#llx
  ", (long long)addr);
  				return err ? err : -1;
  			}
  		}
  		if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
269
  			pr_err("error: verify 0xff failed at "
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  			       "%#llx
  ", (long long)addr);
  			errcnt += 1;
  		}
  		addr += subpgsize;
  	}
  
  	return err;
  }
  
  static int verify_all_eraseblocks_ff(void)
  {
  	int err;
  	unsigned int i;
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
284
285
  	pr_info("verifying all eraseblocks for 0xff
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
286
287
288
289
290
291
292
  	for (i = 0; i < ebcnt; ++i) {
  		if (bbt[i])
  			continue;
  		err = verify_eraseblock_ff(i);
  		if (err)
  			return err;
  		if (i % 256 == 0)
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
293
294
  			pr_info("verified up to eraseblock %u
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
295
296
  		cond_resched();
  	}
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
297
298
  	pr_info("verified %u eraseblocks
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
299
300
  	return 0;
  }
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
301
302
303
304
305
306
307
308
309
310
  static int __init mtd_subpagetest_init(void)
  {
  	int err = 0;
  	uint32_t i;
  	uint64_t tmp;
  
  	printk(KERN_INFO "
  ");
  	printk(KERN_INFO "=================================================
  ");
7406060e2   Wolfram Sang   mtd: tests: don't...
311
312
  
  	if (dev < 0) {
064a7694b   Masanari Iida   mtd: Fix typo mtd...
313
314
  		pr_info("Please specify a valid mtd-device via module parameter
  ");
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
315
316
  		pr_crit("CAREFUL: This test wipes all data on the specified MTD device!
  ");
7406060e2   Wolfram Sang   mtd: tests: don't...
317
318
  		return -EINVAL;
  	}
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
319
320
  	pr_info("MTD device: %d
  ", dev);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
321
322
323
324
  
  	mtd = get_mtd_device(NULL, dev);
  	if (IS_ERR(mtd)) {
  		err = PTR_ERR(mtd);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
325
326
  		pr_err("error: cannot get MTD device
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
327
328
  		return err;
  	}
818b97392   Huang Shijie   mtd: nand: add a ...
329
  	if (!mtd_type_is_nand(mtd)) {
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
330
331
  		pr_info("this test requires NAND flash
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
332
333
334
335
  		goto out;
  	}
  
  	subpgsize = mtd->writesize >> mtd->subpage_sft;
7b7e905ec   Roman Tereshonkov   mtd: tests: print...
336
337
338
339
  	tmp = mtd->size;
  	do_div(tmp, mtd->erasesize);
  	ebcnt = tmp;
  	pgcnt = mtd->erasesize / mtd->writesize;
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
340
  	pr_info("MTD device size %llu, eraseblock size %u, "
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
341
342
343
344
345
346
347
348
349
  	       "page size %u, subpage size %u, count of eraseblocks %u, "
  	       "pages per eraseblock %u, OOB size %u
  ",
  	       (unsigned long long)mtd->size, mtd->erasesize,
  	       mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize);
  
  	err = -ENOMEM;
  	bufsize = subpgsize * 32;
  	writebuf = kmalloc(bufsize, GFP_KERNEL);
33777e667   Brian Norris   mtd: tests: don't...
350
  	if (!writebuf)
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
351
  		goto out;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
352
  	readbuf = kmalloc(bufsize, GFP_KERNEL);
33777e667   Brian Norris   mtd: tests: don't...
353
  	if (!readbuf)
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
354
  		goto out;
725cd71c0   Akinobu Mita   mtd: mtd_subpaget...
355
356
357
  	bbt = kzalloc(ebcnt, GFP_KERNEL);
  	if (!bbt)
  		goto out;
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
358

725cd71c0   Akinobu Mita   mtd: mtd_subpaget...
359
  	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
360
361
  	if (err)
  		goto out;
725cd71c0   Akinobu Mita   mtd: mtd_subpaget...
362
  	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
363
364
  	if (err)
  		goto out;
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
365
366
  	pr_info("writing whole device
  ");
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
367
  	prandom_seed_state(&rnd_state, 1);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
368
369
370
371
372
373
374
  	for (i = 0; i < ebcnt; ++i) {
  		if (bbt[i])
  			continue;
  		err = write_eraseblock(i);
  		if (unlikely(err))
  			goto out;
  		if (i % 256 == 0)
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
375
376
  			pr_info("written up to eraseblock %u
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
377
378
  		cond_resched();
  	}
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
379
380
  	pr_info("written %u eraseblocks
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
381

a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
382
  	prandom_seed_state(&rnd_state, 1);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
383
384
  	pr_info("verifying all eraseblocks
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
385
386
387
388
389
390
391
  	for (i = 0; i < ebcnt; ++i) {
  		if (bbt[i])
  			continue;
  		err = verify_eraseblock(i);
  		if (unlikely(err))
  			goto out;
  		if (i % 256 == 0)
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
392
393
  			pr_info("verified up to eraseblock %u
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
394
395
  		cond_resched();
  	}
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
396
397
  	pr_info("verified %u eraseblocks
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
398

725cd71c0   Akinobu Mita   mtd: mtd_subpaget...
399
  	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
400
401
402
403
404
405
406
407
  	if (err)
  		goto out;
  
  	err = verify_all_eraseblocks_ff();
  	if (err)
  		goto out;
  
  	/* Write all eraseblocks */
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
408
  	prandom_seed_state(&rnd_state, 3);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
409
410
  	pr_info("writing whole device
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
411
412
413
414
415
416
417
  	for (i = 0; i < ebcnt; ++i) {
  		if (bbt[i])
  			continue;
  		err = write_eraseblock2(i);
  		if (unlikely(err))
  			goto out;
  		if (i % 256 == 0)
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
418
419
  			pr_info("written up to eraseblock %u
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
420
421
  		cond_resched();
  	}
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
422
423
  	pr_info("written %u eraseblocks
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
424
425
  
  	/* Check all eraseblocks */
a312b78b0   Akinobu Mita   mtd: mtd_subpaget...
426
  	prandom_seed_state(&rnd_state, 3);
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
427
428
  	pr_info("verifying all eraseblocks
  ");
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
429
430
431
432
433
434
435
  	for (i = 0; i < ebcnt; ++i) {
  		if (bbt[i])
  			continue;
  		err = verify_eraseblock2(i);
  		if (unlikely(err))
  			goto out;
  		if (i % 256 == 0)
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
436
437
  			pr_info("verified up to eraseblock %u
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
438
439
  		cond_resched();
  	}
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
440
441
  	pr_info("verified %u eraseblocks
  ", i);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
442

725cd71c0   Akinobu Mita   mtd: mtd_subpaget...
443
  	err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
444
445
446
447
448
449
  	if (err)
  		goto out;
  
  	err = verify_all_eraseblocks_ff();
  	if (err)
  		goto out;
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
450
451
  	pr_info("finished with %d errors
  ", errcnt);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
452
453
454
455
456
457
458
  
  out:
  	kfree(bbt);
  	kfree(readbuf);
  	kfree(writebuf);
  	put_mtd_device(mtd);
  	if (err)
cd66a2df7   Vikram Narayanan   mtd: tests: mtd_s...
459
460
  		pr_info("error %d occurred
  ", err);
bf60862a5   Artem Bityutskiy   MTD: tests: add m...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
  	printk(KERN_INFO "=================================================
  ");
  	return err;
  }
  module_init(mtd_subpagetest_init);
  
  static void __exit mtd_subpagetest_exit(void)
  {
  	return;
  }
  module_exit(mtd_subpagetest_exit);
  
  MODULE_DESCRIPTION("Subpage test module");
  MODULE_AUTHOR("Adrian Hunter");
  MODULE_LICENSE("GPL");