1a995c792SAkinobu Mita /* 2a995c792SAkinobu Mita * Copyright (C) 2007 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 read and write speed of a MTD device. 18a995c792SAkinobu Mita * 19a995c792SAkinobu Mita * Author: Adrian Hunter <adrian.hunter@nokia.com> 20a995c792SAkinobu Mita */ 21a995c792SAkinobu Mita 22a995c792SAkinobu Mita #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 23a995c792SAkinobu Mita 24a995c792SAkinobu Mita #include <linux/init.h> 25*af30c0a0SShraddha Barke #include <linux/ktime.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 3459b0816dSAkinobu Mita #include "mtd_test.h" 3559b0816dSAkinobu 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 int count; 41a995c792SAkinobu Mita module_param(count, int, S_IRUGO); 42a995c792SAkinobu Mita MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use " 43a995c792SAkinobu Mita "(0 means use all)"); 44a995c792SAkinobu Mita 45a995c792SAkinobu Mita static struct mtd_info *mtd; 46a995c792SAkinobu Mita static unsigned char *iobuf; 47a995c792SAkinobu Mita static unsigned char *bbt; 48a995c792SAkinobu Mita 49a995c792SAkinobu Mita static int pgsize; 50a995c792SAkinobu Mita static int ebcnt; 51a995c792SAkinobu Mita static int pgcnt; 52a995c792SAkinobu Mita static int goodebcnt; 53*af30c0a0SShraddha Barke static ktime_t start, finish; 54a995c792SAkinobu Mita 55a995c792SAkinobu Mita static int multiblock_erase(int ebnum, int blocks) 56a995c792SAkinobu Mita { 57a995c792SAkinobu Mita int err; 58a995c792SAkinobu Mita struct erase_info ei; 591001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 60a995c792SAkinobu Mita 61a995c792SAkinobu Mita memset(&ei, 0, sizeof(struct erase_info)); 62a995c792SAkinobu Mita ei.mtd = mtd; 63a995c792SAkinobu Mita ei.addr = addr; 64a995c792SAkinobu Mita ei.len = mtd->erasesize * blocks; 65a995c792SAkinobu Mita 66a995c792SAkinobu Mita err = mtd_erase(mtd, &ei); 67a995c792SAkinobu Mita if (err) { 68a995c792SAkinobu Mita pr_err("error %d while erasing EB %d, blocks %d\n", 69a995c792SAkinobu Mita err, ebnum, blocks); 70a995c792SAkinobu Mita return err; 71a995c792SAkinobu Mita } 72a995c792SAkinobu Mita 73a995c792SAkinobu Mita if (ei.state == MTD_ERASE_FAILED) { 74a995c792SAkinobu Mita pr_err("some erase error occurred at EB %d," 75a995c792SAkinobu Mita "blocks %d\n", ebnum, blocks); 76a995c792SAkinobu Mita return -EIO; 77a995c792SAkinobu Mita } 78a995c792SAkinobu Mita 79a995c792SAkinobu Mita return 0; 80a995c792SAkinobu Mita } 81a995c792SAkinobu Mita 82a995c792SAkinobu Mita static int write_eraseblock(int ebnum) 83a995c792SAkinobu Mita { 841001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 85a995c792SAkinobu Mita 868a9f4aa3SAkinobu Mita return mtdtest_write(mtd, addr, mtd->erasesize, iobuf); 87a995c792SAkinobu Mita } 88a995c792SAkinobu Mita 89a995c792SAkinobu Mita static int write_eraseblock_by_page(int ebnum) 90a995c792SAkinobu Mita { 91a995c792SAkinobu Mita int i, err = 0; 921001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 93a995c792SAkinobu Mita void *buf = iobuf; 94a995c792SAkinobu Mita 95a995c792SAkinobu Mita for (i = 0; i < pgcnt; i++) { 9659b0816dSAkinobu Mita err = mtdtest_write(mtd, addr, pgsize, buf); 978a9f4aa3SAkinobu Mita if (err) 98a995c792SAkinobu Mita break; 99a995c792SAkinobu Mita addr += pgsize; 100a995c792SAkinobu Mita buf += pgsize; 101a995c792SAkinobu Mita } 102a995c792SAkinobu Mita 103a995c792SAkinobu Mita return err; 104a995c792SAkinobu Mita } 105a995c792SAkinobu Mita 106a995c792SAkinobu Mita static int write_eraseblock_by_2pages(int ebnum) 107a995c792SAkinobu Mita { 10859b0816dSAkinobu Mita size_t sz = pgsize * 2; 109a995c792SAkinobu Mita int i, n = pgcnt / 2, err = 0; 1101001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 111a995c792SAkinobu Mita void *buf = iobuf; 112a995c792SAkinobu Mita 113a995c792SAkinobu Mita for (i = 0; i < n; i++) { 11459b0816dSAkinobu Mita err = mtdtest_write(mtd, addr, sz, buf); 1158a9f4aa3SAkinobu Mita if (err) 116a995c792SAkinobu Mita return err; 117a995c792SAkinobu Mita addr += sz; 118a995c792SAkinobu Mita buf += sz; 119a995c792SAkinobu Mita } 1208a9f4aa3SAkinobu Mita if (pgcnt % 2) 12159b0816dSAkinobu Mita err = mtdtest_write(mtd, addr, pgsize, buf); 122a995c792SAkinobu Mita 123a995c792SAkinobu Mita return err; 124a995c792SAkinobu Mita } 125a995c792SAkinobu Mita 126a995c792SAkinobu Mita static int read_eraseblock(int ebnum) 127a995c792SAkinobu Mita { 1281001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 129a995c792SAkinobu Mita 130abc173adSAkinobu Mita return mtdtest_read(mtd, addr, mtd->erasesize, iobuf); 131a995c792SAkinobu Mita } 132a995c792SAkinobu Mita 133a995c792SAkinobu Mita static int read_eraseblock_by_page(int ebnum) 134a995c792SAkinobu Mita { 135a995c792SAkinobu Mita int i, err = 0; 1361001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 137a995c792SAkinobu Mita void *buf = iobuf; 138a995c792SAkinobu Mita 139a995c792SAkinobu Mita for (i = 0; i < pgcnt; i++) { 14059b0816dSAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, buf); 141abc173adSAkinobu Mita if (err) 142a995c792SAkinobu Mita break; 143a995c792SAkinobu Mita addr += pgsize; 144a995c792SAkinobu Mita buf += pgsize; 145a995c792SAkinobu Mita } 146a995c792SAkinobu Mita 147a995c792SAkinobu Mita return err; 148a995c792SAkinobu Mita } 149a995c792SAkinobu Mita 150a995c792SAkinobu Mita static int read_eraseblock_by_2pages(int ebnum) 151a995c792SAkinobu Mita { 15259b0816dSAkinobu Mita size_t sz = pgsize * 2; 153a995c792SAkinobu Mita int i, n = pgcnt / 2, err = 0; 1541001ff7aSBrian Norris loff_t addr = (loff_t)ebnum * mtd->erasesize; 155a995c792SAkinobu Mita void *buf = iobuf; 156a995c792SAkinobu Mita 157a995c792SAkinobu Mita for (i = 0; i < n; i++) { 15859b0816dSAkinobu Mita err = mtdtest_read(mtd, addr, sz, buf); 159abc173adSAkinobu Mita if (err) 160a995c792SAkinobu Mita return err; 161a995c792SAkinobu Mita addr += sz; 162a995c792SAkinobu Mita buf += sz; 163a995c792SAkinobu Mita } 164abc173adSAkinobu Mita if (pgcnt % 2) 16559b0816dSAkinobu Mita err = mtdtest_read(mtd, addr, pgsize, buf); 166a995c792SAkinobu Mita 167a995c792SAkinobu Mita return err; 168a995c792SAkinobu Mita } 169a995c792SAkinobu Mita 170a995c792SAkinobu Mita static inline void start_timing(void) 171a995c792SAkinobu Mita { 172*af30c0a0SShraddha Barke start = ktime_get(); 173a995c792SAkinobu Mita } 174a995c792SAkinobu Mita 175a995c792SAkinobu Mita static inline void stop_timing(void) 176a995c792SAkinobu Mita { 177*af30c0a0SShraddha Barke finish = ktime_get(); 178a995c792SAkinobu Mita } 179a995c792SAkinobu Mita 180a995c792SAkinobu Mita static long calc_speed(void) 181a995c792SAkinobu Mita { 182a995c792SAkinobu Mita uint64_t k; 183a995c792SAkinobu Mita long ms; 184a995c792SAkinobu Mita 185*af30c0a0SShraddha Barke ms = ktime_ms_delta(finish, start); 186a995c792SAkinobu Mita if (ms == 0) 187a995c792SAkinobu Mita return 0; 188b9da8baeSBrian Norris k = (uint64_t)goodebcnt * (mtd->erasesize / 1024) * 1000; 189a995c792SAkinobu Mita do_div(k, ms); 190a995c792SAkinobu Mita return k; 191a995c792SAkinobu Mita } 192a995c792SAkinobu Mita 193a995c792SAkinobu Mita static int __init mtd_speedtest_init(void) 194a995c792SAkinobu Mita { 195a995c792SAkinobu Mita int err, i, blocks, j, k; 196a995c792SAkinobu Mita long speed; 197a995c792SAkinobu Mita uint64_t tmp; 198a995c792SAkinobu Mita 199a995c792SAkinobu Mita printk(KERN_INFO "\n"); 200a995c792SAkinobu Mita printk(KERN_INFO "=================================================\n"); 201a995c792SAkinobu Mita 202a995c792SAkinobu Mita if (dev < 0) { 203a995c792SAkinobu Mita pr_info("Please specify a valid mtd-device via module parameter\n"); 204a995c792SAkinobu Mita pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); 205a995c792SAkinobu Mita return -EINVAL; 206a995c792SAkinobu Mita } 207a995c792SAkinobu Mita 208a995c792SAkinobu Mita if (count) 209a995c792SAkinobu Mita pr_info("MTD device: %d count: %d\n", dev, count); 210a995c792SAkinobu Mita else 211a995c792SAkinobu Mita pr_info("MTD device: %d\n", dev); 212a995c792SAkinobu Mita 213a995c792SAkinobu Mita mtd = get_mtd_device(NULL, dev); 214a995c792SAkinobu Mita if (IS_ERR(mtd)) { 215a995c792SAkinobu Mita err = PTR_ERR(mtd); 216a995c792SAkinobu Mita pr_err("error: cannot get MTD device\n"); 217a995c792SAkinobu Mita return err; 218a995c792SAkinobu Mita } 219a995c792SAkinobu Mita 220a995c792SAkinobu Mita if (mtd->writesize == 1) { 221a995c792SAkinobu Mita pr_info("not NAND flash, assume page size is 512 " 222a995c792SAkinobu Mita "bytes.\n"); 223a995c792SAkinobu Mita pgsize = 512; 224a995c792SAkinobu Mita } else 225a995c792SAkinobu Mita pgsize = mtd->writesize; 226a995c792SAkinobu Mita 227a995c792SAkinobu Mita tmp = mtd->size; 228a995c792SAkinobu Mita do_div(tmp, mtd->erasesize); 229a995c792SAkinobu Mita ebcnt = tmp; 230a995c792SAkinobu Mita pgcnt = mtd->erasesize / pgsize; 231a995c792SAkinobu Mita 232a995c792SAkinobu Mita pr_info("MTD device size %llu, eraseblock size %u, " 233a995c792SAkinobu Mita "page size %u, count of eraseblocks %u, pages per " 234a995c792SAkinobu Mita "eraseblock %u, OOB size %u\n", 235a995c792SAkinobu Mita (unsigned long long)mtd->size, mtd->erasesize, 236a995c792SAkinobu Mita pgsize, ebcnt, pgcnt, mtd->oobsize); 237a995c792SAkinobu Mita 238a995c792SAkinobu Mita if (count > 0 && count < ebcnt) 239a995c792SAkinobu Mita ebcnt = count; 240a995c792SAkinobu Mita 241a995c792SAkinobu Mita err = -ENOMEM; 242a995c792SAkinobu Mita iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); 243a995c792SAkinobu Mita if (!iobuf) 244a995c792SAkinobu Mita goto out; 245a995c792SAkinobu Mita 246a995c792SAkinobu Mita prandom_bytes(iobuf, mtd->erasesize); 247a995c792SAkinobu Mita 24859b0816dSAkinobu Mita bbt = kzalloc(ebcnt, GFP_KERNEL); 24959b0816dSAkinobu Mita if (!bbt) 25059b0816dSAkinobu Mita goto out; 25159b0816dSAkinobu Mita err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); 252a995c792SAkinobu Mita if (err) 253a995c792SAkinobu Mita goto out; 25459b0816dSAkinobu Mita for (i = 0; i < ebcnt; i++) { 25559b0816dSAkinobu Mita if (!bbt[i]) 25659b0816dSAkinobu Mita goodebcnt++; 25759b0816dSAkinobu Mita } 258a995c792SAkinobu Mita 25959b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 260a995c792SAkinobu Mita if (err) 261a995c792SAkinobu Mita goto out; 262a995c792SAkinobu Mita 263a995c792SAkinobu Mita /* Write all eraseblocks, 1 eraseblock at a time */ 264a995c792SAkinobu Mita pr_info("testing eraseblock write speed\n"); 265a995c792SAkinobu Mita start_timing(); 266a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 267a995c792SAkinobu Mita if (bbt[i]) 268a995c792SAkinobu Mita continue; 269a995c792SAkinobu Mita err = write_eraseblock(i); 270a995c792SAkinobu Mita if (err) 271a995c792SAkinobu Mita goto out; 2722a6a28e7SRichard Weinberger 2732a6a28e7SRichard Weinberger err = mtdtest_relax(); 2742a6a28e7SRichard Weinberger if (err) 2752a6a28e7SRichard Weinberger goto out; 276a995c792SAkinobu Mita } 277a995c792SAkinobu Mita stop_timing(); 278a995c792SAkinobu Mita speed = calc_speed(); 279a995c792SAkinobu Mita pr_info("eraseblock write speed is %ld KiB/s\n", speed); 280a995c792SAkinobu Mita 281a995c792SAkinobu Mita /* Read all eraseblocks, 1 eraseblock at a time */ 282a995c792SAkinobu Mita pr_info("testing eraseblock read speed\n"); 283a995c792SAkinobu Mita start_timing(); 284a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 285a995c792SAkinobu Mita if (bbt[i]) 286a995c792SAkinobu Mita continue; 287a995c792SAkinobu Mita err = read_eraseblock(i); 288a995c792SAkinobu Mita if (err) 289a995c792SAkinobu Mita goto out; 2902a6a28e7SRichard Weinberger 2912a6a28e7SRichard Weinberger err = mtdtest_relax(); 2922a6a28e7SRichard Weinberger if (err) 2932a6a28e7SRichard Weinberger goto out; 294a995c792SAkinobu Mita } 295a995c792SAkinobu Mita stop_timing(); 296a995c792SAkinobu Mita speed = calc_speed(); 297a995c792SAkinobu Mita pr_info("eraseblock read speed is %ld KiB/s\n", speed); 298a995c792SAkinobu Mita 29959b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 300a995c792SAkinobu Mita if (err) 301a995c792SAkinobu Mita goto out; 302a995c792SAkinobu Mita 303a995c792SAkinobu Mita /* Write all eraseblocks, 1 page at a time */ 304a995c792SAkinobu Mita pr_info("testing page write speed\n"); 305a995c792SAkinobu Mita start_timing(); 306a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 307a995c792SAkinobu Mita if (bbt[i]) 308a995c792SAkinobu Mita continue; 309a995c792SAkinobu Mita err = write_eraseblock_by_page(i); 310a995c792SAkinobu Mita if (err) 311a995c792SAkinobu Mita goto out; 3122a6a28e7SRichard Weinberger 3132a6a28e7SRichard Weinberger err = mtdtest_relax(); 3142a6a28e7SRichard Weinberger if (err) 3152a6a28e7SRichard Weinberger goto out; 316a995c792SAkinobu Mita } 317a995c792SAkinobu Mita stop_timing(); 318a995c792SAkinobu Mita speed = calc_speed(); 319a995c792SAkinobu Mita pr_info("page write speed is %ld KiB/s\n", speed); 320a995c792SAkinobu Mita 321a995c792SAkinobu Mita /* Read all eraseblocks, 1 page at a time */ 322a995c792SAkinobu Mita pr_info("testing page read speed\n"); 323a995c792SAkinobu Mita start_timing(); 324a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 325a995c792SAkinobu Mita if (bbt[i]) 326a995c792SAkinobu Mita continue; 327a995c792SAkinobu Mita err = read_eraseblock_by_page(i); 328a995c792SAkinobu Mita if (err) 329a995c792SAkinobu Mita goto out; 3302a6a28e7SRichard Weinberger 3312a6a28e7SRichard Weinberger err = mtdtest_relax(); 3322a6a28e7SRichard Weinberger if (err) 3332a6a28e7SRichard Weinberger goto out; 334a995c792SAkinobu Mita } 335a995c792SAkinobu Mita stop_timing(); 336a995c792SAkinobu Mita speed = calc_speed(); 337a995c792SAkinobu Mita pr_info("page read speed is %ld KiB/s\n", speed); 338a995c792SAkinobu Mita 33959b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 340a995c792SAkinobu Mita if (err) 341a995c792SAkinobu Mita goto out; 342a995c792SAkinobu Mita 343a995c792SAkinobu Mita /* Write all eraseblocks, 2 pages at a time */ 344a995c792SAkinobu Mita pr_info("testing 2 page write speed\n"); 345a995c792SAkinobu Mita start_timing(); 346a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 347a995c792SAkinobu Mita if (bbt[i]) 348a995c792SAkinobu Mita continue; 349a995c792SAkinobu Mita err = write_eraseblock_by_2pages(i); 350a995c792SAkinobu Mita if (err) 351a995c792SAkinobu Mita goto out; 3522a6a28e7SRichard Weinberger 3532a6a28e7SRichard Weinberger err = mtdtest_relax(); 3542a6a28e7SRichard Weinberger if (err) 3552a6a28e7SRichard Weinberger goto out; 356a995c792SAkinobu Mita } 357a995c792SAkinobu Mita stop_timing(); 358a995c792SAkinobu Mita speed = calc_speed(); 359a995c792SAkinobu Mita pr_info("2 page write speed is %ld KiB/s\n", speed); 360a995c792SAkinobu Mita 361a995c792SAkinobu Mita /* Read all eraseblocks, 2 pages at a time */ 362a995c792SAkinobu Mita pr_info("testing 2 page read speed\n"); 363a995c792SAkinobu Mita start_timing(); 364a995c792SAkinobu Mita for (i = 0; i < ebcnt; ++i) { 365a995c792SAkinobu Mita if (bbt[i]) 366a995c792SAkinobu Mita continue; 367a995c792SAkinobu Mita err = read_eraseblock_by_2pages(i); 368a995c792SAkinobu Mita if (err) 369a995c792SAkinobu Mita goto out; 3702a6a28e7SRichard Weinberger 3712a6a28e7SRichard Weinberger err = mtdtest_relax(); 3722a6a28e7SRichard Weinberger if (err) 3732a6a28e7SRichard Weinberger goto out; 374a995c792SAkinobu Mita } 375a995c792SAkinobu Mita stop_timing(); 376a995c792SAkinobu Mita speed = calc_speed(); 377a995c792SAkinobu Mita pr_info("2 page read speed is %ld KiB/s\n", speed); 378a995c792SAkinobu Mita 379a995c792SAkinobu Mita /* Erase all eraseblocks */ 380a995c792SAkinobu Mita pr_info("Testing erase speed\n"); 381a995c792SAkinobu Mita start_timing(); 38259b0816dSAkinobu Mita err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); 383a995c792SAkinobu Mita if (err) 384a995c792SAkinobu Mita goto out; 385a995c792SAkinobu Mita stop_timing(); 386a995c792SAkinobu Mita speed = calc_speed(); 387a995c792SAkinobu Mita pr_info("erase speed is %ld KiB/s\n", speed); 388a995c792SAkinobu Mita 389a995c792SAkinobu Mita /* Multi-block erase all eraseblocks */ 390a995c792SAkinobu Mita for (k = 1; k < 7; k++) { 391a995c792SAkinobu Mita blocks = 1 << k; 392a995c792SAkinobu Mita pr_info("Testing %dx multi-block erase speed\n", 393a995c792SAkinobu Mita blocks); 394a995c792SAkinobu Mita start_timing(); 395a995c792SAkinobu Mita for (i = 0; i < ebcnt; ) { 396a995c792SAkinobu Mita for (j = 0; j < blocks && (i + j) < ebcnt; j++) 397a995c792SAkinobu Mita if (bbt[i + j]) 398a995c792SAkinobu Mita break; 399a995c792SAkinobu Mita if (j < 1) { 400a995c792SAkinobu Mita i++; 401a995c792SAkinobu Mita continue; 402a995c792SAkinobu Mita } 403a995c792SAkinobu Mita err = multiblock_erase(i, j); 404a995c792SAkinobu Mita if (err) 405a995c792SAkinobu Mita goto out; 4062a6a28e7SRichard Weinberger 4072a6a28e7SRichard Weinberger err = mtdtest_relax(); 4082a6a28e7SRichard Weinberger if (err) 4092a6a28e7SRichard Weinberger goto out; 4102a6a28e7SRichard Weinberger 411a995c792SAkinobu Mita i += j; 412a995c792SAkinobu Mita } 413a995c792SAkinobu Mita stop_timing(); 414a995c792SAkinobu Mita speed = calc_speed(); 415a995c792SAkinobu Mita pr_info("%dx multi-block erase speed is %ld KiB/s\n", 416a995c792SAkinobu Mita blocks, speed); 417a995c792SAkinobu Mita } 418a995c792SAkinobu Mita pr_info("finished\n"); 419a995c792SAkinobu Mita out: 420a995c792SAkinobu Mita kfree(iobuf); 421a995c792SAkinobu Mita kfree(bbt); 422a995c792SAkinobu Mita put_mtd_device(mtd); 423a995c792SAkinobu Mita if (err) 424a995c792SAkinobu Mita pr_info("error %d occurred\n", err); 425a995c792SAkinobu Mita printk(KERN_INFO "=================================================\n"); 426a995c792SAkinobu Mita return err; 427a995c792SAkinobu Mita } 428a995c792SAkinobu Mita module_init(mtd_speedtest_init); 429a995c792SAkinobu Mita 430a995c792SAkinobu Mita static void __exit mtd_speedtest_exit(void) 431a995c792SAkinobu Mita { 432a995c792SAkinobu Mita return; 433a995c792SAkinobu Mita } 434a995c792SAkinobu Mita module_exit(mtd_speedtest_exit); 435a995c792SAkinobu Mita 436a995c792SAkinobu Mita MODULE_DESCRIPTION("Speed test module"); 437a995c792SAkinobu Mita MODULE_AUTHOR("Adrian Hunter"); 438a995c792SAkinobu Mita MODULE_LICENSE("GPL"); 439