diff options
Diffstat (limited to 'drivers/mtd/tests/mtd_speedtest.c')
-rw-r--r-- | drivers/mtd/tests/mtd_speedtest.c | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c index 161feeb7b8b..627d4e2466a 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c @@ -16,7 +16,7 @@ * * Test read and write speed of a MTD device. * - * Author: Adrian Hunter <ext-adrian.hunter@nokia.com> + * Author: Adrian Hunter <adrian.hunter@nokia.com> */ #include <linux/init.h> @@ -33,6 +33,11 @@ static int dev; module_param(dev, int, S_IRUGO); MODULE_PARM_DESC(dev, "MTD device number to use"); +static int count; +module_param(count, int, S_IRUGO); +MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use " + "(0 means use all)"); + static struct mtd_info *mtd; static unsigned char *iobuf; static unsigned char *bbt; @@ -89,6 +94,33 @@ static int erase_eraseblock(int ebnum) return 0; } +static int multiblock_erase(int ebnum, int blocks) +{ + int err; + struct erase_info ei; + loff_t addr = ebnum * mtd->erasesize; + + memset(&ei, 0, sizeof(struct erase_info)); + ei.mtd = mtd; + ei.addr = addr; + ei.len = mtd->erasesize * blocks; + + err = mtd->erase(mtd, &ei); + if (err) { + printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n", + err, ebnum, blocks); + return err; + } + + if (ei.state == MTD_ERASE_FAILED) { + printk(PRINT_PREF "some erase error occurred at EB %d," + "blocks %d\n", ebnum, blocks); + return -EIO; + } + + return 0; +} + static int erase_whole_device(void) { int err; @@ -282,13 +314,16 @@ static inline void stop_timing(void) static long calc_speed(void) { - long ms, k, speed; + uint64_t k; + long ms; ms = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000; - k = goodebcnt * mtd->erasesize / 1024; - speed = (k * 1000) / ms; - return speed; + if (ms == 0) + return 0; + k = goodebcnt * (mtd->erasesize / 1024) * 1000; + do_div(k, ms); + return k; } static int scan_for_bad_eraseblocks(void) @@ -320,13 +355,16 @@ out: static int __init mtd_speedtest_init(void) { - int err, i; + int err, i, blocks, j, k; long speed; uint64_t tmp; printk(KERN_INFO "\n"); printk(KERN_INFO "=================================================\n"); - printk(PRINT_PREF "MTD device: %d\n", dev); + if (count) + printk(PRINT_PREF "MTD device: %d count: %d\n", dev, count); + else + printk(PRINT_PREF "MTD device: %d\n", dev); mtd = get_mtd_device(NULL, dev); if (IS_ERR(mtd)) { @@ -353,6 +391,9 @@ static int __init mtd_speedtest_init(void) (unsigned long long)mtd->size, mtd->erasesize, pgsize, ebcnt, pgcnt, mtd->oobsize); + if (count > 0 && count < ebcnt) + ebcnt = count; + err = -ENOMEM; iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); if (!iobuf) { @@ -484,6 +525,31 @@ static int __init mtd_speedtest_init(void) speed = calc_speed(); printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed); + /* Multi-block erase all eraseblocks */ + for (k = 1; k < 7; k++) { + blocks = 1 << k; + printk(PRINT_PREF "Testing %dx multi-block erase speed\n", + blocks); + start_timing(); + for (i = 0; i < ebcnt; ) { + for (j = 0; j < blocks && (i + j) < ebcnt; j++) + if (bbt[i + j]) + break; + if (j < 1) { + i++; + continue; + } + err = multiblock_erase(i, j); + if (err) + goto out; + cond_resched(); + i += j; + } + stop_timing(); + speed = calc_speed(); + printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n", + blocks, speed); + } printk(PRINT_PREF "finished\n"); out: kfree(iobuf); |