Blame view

drivers/mtd/tests/readtest.c 4.96 KB
72091b688   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-2008 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.
   *
   * Check MTD device read.
   *
   * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
   */
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
21
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
72091b688   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>
72091b688   Artem Bityutskiy   MTD: tests: add m...
28
  #include <linux/sched.h>
bf9c22366   Akinobu Mita   mtd: mtd_readtest...
29
  #include "mtd_test.h"
7406060e2   Wolfram Sang   mtd: tests: don't...
30
  static int dev = -EINVAL;
72091b688   Artem Bityutskiy   MTD: tests: add m...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  module_param(dev, int, S_IRUGO);
  MODULE_PARM_DESC(dev, "MTD device number to use");
  
  static struct mtd_info *mtd;
  static unsigned char *iobuf;
  static unsigned char *iobuf1;
  static unsigned char *bbt;
  
  static int pgsize;
  static int ebcnt;
  static int pgcnt;
  
  static int read_eraseblock_by_page(int ebnum)
  {
72091b688   Artem Bityutskiy   MTD: tests: add m...
45
  	int i, ret, err = 0;
1001ff7a4   Brian Norris   mtd: tests: fix i...
46
  	loff_t addr = (loff_t)ebnum * mtd->erasesize;
72091b688   Artem Bityutskiy   MTD: tests: add m...
47
48
49
50
  	void *buf = iobuf;
  	void *oobbuf = iobuf1;
  
  	for (i = 0; i < pgcnt; i++) {
d8b1e34e2   Christian Herzig   mtd: tests/read: ...
51
  		memset(buf, 0 , pgsize);
bf9c22366   Akinobu Mita   mtd: mtd_readtest...
52
53
  		ret = mtdtest_read(mtd, addr, pgsize, buf);
  		if (ret) {
72091b688   Artem Bityutskiy   MTD: tests: add m...
54
55
  			if (!err)
  				err = ret;
72091b688   Artem Bityutskiy   MTD: tests: add m...
56
57
58
  		}
  		if (mtd->oobsize) {
  			struct mtd_oob_ops ops;
0612b9ddc   Brian Norris   mtd: rename MTD_O...
59
  			ops.mode      = MTD_OPS_PLACE_OOB;
72091b688   Artem Bityutskiy   MTD: tests: add m...
60
61
62
63
64
  			ops.len       = 0;
  			ops.retlen    = 0;
  			ops.ooblen    = mtd->oobsize;
  			ops.oobretlen = 0;
  			ops.ooboffs   = 0;
23d424949   Hannes Eder   trivial: NULL noi...
65
  			ops.datbuf    = NULL;
72091b688   Artem Bityutskiy   MTD: tests: add m...
66
  			ops.oobbuf    = oobbuf;
fd2819bbc   Artem Bityutskiy   mtd: introduce mt...
67
  			ret = mtd_read_oob(mtd, addr, &ops);
d57f40544   Brian Norris   mtd: utilize `mtd...
68
  			if ((ret && !mtd_is_bitflip(ret)) ||
003bc4792   Brian Norris   mtd: tests: ignor...
69
  					ops.oobretlen != mtd->oobsize) {
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
70
  				pr_err("error: read oob failed at "
72091b688   Artem Bityutskiy   MTD: tests: add m...
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  						  "%#llx
  ", (long long)addr);
  				if (!err)
  					err = ret;
  				if (!err)
  					err = -EINVAL;
  			}
  			oobbuf += mtd->oobsize;
  		}
  		addr += pgsize;
  		buf += pgsize;
  	}
  
  	return err;
  }
  
  static void dump_eraseblock(int ebnum)
  {
  	int i, j, n;
  	char line[128];
  	int pg, oob;
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
92
93
  	pr_info("dumping eraseblock %d
  ", ebnum);
72091b688   Artem Bityutskiy   MTD: tests: add m...
94
95
96
97
98
99
100
101
102
103
104
105
106
  	n = mtd->erasesize;
  	for (i = 0; i < n;) {
  		char *p = line;
  
  		p += sprintf(p, "%05x: ", i);
  		for (j = 0; j < 32 && i < n; j++, i++)
  			p += sprintf(p, "%02x", (unsigned int)iobuf[i]);
  		printk(KERN_CRIT "%s
  ", line);
  		cond_resched();
  	}
  	if (!mtd->oobsize)
  		return;
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
107
108
  	pr_info("dumping oob from eraseblock %d
  ", ebnum);
72091b688   Artem Bityutskiy   MTD: tests: add m...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  	n = mtd->oobsize;
  	for (pg = 0, i = 0; pg < pgcnt; pg++)
  		for (oob = 0; oob < n;) {
  			char *p = line;
  
  			p += sprintf(p, "%05x: ", i);
  			for (j = 0; j < 32 && oob < n; j++, oob++, i++)
  				p += sprintf(p, "%02x",
  					     (unsigned int)iobuf1[i]);
  			printk(KERN_CRIT "%s
  ", line);
  			cond_resched();
  		}
  }
72091b688   Artem Bityutskiy   MTD: tests: add m...
123
124
125
126
127
128
129
130
131
  static int __init mtd_readtest_init(void)
  {
  	uint64_t tmp;
  	int err, i;
  
  	printk(KERN_INFO "
  ");
  	printk(KERN_INFO "=================================================
  ");
7406060e2   Wolfram Sang   mtd: tests: don't...
132
133
  
  	if (dev < 0) {
064a7694b   Masanari Iida   mtd: Fix typo mtd...
134
135
  		pr_info("Please specify a valid mtd-device via module parameter
  ");
7406060e2   Wolfram Sang   mtd: tests: don't...
136
137
  		return -EINVAL;
  	}
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
138
139
  	pr_info("MTD device: %d
  ", dev);
72091b688   Artem Bityutskiy   MTD: tests: add m...
140
141
142
143
  
  	mtd = get_mtd_device(NULL, dev);
  	if (IS_ERR(mtd)) {
  		err = PTR_ERR(mtd);
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
144
145
  		pr_err("error: Cannot get MTD device
  ");
72091b688   Artem Bityutskiy   MTD: tests: add m...
146
147
148
149
  		return err;
  	}
  
  	if (mtd->writesize == 1) {
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
150
  		pr_info("not NAND flash, assume page size is 512 "
72091b688   Artem Bityutskiy   MTD: tests: add m...
151
152
153
154
155
156
157
158
159
  		       "bytes.
  ");
  		pgsize = 512;
  	} else
  		pgsize = mtd->writesize;
  
  	tmp = mtd->size;
  	do_div(tmp, mtd->erasesize);
  	ebcnt = tmp;
f5e2bae0a   Morten Thunberg Svendsen   mtd: tests: fix r...
160
  	pgcnt = mtd->erasesize / pgsize;
72091b688   Artem Bityutskiy   MTD: tests: add m...
161

e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
162
  	pr_info("MTD device size %llu, eraseblock size %u, "
72091b688   Artem Bityutskiy   MTD: tests: add m...
163
164
165
166
167
168
169
170
  	       "page size %u, count of eraseblocks %u, pages per "
  	       "eraseblock %u, OOB size %u
  ",
  	       (unsigned long long)mtd->size, mtd->erasesize,
  	       pgsize, ebcnt, pgcnt, mtd->oobsize);
  
  	err = -ENOMEM;
  	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
33777e667   Brian Norris   mtd: tests: don't...
171
  	if (!iobuf)
72091b688   Artem Bityutskiy   MTD: tests: add m...
172
  		goto out;
72091b688   Artem Bityutskiy   MTD: tests: add m...
173
  	iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL);
33777e667   Brian Norris   mtd: tests: don't...
174
  	if (!iobuf1)
72091b688   Artem Bityutskiy   MTD: tests: add m...
175
  		goto out;
72091b688   Artem Bityutskiy   MTD: tests: add m...
176

bf9c22366   Akinobu Mita   mtd: mtd_readtest...
177
178
179
180
  	bbt = kzalloc(ebcnt, GFP_KERNEL);
  	if (!bbt)
  		goto out;
  	err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
72091b688   Artem Bityutskiy   MTD: tests: add m...
181
182
183
184
  	if (err)
  		goto out;
  
  	/* Read all eraseblocks 1 page at a time */
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
185
186
  	pr_info("testing page read
  ");
72091b688   Artem Bityutskiy   MTD: tests: add m...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  	for (i = 0; i < ebcnt; ++i) {
  		int ret;
  
  		if (bbt[i])
  			continue;
  		ret = read_eraseblock_by_page(i);
  		if (ret) {
  			dump_eraseblock(i);
  			if (!err)
  				err = ret;
  		}
  		cond_resched();
  	}
  
  	if (err)
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
202
203
  		pr_info("finished with errors
  ");
72091b688   Artem Bityutskiy   MTD: tests: add m...
204
  	else
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
205
206
  		pr_info("finished
  ");
72091b688   Artem Bityutskiy   MTD: tests: add m...
207
208
209
210
211
212
213
214
  
  out:
  
  	kfree(iobuf);
  	kfree(iobuf1);
  	kfree(bbt);
  	put_mtd_device(mtd);
  	if (err)
e45048a6a   Vikram Narayanan   mtd: tests: mtd_r...
215
216
  		pr_info("error %d occurred
  ", err);
72091b688   Artem Bityutskiy   MTD: tests: add m...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  	printk(KERN_INFO "=================================================
  ");
  	return err;
  }
  module_init(mtd_readtest_init);
  
  static void __exit mtd_readtest_exit(void)
  {
  	return;
  }
  module_exit(mtd_readtest_exit);
  
  MODULE_DESCRIPTION("Read test module");
  MODULE_AUTHOR("Adrian Hunter");
  MODULE_LICENSE("GPL");