1*4cd10358SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 272069be9SArtem Bityutskiy /* 372069be9SArtem Bityutskiy * Copyright (C) 2007 Nokia Corporation 472069be9SArtem Bityutskiy * 572069be9SArtem Bityutskiy * Test read and write speed of a MTD device. 672069be9SArtem Bityutskiy * 7fc7fe769SAdrian Hunter * Author: Adrian Hunter <adrian.hunter@nokia.com> 872069be9SArtem Bityutskiy */ 972069be9SArtem Bityutskiy 102c70d292SVikram Narayanan #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 112c70d292SVikram Narayanan 1272069be9SArtem Bityutskiy #include <linux/init.h> 13af30c0a0SShraddha Barke #include <linux/ktime.h> 1472069be9SArtem Bityutskiy #include <linux/module.h> 1572069be9SArtem Bityutskiy #include <linux/moduleparam.h> 1672069be9SArtem Bityutskiy #include <linux/err.h> 1772069be9SArtem Bityutskiy #include <linux/mtd/mtd.h> 185a0e3ad6STejun Heo #include <linux/slab.h> 1972069be9SArtem Bityutskiy #include <linux/sched.h> 20bfea1d4eSArtem Bityutskiy #include <linux/random.h> 2172069be9SArtem Bityutskiy 2259b0816dSAkinobu Mita #include "mtd_test.h" 2359b0816dSAkinobu Mita 247406060eSWolfram Sang static int dev = -EINVAL; 2572069be9SArtem Bityutskiy module_param(dev, int, S_IRUGO); 2672069be9SArtem Bityutskiy MODULE_PARM_DESC(dev, "MTD device number to use"); 2772069be9SArtem Bityutskiy 28fc7fe769SAdrian Hunter static int count; 29fc7fe769SAdrian Hunter module_param(count, int, S_IRUGO); 30fc7fe769SAdrian Hunter MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use " 31fc7fe769SAdrian Hunter "(0 means use all)"); 32fc7fe769SAdrian Hunter 3372069be9SArtem Bityutskiy static struct mtd_info *mtd; 3472069be9SArtem Bityutskiy static unsigned char *iobuf; 3572069be9SArtem Bityutskiy static unsigned char *bbt; 3672069be9SArtem Bityutskiy 3772069be9SArtem Bityutskiy static int pgsize; 3872069be9SArtem Bityutskiy static int ebcnt; 3972069be9SArtem Bityutskiy static int pgcnt; 4072069be9SArtem Bityutskiy static int goodebcnt; 41af30c0a0SShraddha Barke static ktime_t start, finish; 4272069be9SArtem Bityutskiy 434085bcc6SRoman Tereshonkov static int multiblock_erase(int ebnum, int blocks) 444085bcc6SRoman Tereshonkov { 454085bcc6SRoman Tereshonkov int err; 464085bcc6SRoman Tereshonkov struct erase_info ei; 471001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 484085bcc6SRoman Tereshonkov 494085bcc6SRoman Tereshonkov memset(&ei, 0, sizeof(struct erase_info)); 504085bcc6SRoman Tereshonkov ei.addr = addr; 514085bcc6SRoman Tereshonkov ei.len = mtd->erasesize * blocks; 524085bcc6SRoman Tereshonkov 537e1f0dc0SArtem Bityutskiy err = mtd_erase(mtd, &ei); 544085bcc6SRoman Tereshonkov if (err) { 552c70d292SVikram Narayanan pr_err("error %d while erasing EB %d, blocks %d\n", 564085bcc6SRoman Tereshonkov err, ebnum, blocks); 574085bcc6SRoman Tereshonkov return err; 584085bcc6SRoman Tereshonkov } 594085bcc6SRoman Tereshonkov 604085bcc6SRoman Tereshonkov return 0; 614085bcc6SRoman Tereshonkov } 624085bcc6SRoman Tereshonkov 6372069be9SArtem Bityutskiy static int write_eraseblock(int ebnum) 6472069be9SArtem Bityutskiy { 651001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 6672069be9SArtem Bityutskiy 678a9f4aa3SAkinobu Mita return mtdtest_write(mtd, addr, mtd->erasesize, iobuf); 6872069be9SArtem Bityutskiy } 6972069be9SArtem Bityutskiy 7072069be9SArtem Bityutskiy static int write_eraseblock_by_page(int ebnum) 7172069be9SArtem Bityutskiy { 7272069be9SArtem Bityutskiy int i, err = 0; 731001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 7472069be9SArtem Bityutskiy void *buf = iobuf; 7572069be9SArtem Bityutskiy 7672069be9SArtem Bityutskiy for (i = 0; i < pgcnt; i++) { 7759b0816dSAkinobu Mita err = mtdtest_write(mtd, addr, pgsize, buf); 788a9f4aa3SAkinobu Mita if (err) 7972069be9SArtem Bityutskiy break; 8072069be9SArtem Bityutskiy addr += pgsize; 8172069be9SArtem Bityutskiy buf += pgsize; 8272069be9SArtem Bityutskiy } 8372069be9SArtem Bityutskiy 8472069be9SArtem Bityutskiy return err; 8572069be9SArtem Bityutskiy } 8672069be9SArtem Bityutskiy 8772069be9SArtem Bityutskiy static int write_eraseblock_by_2pages(int ebnum) 8872069be9SArtem Bityutskiy { 8959b0816dSAkinobu Mita size_t sz = pgsize * 2; 9072069be9SArtem Bityutskiy int i, n = pgcnt / 2, err = 0; 911001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 9272069be9SArtem Bityutskiy void *buf = iobuf; 9372069be9SArtem Bityutskiy 9472069be9SArtem Bityutskiy for (i = 0; i < n; i++) { 9559b0816dSAkinobu Mita err = mtdtest_write(mtd, addr, sz, buf); 968a9f4aa3SAkinobu Mita if (err) 9772069be9SArtem Bityutskiy return err; 9872069be9SArtem Bityutskiy addr += sz; 9972069be9SArtem Bityutskiy buf += sz; 10072069be9SArtem Bityutskiy } 1018a9f4aa3SAkinobu Mita if (pgcnt % 2) 10259b0816dSAkinobu Mita err = mtdtest_write(mtd, addr, pgsize, buf); 10372069be9SArtem Bityutskiy 10472069be9SArtem Bityutskiy return err; 10572069be9SArtem Bityutskiy } 10672069be9SArtem Bityutskiy 10772069be9SArtem Bityutskiy static int read_eraseblock(int ebnum) 10872069be9SArtem Bityutskiy { 1091001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 11072069be9SArtem Bityutskiy 111abc173adSAkinobu Mita return mtdtest_read(mtd, addr, mtd->erasesize, iobuf); 11272069be9SArtem Bityutskiy } 11372069be9SArtem Bityutskiy 11472069be9SArtem Bityutskiy static int read_eraseblock_by_page(int ebnum) 11572069be9SArtem Bityutskiy { 11672069be9SArtem Bityutskiy int i, err = 0; 1171001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 11872069be9SArtem Bityutskiy void *buf = iobuf; 11972069be9SArtem Bityutskiy 12072069be9SArtem Bityutskiy for (i = 0; i < pgcnt; i++) { 12159b0816dSAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, buf); 122abc173adSAkinobu Mita if (err) 12372069be9SArtem Bityutskiy break; 12472069be9SArtem Bityutskiy addr += pgsize; 12572069be9SArtem Bityutskiy buf += pgsize; 12672069be9SArtem Bityutskiy } 12772069be9SArtem Bityutskiy 12872069be9SArtem Bityutskiy return err; 12972069be9SArtem Bityutskiy } 13072069be9SArtem Bityutskiy 13172069be9SArtem Bityutskiy static int read_eraseblock_by_2pages(int ebnum) 13272069be9SArtem Bityutskiy { 13359b0816dSAkinobu Mita size_t sz = pgsize * 2; 13472069be9SArtem Bityutskiy int i, n = pgcnt / 2, err = 0; 1351001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 13672069be9SArtem Bityutskiy void *buf = iobuf; 13772069be9SArtem Bityutskiy 13872069be9SArtem Bityutskiy for (i = 0; i < n; i++) { 13959b0816dSAkinobu Mita err = mtdtest_read(mtd, addr, sz, buf); 140abc173adSAkinobu Mita if (err) 14172069be9SArtem Bityutskiy return err; 14272069be9SArtem Bityutskiy addr += sz; 14372069be9SArtem Bityutskiy buf += sz; 14472069be9SArtem Bityutskiy } 145abc173adSAkinobu Mita if (pgcnt % 2) 14659b0816dSAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, buf); 14772069be9SArtem Bityutskiy 14872069be9SArtem Bityutskiy return err; 14972069be9SArtem Bityutskiy } 15072069be9SArtem Bityutskiy 15172069be9SArtem Bityutskiy static inline void start_timing(void) 15272069be9SArtem Bityutskiy { 153af30c0a0SShraddha Barke start = ktime_get(); 15472069be9SArtem Bityutskiy } 15572069be9SArtem Bityutskiy 15672069be9SArtem Bityutskiy static inline void stop_timing(void) 15772069be9SArtem Bityutskiy { 158af30c0a0SShraddha Barke finish = ktime_get(); 15972069be9SArtem Bityutskiy } 16072069be9SArtem Bityutskiy 16172069be9SArtem Bityutskiy static long calc_speed(void) 16272069be9SArtem Bityutskiy { 163e70727e4SDavid Lambert uint64_t k; 164e70727e4SDavid Lambert long ms; 16572069be9SArtem Bityutskiy 166af30c0a0SShraddha Barke ms = ktime_ms_delta(finish, start); 167e70727e4SDavid Lambert if (ms == 0) 168e70727e4SDavid Lambert return 0; 169b9da8baeSBrian Norris k = (uint64_t)goodebcnt * (mtd->erasesize / 1024) * 1000; 170e70727e4SDavid Lambert do_div(k, ms); 171e70727e4SDavid Lambert return k; 17272069be9SArtem Bityutskiy } 17372069be9SArtem Bityutskiy 17472069be9SArtem Bityutskiy static int __init mtd_speedtest_init(void) 17572069be9SArtem Bityutskiy { 1764085bcc6SRoman Tereshonkov int err, i, blocks, j, k; 17772069be9SArtem Bityutskiy long speed; 17872069be9SArtem Bityutskiy uint64_t tmp; 17972069be9SArtem Bityutskiy 18072069be9SArtem Bityutskiy printk(KERN_INFO "\n"); 18172069be9SArtem Bityutskiy printk(KERN_INFO "=================================================\n"); 1827406060eSWolfram Sang 1837406060eSWolfram Sang if (dev < 0) { 184064a7694SMasanari Iida pr_info("Please specify a valid mtd-device via module parameter\n"); 1852c70d292SVikram Narayanan pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); 1867406060eSWolfram Sang return -EINVAL; 1877406060eSWolfram Sang } 1887406060eSWolfram Sang 189fc7fe769SAdrian Hunter if (count) 1902c70d292SVikram Narayanan pr_info("MTD device: %d count: %d\n", dev, count); 191fc7fe769SAdrian Hunter else 1922c70d292SVikram Narayanan pr_info("MTD device: %d\n", dev); 19372069be9SArtem Bityutskiy 19472069be9SArtem Bityutskiy mtd = get_mtd_device(NULL, dev); 19572069be9SArtem Bityutskiy if (IS_ERR(mtd)) { 19672069be9SArtem Bityutskiy err = PTR_ERR(mtd); 1972c70d292SVikram Narayanan pr_err("error: cannot get MTD device\n"); 19872069be9SArtem Bityutskiy return err; 19972069be9SArtem Bityutskiy } 20072069be9SArtem Bityutskiy 20172069be9SArtem Bityutskiy if (mtd->writesize == 1) { 2022c70d292SVikram Narayanan pr_info("not NAND flash, assume page size is 512 " 20372069be9SArtem Bityutskiy "bytes.\n"); 20472069be9SArtem Bityutskiy pgsize = 512; 20572069be9SArtem Bityutskiy } else 20672069be9SArtem Bityutskiy pgsize = mtd->writesize; 20772069be9SArtem Bityutskiy 20872069be9SArtem Bityutskiy tmp = mtd->size; 20972069be9SArtem Bityutskiy do_div(tmp, mtd->erasesize); 21072069be9SArtem Bityutskiy ebcnt = tmp; 211f5e2bae0SMorten Thunberg Svendsen pgcnt = mtd->erasesize / pgsize; 21272069be9SArtem Bityutskiy 2132c70d292SVikram Narayanan pr_info("MTD device size %llu, eraseblock size %u, " 21472069be9SArtem Bityutskiy "page size %u, count of eraseblocks %u, pages per " 21572069be9SArtem Bityutskiy "eraseblock %u, OOB size %u\n", 21672069be9SArtem Bityutskiy (unsigned long long)mtd->size, mtd->erasesize, 21772069be9SArtem Bityutskiy pgsize, ebcnt, pgcnt, mtd->oobsize); 21872069be9SArtem Bityutskiy 219fc7fe769SAdrian Hunter if (count > 0 && count < ebcnt) 220fc7fe769SAdrian Hunter ebcnt = count; 221fc7fe769SAdrian Hunter 22272069be9SArtem Bityutskiy err = -ENOMEM; 22372069be9SArtem Bityutskiy iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); 22433777e66SBrian Norris if (!iobuf) 22572069be9SArtem Bityutskiy goto out; 22672069be9SArtem Bityutskiy 22799672f32SAkinobu Mita prandom_bytes(iobuf, mtd->erasesize); 22872069be9SArtem Bityutskiy 22959b0816dSAkinobu Mita bbt = kzalloc(ebcnt, GFP_KERNEL); 23059b0816dSAkinobu Mita if (!bbt) 23159b0816dSAkinobu Mita goto out; 23259b0816dSAkinobu Mita err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); 23372069be9SArtem Bityutskiy if (err) 23472069be9SArtem Bityutskiy goto out; 23559b0816dSAkinobu Mita for (i = 0; i < ebcnt; i++) { 23659b0816dSAkinobu Mita if (!bbt[i]) 23759b0816dSAkinobu Mita goodebcnt++; 23859b0816dSAkinobu Mita } 23972069be9SArtem Bityutskiy 24059b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 24172069be9SArtem Bityutskiy if (err) 24272069be9SArtem Bityutskiy goto out; 24372069be9SArtem Bityutskiy 24472069be9SArtem Bityutskiy /* Write all eraseblocks, 1 eraseblock at a time */ 2452c70d292SVikram Narayanan pr_info("testing eraseblock write speed\n"); 24672069be9SArtem Bityutskiy start_timing(); 24772069be9SArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 24872069be9SArtem Bityutskiy if (bbt[i]) 24972069be9SArtem Bityutskiy continue; 25072069be9SArtem Bityutskiy err = write_eraseblock(i); 25172069be9SArtem Bityutskiy if (err) 25272069be9SArtem Bityutskiy goto out; 2532a6a28e7SRichard Weinberger 2542a6a28e7SRichard Weinberger err = mtdtest_relax(); 2552a6a28e7SRichard Weinberger if (err) 2562a6a28e7SRichard Weinberger goto out; 25772069be9SArtem Bityutskiy } 25872069be9SArtem Bityutskiy stop_timing(); 25972069be9SArtem Bityutskiy speed = calc_speed(); 2602c70d292SVikram Narayanan pr_info("eraseblock write speed is %ld KiB/s\n", speed); 26172069be9SArtem Bityutskiy 26272069be9SArtem Bityutskiy /* Read all eraseblocks, 1 eraseblock at a time */ 2632c70d292SVikram Narayanan pr_info("testing eraseblock read speed\n"); 26472069be9SArtem Bityutskiy start_timing(); 26572069be9SArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 26672069be9SArtem Bityutskiy if (bbt[i]) 26772069be9SArtem Bityutskiy continue; 26872069be9SArtem Bityutskiy err = read_eraseblock(i); 26972069be9SArtem Bityutskiy if (err) 27072069be9SArtem Bityutskiy goto out; 2712a6a28e7SRichard Weinberger 2722a6a28e7SRichard Weinberger err = mtdtest_relax(); 2732a6a28e7SRichard Weinberger if (err) 2742a6a28e7SRichard Weinberger goto out; 27572069be9SArtem Bityutskiy } 27672069be9SArtem Bityutskiy stop_timing(); 27772069be9SArtem Bityutskiy speed = calc_speed(); 2782c70d292SVikram Narayanan pr_info("eraseblock read speed is %ld KiB/s\n", speed); 27972069be9SArtem Bityutskiy 28059b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 28172069be9SArtem Bityutskiy if (err) 28272069be9SArtem Bityutskiy goto out; 28372069be9SArtem Bityutskiy 28472069be9SArtem Bityutskiy /* Write all eraseblocks, 1 page at a time */ 2852c70d292SVikram Narayanan pr_info("testing page write speed\n"); 28672069be9SArtem Bityutskiy start_timing(); 28772069be9SArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 28872069be9SArtem Bityutskiy if (bbt[i]) 28972069be9SArtem Bityutskiy continue; 29072069be9SArtem Bityutskiy err = write_eraseblock_by_page(i); 29172069be9SArtem Bityutskiy if (err) 29272069be9SArtem Bityutskiy goto out; 2932a6a28e7SRichard Weinberger 2942a6a28e7SRichard Weinberger err = mtdtest_relax(); 2952a6a28e7SRichard Weinberger if (err) 2962a6a28e7SRichard Weinberger goto out; 29772069be9SArtem Bityutskiy } 29872069be9SArtem Bityutskiy stop_timing(); 29972069be9SArtem Bityutskiy speed = calc_speed(); 3002c70d292SVikram Narayanan pr_info("page write speed is %ld KiB/s\n", speed); 30172069be9SArtem Bityutskiy 30272069be9SArtem Bityutskiy /* Read all eraseblocks, 1 page at a time */ 3032c70d292SVikram Narayanan pr_info("testing page read speed\n"); 30472069be9SArtem Bityutskiy start_timing(); 30572069be9SArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 30672069be9SArtem Bityutskiy if (bbt[i]) 30772069be9SArtem Bityutskiy continue; 30872069be9SArtem Bityutskiy err = read_eraseblock_by_page(i); 30972069be9SArtem Bityutskiy if (err) 31072069be9SArtem Bityutskiy goto out; 3112a6a28e7SRichard Weinberger 3122a6a28e7SRichard Weinberger err = mtdtest_relax(); 3132a6a28e7SRichard Weinberger if (err) 3142a6a28e7SRichard Weinberger goto out; 31572069be9SArtem Bityutskiy } 31672069be9SArtem Bityutskiy stop_timing(); 31772069be9SArtem Bityutskiy speed = calc_speed(); 3182c70d292SVikram Narayanan pr_info("page read speed is %ld KiB/s\n", speed); 31972069be9SArtem Bityutskiy 32059b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 32172069be9SArtem Bityutskiy if (err) 32272069be9SArtem Bityutskiy goto out; 32372069be9SArtem Bityutskiy 32472069be9SArtem Bityutskiy /* Write all eraseblocks, 2 pages at a time */ 3252c70d292SVikram Narayanan pr_info("testing 2 page write speed\n"); 32672069be9SArtem Bityutskiy start_timing(); 32772069be9SArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 32872069be9SArtem Bityutskiy if (bbt[i]) 32972069be9SArtem Bityutskiy continue; 33072069be9SArtem Bityutskiy err = write_eraseblock_by_2pages(i); 33172069be9SArtem Bityutskiy if (err) 33272069be9SArtem Bityutskiy goto out; 3332a6a28e7SRichard Weinberger 3342a6a28e7SRichard Weinberger err = mtdtest_relax(); 3352a6a28e7SRichard Weinberger if (err) 3362a6a28e7SRichard Weinberger goto out; 33772069be9SArtem Bityutskiy } 33872069be9SArtem Bityutskiy stop_timing(); 33972069be9SArtem Bityutskiy speed = calc_speed(); 3402c70d292SVikram Narayanan pr_info("2 page write speed is %ld KiB/s\n", speed); 34172069be9SArtem Bityutskiy 34272069be9SArtem Bityutskiy /* Read all eraseblocks, 2 pages at a time */ 3432c70d292SVikram Narayanan pr_info("testing 2 page read speed\n"); 34472069be9SArtem Bityutskiy start_timing(); 34572069be9SArtem Bityutskiy for (i = 0; i < ebcnt; ++i) { 34672069be9SArtem Bityutskiy if (bbt[i]) 34772069be9SArtem Bityutskiy continue; 34872069be9SArtem Bityutskiy err = read_eraseblock_by_2pages(i); 34972069be9SArtem Bityutskiy if (err) 35072069be9SArtem Bityutskiy goto out; 3512a6a28e7SRichard Weinberger 3522a6a28e7SRichard Weinberger err = mtdtest_relax(); 3532a6a28e7SRichard Weinberger if (err) 3542a6a28e7SRichard Weinberger goto out; 35572069be9SArtem Bityutskiy } 35672069be9SArtem Bityutskiy stop_timing(); 35772069be9SArtem Bityutskiy speed = calc_speed(); 3582c70d292SVikram Narayanan pr_info("2 page read speed is %ld KiB/s\n", speed); 35972069be9SArtem Bityutskiy 36072069be9SArtem Bityutskiy /* Erase all eraseblocks */ 3612c70d292SVikram Narayanan pr_info("Testing erase speed\n"); 36272069be9SArtem Bityutskiy start_timing(); 36359b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 36472069be9SArtem Bityutskiy if (err) 36572069be9SArtem Bityutskiy goto out; 36672069be9SArtem Bityutskiy stop_timing(); 36772069be9SArtem Bityutskiy speed = calc_speed(); 3682c70d292SVikram Narayanan pr_info("erase speed is %ld KiB/s\n", speed); 36972069be9SArtem Bityutskiy 3704085bcc6SRoman Tereshonkov /* Multi-block erase all eraseblocks */ 3714085bcc6SRoman Tereshonkov for (k = 1; k < 7; k++) { 3724085bcc6SRoman Tereshonkov blocks = 1 << k; 3732c70d292SVikram Narayanan pr_info("Testing %dx multi-block erase speed\n", 3744085bcc6SRoman Tereshonkov blocks); 3754085bcc6SRoman Tereshonkov start_timing(); 3764085bcc6SRoman Tereshonkov for (i = 0; i < ebcnt; ) { 3774085bcc6SRoman Tereshonkov for (j = 0; j < blocks && (i + j) < ebcnt; j++) 3784085bcc6SRoman Tereshonkov if (bbt[i + j]) 3794085bcc6SRoman Tereshonkov break; 3804085bcc6SRoman Tereshonkov if (j < 1) { 3814085bcc6SRoman Tereshonkov i++; 3824085bcc6SRoman Tereshonkov continue; 3834085bcc6SRoman Tereshonkov } 3844085bcc6SRoman Tereshonkov err = multiblock_erase(i, j); 3854085bcc6SRoman Tereshonkov if (err) 3864085bcc6SRoman Tereshonkov goto out; 3872a6a28e7SRichard Weinberger 3882a6a28e7SRichard Weinberger err = mtdtest_relax(); 3892a6a28e7SRichard Weinberger if (err) 3902a6a28e7SRichard Weinberger goto out; 3912a6a28e7SRichard Weinberger 3924085bcc6SRoman Tereshonkov i += j; 3934085bcc6SRoman Tereshonkov } 3944085bcc6SRoman Tereshonkov stop_timing(); 3954085bcc6SRoman Tereshonkov speed = calc_speed(); 3962c70d292SVikram Narayanan pr_info("%dx multi-block erase speed is %ld KiB/s\n", 3974085bcc6SRoman Tereshonkov blocks, speed); 3984085bcc6SRoman Tereshonkov } 3992c70d292SVikram Narayanan pr_info("finished\n"); 40072069be9SArtem Bityutskiy out: 40172069be9SArtem Bityutskiy kfree(iobuf); 40272069be9SArtem Bityutskiy kfree(bbt); 40372069be9SArtem Bityutskiy put_mtd_device(mtd); 40472069be9SArtem Bityutskiy if (err) 4052c70d292SVikram Narayanan pr_info("error %d occurred\n", err); 40672069be9SArtem Bityutskiy printk(KERN_INFO "=================================================\n"); 40772069be9SArtem Bityutskiy return err; 40872069be9SArtem Bityutskiy } 40972069be9SArtem Bityutskiy module_init(mtd_speedtest_init); 41072069be9SArtem Bityutskiy 41172069be9SArtem Bityutskiy static void __exit mtd_speedtest_exit(void) 41272069be9SArtem Bityutskiy { 41372069be9SArtem Bityutskiy return; 41472069be9SArtem Bityutskiy } 41572069be9SArtem Bityutskiy module_exit(mtd_speedtest_exit); 41672069be9SArtem Bityutskiy 41772069be9SArtem Bityutskiy MODULE_DESCRIPTION("Speed test module"); 41872069be9SArtem Bityutskiy MODULE_AUTHOR("Adrian Hunter"); 41972069be9SArtem Bityutskiy MODULE_LICENSE("GPL"); 420