blob: 8eb40b6e6dfa937a611b10c7051848e52271450e [file] [log] [blame]
Thomas Gleixner4cd10352019-05-29 16:57:41 -07001// SPDX-License-Identifier: GPL-2.0-only
Artem Bityutskiye73f2172008-12-08 13:34:16 +02002/*
3 * Copyright (C) 2006-2008 Nokia Corporation
4 *
Artem Bityutskiye73f2172008-12-08 13:34:16 +02005 * Test page read and write on MTD device.
6 *
7 * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
8 */
9
Vikram Narayananbb998412012-10-10 23:07:40 +053010#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
Artem Bityutskiye73f2172008-12-08 13:34:16 +020012#include <asm/div64.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/err.h>
17#include <linux/mtd/mtd.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Artem Bityutskiye73f2172008-12-08 13:34:16 +020019#include <linux/sched.h>
Akinobu Mita825b8cc2013-02-27 17:05:35 -080020#include <linux/random.h>
Artem Bityutskiye73f2172008-12-08 13:34:16 +020021
Akinobu Mita66b28182013-08-03 18:52:10 +090022#include "mtd_test.h"
23
Wolfram Sang74060602011-10-30 00:11:53 +020024static int dev = -EINVAL;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020025module_param(dev, int, S_IRUGO);
26MODULE_PARM_DESC(dev, "MTD device number to use");
27
28static struct mtd_info *mtd;
29static unsigned char *twopages;
30static unsigned char *writebuf;
31static unsigned char *boundary;
32static unsigned char *bbt;
33
34static int pgsize;
35static int bufsize;
36static int ebcnt;
37static int pgcnt;
38static int errcnt;
Akinobu Mita825b8cc2013-02-27 17:05:35 -080039static struct rnd_state rnd_state;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020040
Artem Bityutskiye73f2172008-12-08 13:34:16 +020041static int write_eraseblock(int ebnum)
42{
Brian Norris1001ff7a2014-07-21 19:07:12 -070043 loff_t addr = (loff_t)ebnum * mtd->erasesize;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020044
Akinobu Mita825b8cc2013-02-27 17:05:35 -080045 prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
Artem Bityutskiye73f2172008-12-08 13:34:16 +020046 cond_resched();
Akinobu Mita8a9f4aa2013-08-15 22:55:09 +090047 return mtdtest_write(mtd, addr, mtd->erasesize, writebuf);
Artem Bityutskiye73f2172008-12-08 13:34:16 +020048}
49
50static int verify_eraseblock(int ebnum)
51{
52 uint32_t j;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020053 int err = 0, i;
54 loff_t addr0, addrn;
Brian Norris1001ff7a2014-07-21 19:07:12 -070055 loff_t addr = (loff_t)ebnum * mtd->erasesize;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020056
57 addr0 = 0;
Roel Kluinc6f7e7b2009-07-31 16:21:01 +020058 for (i = 0; i < ebcnt && bbt[i]; ++i)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020059 addr0 += mtd->erasesize;
60
61 addrn = mtd->size;
Roel Kluinc6f7e7b2009-07-31 16:21:01 +020062 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020063 addrn -= mtd->erasesize;
64
Akinobu Mita825b8cc2013-02-27 17:05:35 -080065 prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize);
Artem Bityutskiye73f2172008-12-08 13:34:16 +020066 for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
67 /* Do a read to set the internal dataRAMs to different data */
Akinobu Mita66b28182013-08-03 18:52:10 +090068 err = mtdtest_read(mtd, addr0, bufsize, twopages);
Akinobu Mitaabc173a2013-08-15 22:55:08 +090069 if (err)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020070 return err;
Akinobu Mita66b28182013-08-03 18:52:10 +090071 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
Akinobu Mitaabc173a2013-08-15 22:55:08 +090072 if (err)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020073 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020074 memset(twopages, 0, bufsize);
Akinobu Mita66b28182013-08-03 18:52:10 +090075 err = mtdtest_read(mtd, addr, bufsize, twopages);
Akinobu Mitaabc173a2013-08-15 22:55:08 +090076 if (err)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020077 break;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020078 if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
Vikram Narayananbb998412012-10-10 23:07:40 +053079 pr_err("error: verify failed at %#llx\n",
Artem Bityutskiye73f2172008-12-08 13:34:16 +020080 (long long)addr);
81 errcnt += 1;
82 }
83 }
84 /* Check boundary between eraseblocks */
85 if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
Akinobu Mita825b8cc2013-02-27 17:05:35 -080086 struct rnd_state old_state = rnd_state;
87
Artem Bityutskiye73f2172008-12-08 13:34:16 +020088 /* Do a read to set the internal dataRAMs to different data */
Akinobu Mita66b28182013-08-03 18:52:10 +090089 err = mtdtest_read(mtd, addr0, bufsize, twopages);
Akinobu Mitaabc173a2013-08-15 22:55:08 +090090 if (err)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020091 return err;
Akinobu Mita66b28182013-08-03 18:52:10 +090092 err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages);
Akinobu Mitaabc173a2013-08-15 22:55:08 +090093 if (err)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020094 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020095 memset(twopages, 0, bufsize);
Akinobu Mita66b28182013-08-03 18:52:10 +090096 err = mtdtest_read(mtd, addr, bufsize, twopages);
Akinobu Mitaabc173a2013-08-15 22:55:08 +090097 if (err)
Artem Bityutskiye73f2172008-12-08 13:34:16 +020098 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +020099 memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
Akinobu Mita825b8cc2013-02-27 17:05:35 -0800100 prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200101 if (memcmp(twopages, boundary, bufsize)) {
Vikram Narayananbb998412012-10-10 23:07:40 +0530102 pr_err("error: verify failed at %#llx\n",
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200103 (long long)addr);
104 errcnt += 1;
105 }
Akinobu Mita825b8cc2013-02-27 17:05:35 -0800106 rnd_state = old_state;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200107 }
108 return err;
109}
110
111static int crosstest(void)
112{
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200113 int err = 0, i;
114 loff_t addr, addr0, addrn;
115 unsigned char *pp1, *pp2, *pp3, *pp4;
116
Vikram Narayananbb998412012-10-10 23:07:40 +0530117 pr_info("crosstest\n");
Kees Cook6396bb22018-06-12 14:03:40 -0700118 pp1 = kcalloc(pgsize, 4, GFP_KERNEL);
Brian Norris33777e62013-05-02 14:18:51 -0700119 if (!pp1)
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200120 return -ENOMEM;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200121 pp2 = pp1 + pgsize;
122 pp3 = pp2 + pgsize;
123 pp4 = pp3 + pgsize;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200124
125 addr0 = 0;
Roel Kluinc6f7e7b2009-07-31 16:21:01 +0200126 for (i = 0; i < ebcnt && bbt[i]; ++i)
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200127 addr0 += mtd->erasesize;
128
129 addrn = mtd->size;
Roel Kluinc6f7e7b2009-07-31 16:21:01 +0200130 for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i)
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200131 addrn -= mtd->erasesize;
132
133 /* Read 2nd-to-last page to pp1 */
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200134 addr = addrn - pgsize - pgsize;
Akinobu Mita66b28182013-08-03 18:52:10 +0900135 err = mtdtest_read(mtd, addr, pgsize, pp1);
136 if (err) {
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200137 kfree(pp1);
138 return err;
139 }
140
141 /* Read 3rd-to-last page to pp1 */
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200142 addr = addrn - pgsize - pgsize - pgsize;
Akinobu Mita66b28182013-08-03 18:52:10 +0900143 err = mtdtest_read(mtd, addr, pgsize, pp1);
144 if (err) {
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200145 kfree(pp1);
146 return err;
147 }
148
149 /* Read first page to pp2 */
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200150 addr = addr0;
Vikram Narayananbb998412012-10-10 23:07:40 +0530151 pr_info("reading page at %#llx\n", (long long)addr);
Akinobu Mita66b28182013-08-03 18:52:10 +0900152 err = mtdtest_read(mtd, addr, pgsize, pp2);
153 if (err) {
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200154 kfree(pp1);
155 return err;
156 }
157
158 /* Read last page to pp3 */
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200159 addr = addrn - pgsize;
Vikram Narayananbb998412012-10-10 23:07:40 +0530160 pr_info("reading page at %#llx\n", (long long)addr);
Akinobu Mita66b28182013-08-03 18:52:10 +0900161 err = mtdtest_read(mtd, addr, pgsize, pp3);
162 if (err) {
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200163 kfree(pp1);
164 return err;
165 }
166
167 /* Read first page again to pp4 */
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200168 addr = addr0;
Vikram Narayananbb998412012-10-10 23:07:40 +0530169 pr_info("reading page at %#llx\n", (long long)addr);
Akinobu Mita66b28182013-08-03 18:52:10 +0900170 err = mtdtest_read(mtd, addr, pgsize, pp4);
171 if (err) {
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200172 kfree(pp1);
173 return err;
174 }
175
176 /* pp2 and pp4 should be the same */
Vikram Narayananbb998412012-10-10 23:07:40 +0530177 pr_info("verifying pages read at %#llx match\n",
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200178 (long long)addr0);
179 if (memcmp(pp2, pp4, pgsize)) {
Vikram Narayananbb998412012-10-10 23:07:40 +0530180 pr_err("verify failed!\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200181 errcnt += 1;
182 } else if (!err)
Vikram Narayananbb998412012-10-10 23:07:40 +0530183 pr_info("crosstest ok\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200184 kfree(pp1);
185 return err;
186}
187
188static int erasecrosstest(void)
189{
Roel Kluin7fc14bc2010-07-13 13:24:31 +0300190 int err = 0, i, ebnum, ebnum2;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200191 loff_t addr0;
192 char *readbuf = twopages;
193
Vikram Narayananbb998412012-10-10 23:07:40 +0530194 pr_info("erasecrosstest\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200195
196 ebnum = 0;
197 addr0 = 0;
Roel Kluinc6f7e7b2009-07-31 16:21:01 +0200198 for (i = 0; i < ebcnt && bbt[i]; ++i) {
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200199 addr0 += mtd->erasesize;
200 ebnum += 1;
201 }
202
203 ebnum2 = ebcnt - 1;
204 while (ebnum2 && bbt[ebnum2])
205 ebnum2 -= 1;
206
Vikram Narayananbb998412012-10-10 23:07:40 +0530207 pr_info("erasing block %d\n", ebnum);
Akinobu Mita66b28182013-08-03 18:52:10 +0900208 err = mtdtest_erase_eraseblock(mtd, ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200209 if (err)
210 return err;
211
Vikram Narayananbb998412012-10-10 23:07:40 +0530212 pr_info("writing 1st page of block %d\n", ebnum);
Akinobu Mita825b8cc2013-02-27 17:05:35 -0800213 prandom_bytes_state(&rnd_state, writebuf, pgsize);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200214 strcpy(writebuf, "There is no data like this!");
Akinobu Mita66b28182013-08-03 18:52:10 +0900215 err = mtdtest_write(mtd, addr0, pgsize, writebuf);
Akinobu Mita8a9f4aa2013-08-15 22:55:09 +0900216 if (err)
Akinobu Mita66b28182013-08-03 18:52:10 +0900217 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200218
Vikram Narayananbb998412012-10-10 23:07:40 +0530219 pr_info("reading 1st page of block %d\n", ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200220 memset(readbuf, 0, pgsize);
Akinobu Mita66b28182013-08-03 18:52:10 +0900221 err = mtdtest_read(mtd, addr0, pgsize, readbuf);
Akinobu Mitaabc173a2013-08-15 22:55:08 +0900222 if (err)
Akinobu Mita66b28182013-08-03 18:52:10 +0900223 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200224
Vikram Narayananbb998412012-10-10 23:07:40 +0530225 pr_info("verifying 1st page of block %d\n", ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200226 if (memcmp(writebuf, readbuf, pgsize)) {
Vikram Narayananbb998412012-10-10 23:07:40 +0530227 pr_err("verify failed!\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200228 errcnt += 1;
Roel Kluin7fc14bc2010-07-13 13:24:31 +0300229 return -1;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200230 }
231
Vikram Narayananbb998412012-10-10 23:07:40 +0530232 pr_info("erasing block %d\n", ebnum);
Akinobu Mita66b28182013-08-03 18:52:10 +0900233 err = mtdtest_erase_eraseblock(mtd, ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200234 if (err)
235 return err;
236
Vikram Narayananbb998412012-10-10 23:07:40 +0530237 pr_info("writing 1st page of block %d\n", ebnum);
Akinobu Mita825b8cc2013-02-27 17:05:35 -0800238 prandom_bytes_state(&rnd_state, writebuf, pgsize);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200239 strcpy(writebuf, "There is no data like this!");
Akinobu Mita66b28182013-08-03 18:52:10 +0900240 err = mtdtest_write(mtd, addr0, pgsize, writebuf);
Akinobu Mita8a9f4aa2013-08-15 22:55:09 +0900241 if (err)
Akinobu Mita66b28182013-08-03 18:52:10 +0900242 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200243
Vikram Narayananbb998412012-10-10 23:07:40 +0530244 pr_info("erasing block %d\n", ebnum2);
Akinobu Mita66b28182013-08-03 18:52:10 +0900245 err = mtdtest_erase_eraseblock(mtd, ebnum2);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200246 if (err)
247 return err;
248
Vikram Narayananbb998412012-10-10 23:07:40 +0530249 pr_info("reading 1st page of block %d\n", ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200250 memset(readbuf, 0, pgsize);
Akinobu Mita66b28182013-08-03 18:52:10 +0900251 err = mtdtest_read(mtd, addr0, pgsize, readbuf);
Akinobu Mitaabc173a2013-08-15 22:55:08 +0900252 if (err)
Akinobu Mita66b28182013-08-03 18:52:10 +0900253 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200254
Vikram Narayananbb998412012-10-10 23:07:40 +0530255 pr_info("verifying 1st page of block %d\n", ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200256 if (memcmp(writebuf, readbuf, pgsize)) {
Vikram Narayananbb998412012-10-10 23:07:40 +0530257 pr_err("verify failed!\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200258 errcnt += 1;
Roel Kluin7fc14bc2010-07-13 13:24:31 +0300259 return -1;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200260 }
261
Roel Kluin7fc14bc2010-07-13 13:24:31 +0300262 if (!err)
Vikram Narayananbb998412012-10-10 23:07:40 +0530263 pr_info("erasecrosstest ok\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200264 return err;
265}
266
267static int erasetest(void)
268{
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200269 int err = 0, i, ebnum, ok = 1;
270 loff_t addr0;
271
Vikram Narayananbb998412012-10-10 23:07:40 +0530272 pr_info("erasetest\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200273
274 ebnum = 0;
275 addr0 = 0;
Roel Kluinc6f7e7b2009-07-31 16:21:01 +0200276 for (i = 0; i < ebcnt && bbt[i]; ++i) {
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200277 addr0 += mtd->erasesize;
278 ebnum += 1;
279 }
280
Vikram Narayananbb998412012-10-10 23:07:40 +0530281 pr_info("erasing block %d\n", ebnum);
Akinobu Mita66b28182013-08-03 18:52:10 +0900282 err = mtdtest_erase_eraseblock(mtd, ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200283 if (err)
284 return err;
285
Vikram Narayananbb998412012-10-10 23:07:40 +0530286 pr_info("writing 1st page of block %d\n", ebnum);
Akinobu Mita825b8cc2013-02-27 17:05:35 -0800287 prandom_bytes_state(&rnd_state, writebuf, pgsize);
Akinobu Mita66b28182013-08-03 18:52:10 +0900288 err = mtdtest_write(mtd, addr0, pgsize, writebuf);
Akinobu Mita8a9f4aa2013-08-15 22:55:09 +0900289 if (err)
Akinobu Mita66b28182013-08-03 18:52:10 +0900290 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200291
Vikram Narayananbb998412012-10-10 23:07:40 +0530292 pr_info("erasing block %d\n", ebnum);
Akinobu Mita66b28182013-08-03 18:52:10 +0900293 err = mtdtest_erase_eraseblock(mtd, ebnum);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200294 if (err)
295 return err;
296
Vikram Narayananbb998412012-10-10 23:07:40 +0530297 pr_info("reading 1st page of block %d\n", ebnum);
Akinobu Mita66b28182013-08-03 18:52:10 +0900298 err = mtdtest_read(mtd, addr0, pgsize, twopages);
Akinobu Mitaabc173a2013-08-15 22:55:08 +0900299 if (err)
Akinobu Mita66b28182013-08-03 18:52:10 +0900300 return err;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200301
Vikram Narayananbb998412012-10-10 23:07:40 +0530302 pr_info("verifying 1st page of block %d is all 0xff\n",
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200303 ebnum);
304 for (i = 0; i < pgsize; ++i)
305 if (twopages[i] != 0xff) {
Vikram Narayananbb998412012-10-10 23:07:40 +0530306 pr_err("verifying all 0xff failed at %d\n",
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200307 i);
308 errcnt += 1;
309 ok = 0;
310 break;
311 }
312
313 if (ok && !err)
Vikram Narayananbb998412012-10-10 23:07:40 +0530314 pr_info("erasetest ok\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200315
316 return err;
317}
318
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200319static int __init mtd_pagetest_init(void)
320{
321 int err = 0;
322 uint64_t tmp;
323 uint32_t i;
324
325 printk(KERN_INFO "\n");
326 printk(KERN_INFO "=================================================\n");
Wolfram Sang74060602011-10-30 00:11:53 +0200327
328 if (dev < 0) {
Masanari Iida064a7692012-11-09 23:20:58 +0900329 pr_info("Please specify a valid mtd-device via module parameter\n");
Vikram Narayananbb998412012-10-10 23:07:40 +0530330 pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
Wolfram Sang74060602011-10-30 00:11:53 +0200331 return -EINVAL;
332 }
333
Vikram Narayananbb998412012-10-10 23:07:40 +0530334 pr_info("MTD device: %d\n", dev);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200335
336 mtd = get_mtd_device(NULL, dev);
337 if (IS_ERR(mtd)) {
338 err = PTR_ERR(mtd);
Vikram Narayananbb998412012-10-10 23:07:40 +0530339 pr_err("error: cannot get MTD device\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200340 return err;
341 }
342
Huang Shijie818b9732013-09-25 14:58:17 +0800343 if (!mtd_type_is_nand(mtd)) {
Vikram Narayananbb998412012-10-10 23:07:40 +0530344 pr_info("this test requires NAND flash\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200345 goto out;
346 }
347
348 tmp = mtd->size;
349 do_div(tmp, mtd->erasesize);
350 ebcnt = tmp;
351 pgcnt = mtd->erasesize / mtd->writesize;
Artem Bityutskiy4c2b8a62009-11-27 16:58:08 +0200352 pgsize = mtd->writesize;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200353
Vikram Narayananbb998412012-10-10 23:07:40 +0530354 pr_info("MTD device size %llu, eraseblock size %u, "
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200355 "page size %u, count of eraseblocks %u, pages per "
356 "eraseblock %u, OOB size %u\n",
357 (unsigned long long)mtd->size, mtd->erasesize,
358 pgsize, ebcnt, pgcnt, mtd->oobsize);
359
360 err = -ENOMEM;
361 bufsize = pgsize * 2;
362 writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
Brian Norris33777e62013-05-02 14:18:51 -0700363 if (!writebuf)
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200364 goto out;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200365 twopages = kmalloc(bufsize, GFP_KERNEL);
Brian Norris33777e62013-05-02 14:18:51 -0700366 if (!twopages)
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200367 goto out;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200368 boundary = kmalloc(bufsize, GFP_KERNEL);
Brian Norris33777e62013-05-02 14:18:51 -0700369 if (!boundary)
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200370 goto out;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200371
Akinobu Mita66b28182013-08-03 18:52:10 +0900372 bbt = kzalloc(ebcnt, GFP_KERNEL);
373 if (!bbt)
374 goto out;
375 err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200376 if (err)
377 goto out;
378
379 /* Erase all eraseblocks */
Vikram Narayananbb998412012-10-10 23:07:40 +0530380 pr_info("erasing whole device\n");
Akinobu Mita66b28182013-08-03 18:52:10 +0900381 err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt);
382 if (err)
383 goto out;
384 pr_info("erased %u eraseblocks\n", ebcnt);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200385
386 /* Write all eraseblocks */
Akinobu Mita825b8cc2013-02-27 17:05:35 -0800387 prandom_seed_state(&rnd_state, 1);
Vikram Narayananbb998412012-10-10 23:07:40 +0530388 pr_info("writing whole device\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200389 for (i = 0; i < ebcnt; ++i) {
390 if (bbt[i])
391 continue;
392 err = write_eraseblock(i);
393 if (err)
394 goto out;
395 if (i % 256 == 0)
Vikram Narayananbb998412012-10-10 23:07:40 +0530396 pr_info("written up to eraseblock %u\n", i);
Richard Weinberger2a6a28e72015-03-29 21:52:06 +0200397
398 err = mtdtest_relax();
399 if (err)
400 goto out;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200401 }
Vikram Narayananbb998412012-10-10 23:07:40 +0530402 pr_info("written %u eraseblocks\n", i);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200403
404 /* Check all eraseblocks */
Akinobu Mita825b8cc2013-02-27 17:05:35 -0800405 prandom_seed_state(&rnd_state, 1);
Vikram Narayananbb998412012-10-10 23:07:40 +0530406 pr_info("verifying all eraseblocks\n");
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200407 for (i = 0; i < ebcnt; ++i) {
408 if (bbt[i])
409 continue;
410 err = verify_eraseblock(i);
411 if (err)
412 goto out;
413 if (i % 256 == 0)
Vikram Narayananbb998412012-10-10 23:07:40 +0530414 pr_info("verified up to eraseblock %u\n", i);
Richard Weinberger2a6a28e72015-03-29 21:52:06 +0200415
416 err = mtdtest_relax();
417 if (err)
418 goto out;
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200419 }
Vikram Narayananbb998412012-10-10 23:07:40 +0530420 pr_info("verified %u eraseblocks\n", i);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200421
422 err = crosstest();
423 if (err)
424 goto out;
425
Stefan Agner148a1a52018-03-03 23:26:22 +0100426 if (ebcnt > 1) {
427 err = erasecrosstest();
428 if (err)
429 goto out;
430 } else {
431 pr_info("skipping erasecrosstest, 2 erase blocks needed\n");
432 }
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200433
434 err = erasetest();
435 if (err)
436 goto out;
437
Vikram Narayananbb998412012-10-10 23:07:40 +0530438 pr_info("finished with %d errors\n", errcnt);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200439out:
440
441 kfree(bbt);
442 kfree(boundary);
443 kfree(twopages);
444 kfree(writebuf);
445 put_mtd_device(mtd);
446 if (err)
Vikram Narayananbb998412012-10-10 23:07:40 +0530447 pr_info("error %d occurred\n", err);
Artem Bityutskiye73f2172008-12-08 13:34:16 +0200448 printk(KERN_INFO "=================================================\n");
449 return err;
450}
451module_init(mtd_pagetest_init);
452
453static void __exit mtd_pagetest_exit(void)
454{
455 return;
456}
457module_exit(mtd_pagetest_exit);
458
459MODULE_DESCRIPTION("NAND page test");
460MODULE_AUTHOR("Adrian Hunter");
461MODULE_LICENSE("GPL");