1a995c792SAkinobu Mita /* 2a995c792SAkinobu Mita * Copyright (C) 2006-2008 Nokia Corporation 3a995c792SAkinobu Mita * 4a995c792SAkinobu Mita * This program is free software; you can redistribute it and/or modify it 5a995c792SAkinobu Mita * under the terms of the GNU General Public License version 2 as published by 6a995c792SAkinobu Mita * the Free Software Foundation. 7a995c792SAkinobu Mita * 8a995c792SAkinobu Mita * This program is distributed in the hope that it will be useful, but WITHOUT 9a995c792SAkinobu Mita * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10a995c792SAkinobu Mita * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11a995c792SAkinobu Mita * more details. 12a995c792SAkinobu Mita * 13a995c792SAkinobu Mita * You should have received a copy of the GNU General Public License along with 14a995c792SAkinobu Mita * this program; see the file COPYING. If not, write to the Free Software 15a995c792SAkinobu Mita * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16a995c792SAkinobu Mita * 17a995c792SAkinobu Mita * Test page read and write on MTD device. 18a995c792SAkinobu Mita * 19a995c792SAkinobu Mita * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> 20a995c792SAkinobu Mita */ 21a995c792SAkinobu Mita 22a995c792SAkinobu Mita #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 23a995c792SAkinobu Mita 24a995c792SAkinobu Mita #include <asm/div64.h> 25a995c792SAkinobu Mita #include <linux/init.h> 26a995c792SAkinobu Mita #include <linux/module.h> 27a995c792SAkinobu Mita #include <linux/moduleparam.h> 28a995c792SAkinobu Mita #include <linux/err.h> 29a995c792SAkinobu Mita #include <linux/mtd/mtd.h> 30a995c792SAkinobu Mita #include <linux/slab.h> 31a995c792SAkinobu Mita #include <linux/sched.h> 32a995c792SAkinobu Mita #include <linux/random.h> 33a995c792SAkinobu Mita 3466b28183SAkinobu Mita #include "mtd_test.h" 3566b28183SAkinobu Mita 36a995c792SAkinobu Mita static int dev = -EINVAL; 37a995c792SAkinobu Mita module_param(dev, int, S_IRUGO); 38a995c792SAkinobu Mita MODULE_PARM_DESC(dev, "MTD device number to use"); 39a995c792SAkinobu Mita 40a995c792SAkinobu Mita static struct mtd_info *mtd; 41a995c792SAkinobu Mita static unsigned char *twopages; 42a995c792SAkinobu Mita static unsigned char *writebuf; 43a995c792SAkinobu Mita static unsigned char *boundary; 44a995c792SAkinobu Mita static unsigned char *bbt; 45a995c792SAkinobu Mita 46a995c792SAkinobu Mita static int pgsize; 47a995c792SAkinobu Mita static int bufsize; 48a995c792SAkinobu Mita static int ebcnt; 49a995c792SAkinobu Mita static int pgcnt; 50a995c792SAkinobu Mita static int errcnt; 51a995c792SAkinobu Mita static struct rnd_state rnd_state; 52a995c792SAkinobu Mita 53a995c792SAkinobu Mita static int write_eraseblock(int ebnum) 54a995c792SAkinobu Mita { 5566b28183SAkinobu Mita int err; 56a995c792SAkinobu Mita loff_t addr = ebnum * mtd->erasesize; 57a995c792SAkinobu Mita 58a995c792SAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); 59a995c792SAkinobu Mita cond_resched(); 6066b28183SAkinobu Mita err = mtdtest_write(mtd, addr, mtd->erasesize, writebuf); 6166b28183SAkinobu Mita if (err) 62a995c792SAkinobu Mita pr_err("error: write failed at %#llx\n", 63a995c792SAkinobu Mita (long long)addr); 64a995c792SAkinobu Mita 65a995c792SAkinobu Mita return err; 66a995c792SAkinobu Mita } 67a995c792SAkinobu Mita 68a995c792SAkinobu Mita static int verify_eraseblock(int ebnum) 69a995c792SAkinobu Mita { 70a995c792SAkinobu Mita uint32_t j; 71a995c792SAkinobu Mita int err = 0, i; 72a995c792SAkinobu Mita loff_t addr0, addrn; 73a995c792SAkinobu Mita loff_t addr = ebnum * mtd->erasesize; 74a995c792SAkinobu Mita 75a995c792SAkinobu Mita addr0 = 0; 76a995c792SAkinobu Mita for (i = 0; i < ebcnt && bbt[i]; ++i) 77a995c792SAkinobu Mita addr0 += mtd->erasesize; 78a995c792SAkinobu Mita 79a995c792SAkinobu Mita addrn = mtd->size; 80a995c792SAkinobu Mita for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i) 81a995c792SAkinobu Mita addrn -= mtd->erasesize; 82a995c792SAkinobu Mita 83a995c792SAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); 84a995c792SAkinobu Mita for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { 85a995c792SAkinobu Mita /* Do a read to set the internal dataRAMs to different data */ 8666b28183SAkinobu Mita err = mtdtest_read(mtd, addr0, bufsize, twopages); 8766b28183SAkinobu Mita if (err) { 88a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 89a995c792SAkinobu Mita (long long)addr0); 90a995c792SAkinobu Mita return err; 91a995c792SAkinobu Mita } 9266b28183SAkinobu Mita err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages); 9366b28183SAkinobu Mita if (err) { 94a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 95a995c792SAkinobu Mita (long long)(addrn - bufsize)); 96a995c792SAkinobu Mita return err; 97a995c792SAkinobu Mita } 98a995c792SAkinobu Mita memset(twopages, 0, bufsize); 9966b28183SAkinobu Mita err = mtdtest_read(mtd, addr, bufsize, twopages); 10066b28183SAkinobu Mita if (err) { 101a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 102a995c792SAkinobu Mita (long long)addr); 103a995c792SAkinobu Mita break; 104a995c792SAkinobu Mita } 105a995c792SAkinobu Mita if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { 106a995c792SAkinobu Mita pr_err("error: verify failed at %#llx\n", 107a995c792SAkinobu Mita (long long)addr); 108a995c792SAkinobu Mita errcnt += 1; 109a995c792SAkinobu Mita } 110a995c792SAkinobu Mita } 111a995c792SAkinobu Mita /* Check boundary between eraseblocks */ 112a995c792SAkinobu Mita if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) { 113a995c792SAkinobu Mita struct rnd_state old_state = rnd_state; 114a995c792SAkinobu Mita 115a995c792SAkinobu Mita /* Do a read to set the internal dataRAMs to different data */ 11666b28183SAkinobu Mita err = mtdtest_read(mtd, addr0, bufsize, twopages); 11766b28183SAkinobu Mita if (err) { 118a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 119a995c792SAkinobu Mita (long long)addr0); 120a995c792SAkinobu Mita return err; 121a995c792SAkinobu Mita } 12266b28183SAkinobu Mita err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages); 12366b28183SAkinobu Mita if (err) { 124a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 125a995c792SAkinobu Mita (long long)(addrn - bufsize)); 126a995c792SAkinobu Mita return err; 127a995c792SAkinobu Mita } 128a995c792SAkinobu Mita memset(twopages, 0, bufsize); 12966b28183SAkinobu Mita err = mtdtest_read(mtd, addr, bufsize, twopages); 13066b28183SAkinobu Mita if (err) { 131a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 132a995c792SAkinobu Mita (long long)addr); 133a995c792SAkinobu Mita return err; 134a995c792SAkinobu Mita } 135a995c792SAkinobu Mita memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); 136a995c792SAkinobu Mita prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize); 137a995c792SAkinobu Mita if (memcmp(twopages, boundary, bufsize)) { 138a995c792SAkinobu Mita pr_err("error: verify failed at %#llx\n", 139a995c792SAkinobu Mita (long long)addr); 140a995c792SAkinobu Mita errcnt += 1; 141a995c792SAkinobu Mita } 142a995c792SAkinobu Mita rnd_state = old_state; 143a995c792SAkinobu Mita } 144a995c792SAkinobu Mita return err; 145a995c792SAkinobu Mita } 146a995c792SAkinobu Mita 147a995c792SAkinobu Mita static int crosstest(void) 148a995c792SAkinobu Mita { 149a995c792SAkinobu Mita int err = 0, i; 150a995c792SAkinobu Mita loff_t addr, addr0, addrn; 151a995c792SAkinobu Mita unsigned char *pp1, *pp2, *pp3, *pp4; 152a995c792SAkinobu Mita 153a995c792SAkinobu Mita pr_info("crosstest\n"); 154a995c792SAkinobu Mita pp1 = kmalloc(pgsize * 4, GFP_KERNEL); 155a995c792SAkinobu Mita if (!pp1) 156a995c792SAkinobu Mita return -ENOMEM; 157a995c792SAkinobu Mita pp2 = pp1 + pgsize; 158a995c792SAkinobu Mita pp3 = pp2 + pgsize; 159a995c792SAkinobu Mita pp4 = pp3 + pgsize; 160a995c792SAkinobu Mita memset(pp1, 0, pgsize * 4); 161a995c792SAkinobu Mita 162a995c792SAkinobu Mita addr0 = 0; 163a995c792SAkinobu Mita for (i = 0; i < ebcnt && bbt[i]; ++i) 164a995c792SAkinobu Mita addr0 += mtd->erasesize; 165a995c792SAkinobu Mita 166a995c792SAkinobu Mita addrn = mtd->size; 167a995c792SAkinobu Mita for (i = 0; i < ebcnt && bbt[ebcnt - i - 1]; ++i) 168a995c792SAkinobu Mita addrn -= mtd->erasesize; 169a995c792SAkinobu Mita 170a995c792SAkinobu Mita /* Read 2nd-to-last page to pp1 */ 171a995c792SAkinobu Mita addr = addrn - pgsize - pgsize; 17266b28183SAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, pp1); 17366b28183SAkinobu Mita if (err) { 174a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 175a995c792SAkinobu Mita (long long)addr); 176a995c792SAkinobu Mita kfree(pp1); 177a995c792SAkinobu Mita return err; 178a995c792SAkinobu Mita } 179a995c792SAkinobu Mita 180a995c792SAkinobu Mita /* Read 3rd-to-last page to pp1 */ 181a995c792SAkinobu Mita addr = addrn - pgsize - pgsize - pgsize; 18266b28183SAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, pp1); 18366b28183SAkinobu Mita if (err) { 184a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 185a995c792SAkinobu Mita (long long)addr); 186a995c792SAkinobu Mita kfree(pp1); 187a995c792SAkinobu Mita return err; 188a995c792SAkinobu Mita } 189a995c792SAkinobu Mita 190a995c792SAkinobu Mita /* Read first page to pp2 */ 191a995c792SAkinobu Mita addr = addr0; 192a995c792SAkinobu Mita pr_info("reading page at %#llx\n", (long long)addr); 19366b28183SAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, pp2); 19466b28183SAkinobu Mita if (err) { 195a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 196a995c792SAkinobu Mita (long long)addr); 197a995c792SAkinobu Mita kfree(pp1); 198a995c792SAkinobu Mita return err; 199a995c792SAkinobu Mita } 200a995c792SAkinobu Mita 201a995c792SAkinobu Mita /* Read last page to pp3 */ 202a995c792SAkinobu Mita addr = addrn - pgsize; 203a995c792SAkinobu Mita pr_info("reading page at %#llx\n", (long long)addr); 20466b28183SAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, pp3); 20566b28183SAkinobu Mita if (err) { 206a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 207a995c792SAkinobu Mita (long long)addr); 208a995c792SAkinobu Mita kfree(pp1); 209a995c792SAkinobu Mita return err; 210a995c792SAkinobu Mita } 211a995c792SAkinobu Mita 212a995c792SAkinobu Mita /* Read first page again to pp4 */ 213a995c792SAkinobu Mita addr = addr0; 214a995c792SAkinobu Mita pr_info("reading page at %#llx\n", (long long)addr); 21566b28183SAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, pp4); 21666b28183SAkinobu Mita if (err) { 217a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 218a995c792SAkinobu Mita (long long)addr); 219a995c792SAkinobu Mita kfree(pp1); 220a995c792SAkinobu Mita return err; 221a995c792SAkinobu Mita } 222a995c792SAkinobu Mita 223a995c792SAkinobu Mita /* pp2 and pp4 should be the same */ 224a995c792SAkinobu Mita pr_info("verifying pages read at %#llx match\n", 225a995c792SAkinobu Mita (long long)addr0); 226a995c792SAkinobu Mita if (memcmp(pp2, pp4, pgsize)) { 227a995c792SAkinobu Mita pr_err("verify failed!\n"); 228a995c792SAkinobu Mita errcnt += 1; 229a995c792SAkinobu Mita } else if (!err) 230a995c792SAkinobu Mita pr_info("crosstest ok\n"); 231a995c792SAkinobu Mita kfree(pp1); 232a995c792SAkinobu Mita return err; 233a995c792SAkinobu Mita } 234a995c792SAkinobu Mita 235a995c792SAkinobu Mita static int erasecrosstest(void) 236a995c792SAkinobu Mita { 237a995c792SAkinobu Mita int err = 0, i, ebnum, ebnum2; 238a995c792SAkinobu Mita loff_t addr0; 239a995c792SAkinobu Mita char *readbuf = twopages; 240a995c792SAkinobu Mita 241a995c792SAkinobu Mita pr_info("erasecrosstest\n"); 242a995c792SAkinobu Mita 243a995c792SAkinobu Mita ebnum = 0; 244a995c792SAkinobu Mita addr0 = 0; 245a995c792SAkinobu Mita for (i = 0; i < ebcnt && bbt[i]; ++i) { 246a995c792SAkinobu Mita addr0 += mtd->erasesize; 247a995c792SAkinobu Mita ebnum += 1; 248a995c792SAkinobu Mita } 249a995c792SAkinobu Mita 250a995c792SAkinobu Mita ebnum2 = ebcnt - 1; 251a995c792SAkinobu Mita while (ebnum2 && bbt[ebnum2]) 252a995c792SAkinobu Mita ebnum2 -= 1; 253a995c792SAkinobu Mita 254a995c792SAkinobu Mita pr_info("erasing block %d\n", ebnum); 25566b28183SAkinobu Mita err = mtdtest_erase_eraseblock(mtd, ebnum); 256a995c792SAkinobu Mita if (err) 257a995c792SAkinobu Mita return err; 258a995c792SAkinobu Mita 259a995c792SAkinobu Mita pr_info("writing 1st page of block %d\n", ebnum); 260a995c792SAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, pgsize); 261a995c792SAkinobu Mita strcpy(writebuf, "There is no data like this!"); 26266b28183SAkinobu Mita err = mtdtest_write(mtd, addr0, pgsize, writebuf); 26366b28183SAkinobu Mita if (err) { 264a995c792SAkinobu Mita pr_info("error: write failed at %#llx\n", 265a995c792SAkinobu Mita (long long)addr0); 26666b28183SAkinobu Mita return err; 267a995c792SAkinobu Mita } 268a995c792SAkinobu Mita 269a995c792SAkinobu Mita pr_info("reading 1st page of block %d\n", ebnum); 270a995c792SAkinobu Mita memset(readbuf, 0, pgsize); 27166b28183SAkinobu Mita err = mtdtest_read(mtd, addr0, pgsize, readbuf); 27266b28183SAkinobu Mita if (err) { 273a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 274a995c792SAkinobu Mita (long long)addr0); 27566b28183SAkinobu Mita return err; 276a995c792SAkinobu Mita } 277a995c792SAkinobu Mita 278a995c792SAkinobu Mita pr_info("verifying 1st page of block %d\n", ebnum); 279a995c792SAkinobu Mita if (memcmp(writebuf, readbuf, pgsize)) { 280a995c792SAkinobu Mita pr_err("verify failed!\n"); 281a995c792SAkinobu Mita errcnt += 1; 282a995c792SAkinobu Mita return -1; 283a995c792SAkinobu Mita } 284a995c792SAkinobu Mita 285a995c792SAkinobu Mita pr_info("erasing block %d\n", ebnum); 28666b28183SAkinobu Mita err = mtdtest_erase_eraseblock(mtd, ebnum); 287a995c792SAkinobu Mita if (err) 288a995c792SAkinobu Mita return err; 289a995c792SAkinobu Mita 290a995c792SAkinobu Mita pr_info("writing 1st page of block %d\n", ebnum); 291a995c792SAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, pgsize); 292a995c792SAkinobu Mita strcpy(writebuf, "There is no data like this!"); 29366b28183SAkinobu Mita err = mtdtest_write(mtd, addr0, pgsize, writebuf); 29466b28183SAkinobu Mita if (err) { 295a995c792SAkinobu Mita pr_err("error: write failed at %#llx\n", 296a995c792SAkinobu Mita (long long)addr0); 29766b28183SAkinobu Mita return err; 298a995c792SAkinobu Mita } 299a995c792SAkinobu Mita 300a995c792SAkinobu Mita pr_info("erasing block %d\n", ebnum2); 30166b28183SAkinobu Mita err = mtdtest_erase_eraseblock(mtd, ebnum2); 302a995c792SAkinobu Mita if (err) 303a995c792SAkinobu Mita return err; 304a995c792SAkinobu Mita 305a995c792SAkinobu Mita pr_info("reading 1st page of block %d\n", ebnum); 306a995c792SAkinobu Mita memset(readbuf, 0, pgsize); 30766b28183SAkinobu Mita err = mtdtest_read(mtd, addr0, pgsize, readbuf); 30866b28183SAkinobu Mita if (err) { 309a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 310a995c792SAkinobu Mita (long long)addr0); 31166b28183SAkinobu Mita return err; 312a995c792SAkinobu Mita } 313a995c792SAkinobu Mita 314a995c792SAkinobu Mita pr_info("verifying 1st page of block %d\n", ebnum); 315a995c792SAkinobu Mita if (memcmp(writebuf, readbuf, pgsize)) { 316a995c792SAkinobu Mita pr_err("verify failed!\n"); 317a995c792SAkinobu Mita errcnt += 1; 318a995c792SAkinobu Mita return -1; 319a995c792SAkinobu Mita } 320a995c792SAkinobu Mita 321a995c792SAkinobu Mita if (!err) 322a995c792SAkinobu Mita pr_info("erasecrosstest ok\n"); 323a995c792SAkinobu Mita return err; 324a995c792SAkinobu Mita } 325a995c792SAkinobu Mita 326a995c792SAkinobu Mita static int erasetest(void) 327a995c792SAkinobu Mita { 328a995c792SAkinobu Mita int err = 0, i, ebnum, ok = 1; 329a995c792SAkinobu Mita loff_t addr0; 330a995c792SAkinobu Mita 331a995c792SAkinobu Mita pr_info("erasetest\n"); 332a995c792SAkinobu Mita 333a995c792SAkinobu Mita ebnum = 0; 334a995c792SAkinobu Mita addr0 = 0; 335a995c792SAkinobu Mita for (i = 0; i < ebcnt && bbt[i]; ++i) { 336a995c792SAkinobu Mita addr0 += mtd->erasesize; 337a995c792SAkinobu Mita ebnum += 1; 338a995c792SAkinobu Mita } 339a995c792SAkinobu Mita 340a995c792SAkinobu Mita pr_info("erasing block %d\n", ebnum); 34166b28183SAkinobu Mita err = mtdtest_erase_eraseblock(mtd, ebnum); 342a995c792SAkinobu Mita if (err) 343a995c792SAkinobu Mita return err; 344a995c792SAkinobu Mita 345a995c792SAkinobu Mita pr_info("writing 1st page of block %d\n", ebnum); 346a995c792SAkinobu Mita prandom_bytes_state(&rnd_state, writebuf, pgsize); 34766b28183SAkinobu Mita err = mtdtest_write(mtd, addr0, pgsize, writebuf); 34866b28183SAkinobu Mita if (err) { 349a995c792SAkinobu Mita pr_err("error: write failed at %#llx\n", 350a995c792SAkinobu Mita (long long)addr0); 35166b28183SAkinobu Mita return err; 352a995c792SAkinobu Mita } 353a995c792SAkinobu Mita 354a995c792SAkinobu Mita pr_info("erasing block %d\n", ebnum); 35566b28183SAkinobu Mita err = mtdtest_erase_eraseblock(mtd, ebnum); 356a995c792SAkinobu Mita if (err) 357a995c792SAkinobu Mita return err; 358a995c792SAkinobu Mita 359a995c792SAkinobu Mita pr_info("reading 1st page of block %d\n", ebnum); 36066b28183SAkinobu Mita err = mtdtest_read(mtd, addr0, pgsize, twopages); 36166b28183SAkinobu Mita if (err) { 362a995c792SAkinobu Mita pr_err("error: read failed at %#llx\n", 363a995c792SAkinobu Mita (long long)addr0); 36466b28183SAkinobu Mita return err; 365a995c792SAkinobu Mita } 366a995c792SAkinobu Mita 367a995c792SAkinobu Mita pr_info("verifying 1st page of block %d is all 0xff\n", 368a995c792SAkinobu Mita ebnum); 369a995c792SAkinobu Mita for (i = 0; i < pgsize; ++i) 370a995c792SAkinobu Mita if (twopages[i] != 0xff) { 371a995c792SAkinobu Mita pr_err("verifying all 0xff failed at %d\n", 372a995c792SAkinobu Mita i); 373a995c792SAkinobu Mita errcnt += 1; 374a995c792SAkinobu Mita ok = 0; 375a995c792SAkinobu Mita break; 376a995c792SAkinobu Mita } 377a995c792SAkinobu Mita 378a995c792SAkinobu Mita if (ok && !err) 379a995c792SAkinobu Mita pr_info("erasetest ok\n"); 380a995c792SAkinobu Mita 381a995c792SAkinobu Mita return err; 382a995c792SAkinobu Mita } 383a995c792SAkinobu Mita 384a995c792SAkinobu Mita static int __init mtd_pagetest_init(void) 385a995c792SAkinobu Mita { 386a995c792SAkinobu Mita int err = 0; 387a995c792SAkinobu Mita uint64_t tmp; 388a995c792SAkinobu Mita uint32_t i; 389a995c792SAkinobu Mita 390a995c792SAkinobu Mita printk(KERN_INFO "\n"); 391a995c792SAkinobu Mita printk(KERN_INFO "=================================================\n"); 392a995c792SAkinobu Mita 393a995c792SAkinobu Mita if (dev < 0) { 394a995c792SAkinobu Mita pr_info("Please specify a valid mtd-device via module parameter\n"); 395a995c792SAkinobu Mita pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); 396a995c792SAkinobu Mita return -EINVAL; 397a995c792SAkinobu Mita } 398a995c792SAkinobu Mita 399a995c792SAkinobu Mita pr_info("MTD device: %d\n", dev); 400a995c792SAkinobu Mita 401a995c792SAkinobu Mita mtd = get_mtd_device(NULL, dev); 402a995c792SAkinobu Mita if (IS_ERR(mtd)) { 403a995c792SAkinobu Mita err = PTR_ERR(mtd); 404a995c792SAkinobu Mita pr_err("error: cannot get MTD device\n"); 405a995c792SAkinobu Mita return err; 406a995c792SAkinobu Mita } 407a995c792SAkinobu Mita 408a995c792SAkinobu Mita if (mtd->type != MTD_NANDFLASH) { 409a995c792SAkinobu Mita pr_info("this test requires NAND flash\n"); 410a995c792SAkinobu Mita goto out; 411a995c792SAkinobu Mita } 412a995c792SAkinobu Mita 413a995c792SAkinobu Mita tmp = mtd->size; 414a995c792SAkinobu Mita do_div(tmp, mtd->erasesize); 415a995c792SAkinobu Mita ebcnt = tmp; 416a995c792SAkinobu Mita pgcnt = mtd->erasesize / mtd->writesize; 417a995c792SAkinobu Mita pgsize = mtd->writesize; 418a995c792SAkinobu Mita 419a995c792SAkinobu Mita pr_info("MTD device size %llu, eraseblock size %u, " 420a995c792SAkinobu Mita "page size %u, count of eraseblocks %u, pages per " 421a995c792SAkinobu Mita "eraseblock %u, OOB size %u\n", 422a995c792SAkinobu Mita (unsigned long long)mtd->size, mtd->erasesize, 423a995c792SAkinobu Mita pgsize, ebcnt, pgcnt, mtd->oobsize); 424a995c792SAkinobu Mita 425a995c792SAkinobu Mita err = -ENOMEM; 426a995c792SAkinobu Mita bufsize = pgsize * 2; 427a995c792SAkinobu Mita writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); 428a995c792SAkinobu Mita if (!writebuf) 429a995c792SAkinobu Mita goto out; 430a995c792SAkinobu Mita twopages = kmalloc(bufsize, GFP_KERNEL); 431a995c792SAkinobu Mita if (!twopages) 432a995c792SAkinobu Mita goto out; 433a995c792SAkinobu Mita boundary = kmalloc(bufsize, GFP_KERNEL); 434a995c792SAkinobu Mita if (!boundary) 435a995c792SAkinobu Mita goto out; 436a995c792SAkinobu Mita 43766b28183SAkinobu Mita bbt = kzalloc(ebcnt, GFP_KERNEL); 43866b28183SAkinobu Mita if (!bbt) 43966b28183SAkinobu Mita goto out; 44066b28183SAkinobu Mita err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); 441a995c792SAkinobu Mita if (err) 442a995c792SAkinobu Mita goto out; 443a995c792SAkinobu Mita 444a995c792SAkinobu Mita /* Erase all eraseblocks */ 445a995c792SAkinobu Mita pr_info("erasing whole device\n"); 44666b28183SAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 447a995c792SAkinobu Mita if (err) 448a995c792SAkinobu Mita goto out; 44966b28183SAkinobu Mita pr_info("erased %u eraseblocks\n", ebcnt); 450a995c792SAkinobu Mita 451a995c792SAkinobu Mita /* Write all eraseblocks */ 452a995c792SAkinobu Mita prandom_seed_state(&rnd_state, 1); 453a995c792SAkinobu Mita pr_info("writing whole device\n"); 454a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 455a995c792SAkinobu Mita if (bbt[i]) 456a995c792SAkinobu Mita continue; 457a995c792SAkinobu Mita err = write_eraseblock(i); 458a995c792SAkinobu Mita if (err) 459a995c792SAkinobu Mita goto out; 460a995c792SAkinobu Mita if (i % 256 == 0) 461a995c792SAkinobu Mita pr_info("written up to eraseblock %u\n", i); 462a995c792SAkinobu Mita cond_resched(); 463a995c792SAkinobu Mita } 464a995c792SAkinobu Mita pr_info("written %u eraseblocks\n", i); 465a995c792SAkinobu Mita 466a995c792SAkinobu Mita /* Check all eraseblocks */ 467a995c792SAkinobu Mita prandom_seed_state(&rnd_state, 1); 468a995c792SAkinobu Mita pr_info("verifying all eraseblocks\n"); 469a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 470a995c792SAkinobu Mita if (bbt[i]) 471a995c792SAkinobu Mita continue; 472a995c792SAkinobu Mita err = verify_eraseblock(i); 473a995c792SAkinobu Mita if (err) 474a995c792SAkinobu Mita goto out; 475a995c792SAkinobu Mita if (i % 256 == 0) 476a995c792SAkinobu Mita pr_info("verified up to eraseblock %u\n", i); 477a995c792SAkinobu Mita cond_resched(); 478a995c792SAkinobu Mita } 479a995c792SAkinobu Mita pr_info("verified %u eraseblocks\n", i); 480a995c792SAkinobu Mita 481a995c792SAkinobu Mita err = crosstest(); 482a995c792SAkinobu Mita if (err) 483a995c792SAkinobu Mita goto out; 484a995c792SAkinobu Mita 485a995c792SAkinobu Mita err = erasecrosstest(); 486a995c792SAkinobu Mita if (err) 487a995c792SAkinobu Mita goto out; 488a995c792SAkinobu Mita 489a995c792SAkinobu Mita err = erasetest(); 490a995c792SAkinobu Mita if (err) 491a995c792SAkinobu Mita goto out; 492a995c792SAkinobu Mita 493a995c792SAkinobu Mita pr_info("finished with %d errors\n", errcnt); 494a995c792SAkinobu Mita out: 495a995c792SAkinobu Mita 496a995c792SAkinobu Mita kfree(bbt); 497a995c792SAkinobu Mita kfree(boundary); 498a995c792SAkinobu Mita kfree(twopages); 499a995c792SAkinobu Mita kfree(writebuf); 500a995c792SAkinobu Mita put_mtd_device(mtd); 501a995c792SAkinobu Mita if (err) 502a995c792SAkinobu Mita pr_info("error %d occurred\n", err); 503a995c792SAkinobu Mita printk(KERN_INFO "=================================================\n"); 504a995c792SAkinobu Mita return err; 505a995c792SAkinobu Mita } 506a995c792SAkinobu Mita module_init(mtd_pagetest_init); 507a995c792SAkinobu Mita 508a995c792SAkinobu Mita static void __exit mtd_pagetest_exit(void) 509a995c792SAkinobu Mita { 510a995c792SAkinobu Mita return; 511a995c792SAkinobu Mita } 512a995c792SAkinobu Mita module_exit(mtd_pagetest_exit); 513a995c792SAkinobu Mita 514a995c792SAkinobu Mita MODULE_DESCRIPTION("NAND page test"); 515a995c792SAkinobu Mita MODULE_AUTHOR("Adrian Hunter"); 516a995c792SAkinobu Mita MODULE_LICENSE("GPL"); 517