diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2013-08-03 18:52:08 +0900 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2013-08-30 21:34:06 +0100 |
commit | a995c792280db558f994c253c1c3c3a55977d529 (patch) | |
tree | 7555f07ffad35a5dbb216a4a03eb11efdc5e35a3 /drivers/mtd/tests/mtd_torturetest.c | |
parent | 084db4b020c7bb7f4169ae74fb9a685c30a2939d (diff) |
mtd: tests: rename sources in order to link a helper object
Each mtd test module have a single source whose name is the same as
the module name. In order to link a single object including helper
functions to every test module, this rename these sources to the
different names.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Vikram Narayanan <vikram186@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/tests/mtd_torturetest.c')
-rw-r--r-- | drivers/mtd/tests/mtd_torturetest.c | 535 |
1 files changed, 0 insertions, 535 deletions
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c deleted file mode 100644 index 3a9f6a6a79f9..000000000000 --- a/drivers/mtd/tests/mtd_torturetest.c +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright (C) 2006-2008 Artem Bityutskiy - * Copyright (C) 2006-2008 Jarkko Lavinen - * Copyright (C) 2006-2008 Adrian Hunter - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; see the file COPYING. If not, write to the Free Software - * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Authors: Artem Bityutskiy, Jarkko Lavinen, Adria Hunter - * - * WARNING: this test program may kill your flash and your device. Do not - * use it unless you know what you do. Authors are not responsible for any - * damage caused by this program. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/err.h> -#include <linux/mtd/mtd.h> -#include <linux/slab.h> -#include <linux/sched.h> - -#define RETRIES 3 - -static int eb = 8; -module_param(eb, int, S_IRUGO); -MODULE_PARM_DESC(eb, "eraseblock number within the selected MTD device"); - -static int ebcnt = 32; -module_param(ebcnt, int, S_IRUGO); -MODULE_PARM_DESC(ebcnt, "number of consecutive eraseblocks to torture"); - -static int pgcnt; -module_param(pgcnt, int, S_IRUGO); -MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)"); - -static int dev = -EINVAL; -module_param(dev, int, S_IRUGO); -MODULE_PARM_DESC(dev, "MTD device number to use"); - -static int gran = 512; -module_param(gran, int, S_IRUGO); -MODULE_PARM_DESC(gran, "how often the status information should be printed"); - -static int check = 1; -module_param(check, int, S_IRUGO); -MODULE_PARM_DESC(check, "if the written data should be checked"); - -static unsigned int cycles_count; -module_param(cycles_count, uint, S_IRUGO); -MODULE_PARM_DESC(cycles_count, "how many erase cycles to do " - "(infinite by default)"); - -static struct mtd_info *mtd; - -/* This buffer contains 0x555555...0xAAAAAA... pattern */ -static unsigned char *patt_5A5; -/* This buffer contains 0xAAAAAA...0x555555... pattern */ -static unsigned char *patt_A5A; -/* This buffer contains all 0xFF bytes */ -static unsigned char *patt_FF; -/* This a temporary buffer is use when checking data */ -static unsigned char *check_buf; -/* How many erase cycles were done */ -static unsigned int erase_cycles; - -static int pgsize; -static struct timeval start, finish; - -static void report_corrupt(unsigned char *read, unsigned char *written); - -static inline void start_timing(void) -{ - do_gettimeofday(&start); -} - -static inline void stop_timing(void) -{ - do_gettimeofday(&finish); -} - -/* - * Erase eraseblock number @ebnum. - */ -static inline int erase_eraseblock(int ebnum) -{ - 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; - - err = mtd_erase(mtd, &ei); - if (err) { - pr_err("error %d while erasing EB %d\n", err, ebnum); - return err; - } - - if (ei.state == MTD_ERASE_FAILED) { - pr_err("some erase error occurred at EB %d\n", - ebnum); - return -EIO; - } - - return 0; -} - -/* - * Check that the contents of eraseblock number @enbum is equivalent to the - * @buf buffer. - */ -static inline int check_eraseblock(int ebnum, unsigned char *buf) -{ - int err, retries = 0; - size_t read; - loff_t addr = ebnum * mtd->erasesize; - size_t len = mtd->erasesize; - - if (pgcnt) { - addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; - len = pgcnt * pgsize; - } - -retry: - err = mtd_read(mtd, addr, len, &read, check_buf); - if (mtd_is_bitflip(err)) - pr_err("single bit flip occurred at EB %d " - "MTD reported that it was fixed.\n", ebnum); - else if (err) { - pr_err("error %d while reading EB %d, " - "read %zd\n", err, ebnum, read); - return err; - } - - if (read != len) { - pr_err("failed to read %zd bytes from EB %d, " - "read only %zd, but no error reported\n", - len, ebnum, read); - return -EIO; - } - - if (memcmp(buf, check_buf, len)) { - pr_err("read wrong data from EB %d\n", ebnum); - report_corrupt(check_buf, buf); - - if (retries++ < RETRIES) { - /* Try read again */ - yield(); - pr_info("re-try reading data from EB %d\n", - ebnum); - goto retry; - } else { - pr_info("retried %d times, still errors, " - "give-up\n", RETRIES); - return -EINVAL; - } - } - - if (retries != 0) - pr_info("only attempt number %d was OK (!!!)\n", - retries); - - return 0; -} - -static inline int write_pattern(int ebnum, void *buf) -{ - int err; - size_t written; - loff_t addr = ebnum * mtd->erasesize; - size_t len = mtd->erasesize; - - if (pgcnt) { - addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize; - len = pgcnt * pgsize; - } - err = mtd_write(mtd, addr, len, &written, buf); - if (err) { - pr_err("error %d while writing EB %d, written %zd" - " bytes\n", err, ebnum, written); - return err; - } - if (written != len) { - pr_info("written only %zd bytes of %zd, but no error" - " reported\n", written, len); - return -EIO; - } - - return 0; -} - -static int __init tort_init(void) -{ - int err = 0, i, infinite = !cycles_count; - int *bad_ebs; - - printk(KERN_INFO "\n"); - printk(KERN_INFO "=================================================\n"); - pr_info("Warning: this program is trying to wear out your " - "flash, stop it if this is not wanted.\n"); - - if (dev < 0) { - pr_info("Please specify a valid mtd-device via module parameter\n"); - pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n"); - return -EINVAL; - } - - pr_info("MTD device: %d\n", dev); - pr_info("torture %d eraseblocks (%d-%d) of mtd%d\n", - ebcnt, eb, eb + ebcnt - 1, dev); - if (pgcnt) - pr_info("torturing just %d pages per eraseblock\n", - pgcnt); - pr_info("write verify %s\n", check ? "enabled" : "disabled"); - - mtd = get_mtd_device(NULL, dev); - if (IS_ERR(mtd)) { - err = PTR_ERR(mtd); - pr_err("error: cannot get MTD device\n"); - return err; - } - - if (mtd->writesize == 1) { - pr_info("not NAND flash, assume page size is 512 " - "bytes.\n"); - pgsize = 512; - } else - pgsize = mtd->writesize; - - if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) { - pr_err("error: invalid pgcnt value %d\n", pgcnt); - goto out_mtd; - } - - err = -ENOMEM; - patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL); - if (!patt_5A5) - goto out_mtd; - - patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL); - if (!patt_A5A) - goto out_patt_5A5; - - patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL); - if (!patt_FF) - goto out_patt_A5A; - - check_buf = kmalloc(mtd->erasesize, GFP_KERNEL); - if (!check_buf) - goto out_patt_FF; - - bad_ebs = kcalloc(ebcnt, sizeof(*bad_ebs), GFP_KERNEL); - if (!bad_ebs) - goto out_check_buf; - - err = 0; - - /* Initialize patterns */ - memset(patt_FF, 0xFF, mtd->erasesize); - for (i = 0; i < mtd->erasesize / pgsize; i++) { - if (!(i & 1)) { - memset(patt_5A5 + i * pgsize, 0x55, pgsize); - memset(patt_A5A + i * pgsize, 0xAA, pgsize); - } else { - memset(patt_5A5 + i * pgsize, 0xAA, pgsize); - memset(patt_A5A + i * pgsize, 0x55, pgsize); - } - } - - /* - * Check if there is a bad eraseblock among those we are going to test. - */ - if (mtd_can_have_bb(mtd)) { - for (i = eb; i < eb + ebcnt; i++) { - err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize); - - if (err < 0) { - pr_info("block_isbad() returned %d " - "for EB %d\n", err, i); - goto out; - } - - if (err) { - pr_err("EB %d is bad. Skip it.\n", i); - bad_ebs[i - eb] = 1; - } - } - } - - start_timing(); - while (1) { - int i; - void *patt; - - /* Erase all eraseblocks */ - for (i = eb; i < eb + ebcnt; i++) { - if (bad_ebs[i - eb]) - continue; - err = erase_eraseblock(i); - if (err) - goto out; - cond_resched(); - } - - /* Check if the eraseblocks contain only 0xFF bytes */ - if (check) { - for (i = eb; i < eb + ebcnt; i++) { - if (bad_ebs[i - eb]) - continue; - err = check_eraseblock(i, patt_FF); - if (err) { - pr_info("verify failed" - " for 0xFF... pattern\n"); - goto out; - } - cond_resched(); - } - } - - /* Write the pattern */ - for (i = eb; i < eb + ebcnt; i++) { - if (bad_ebs[i - eb]) - continue; - if ((eb + erase_cycles) & 1) - patt = patt_5A5; - else - patt = patt_A5A; - err = write_pattern(i, patt); - if (err) - goto out; - cond_resched(); - } - - /* Verify what we wrote */ - if (check) { - for (i = eb; i < eb + ebcnt; i++) { - if (bad_ebs[i - eb]) - continue; - if ((eb + erase_cycles) & 1) - patt = patt_5A5; - else - patt = patt_A5A; - err = check_eraseblock(i, patt); - if (err) { - pr_info("verify failed for %s" - " pattern\n", - ((eb + erase_cycles) & 1) ? - "0x55AA55..." : "0xAA55AA..."); - goto out; - } - cond_resched(); - } - } - - erase_cycles += 1; - - if (erase_cycles % gran == 0) { - long ms; - - stop_timing(); - ms = (finish.tv_sec - start.tv_sec) * 1000 + - (finish.tv_usec - start.tv_usec) / 1000; - pr_info("%08u erase cycles done, took %lu " - "milliseconds (%lu seconds)\n", - erase_cycles, ms, ms / 1000); - start_timing(); - } - - if (!infinite && --cycles_count == 0) - break; - } -out: - - pr_info("finished after %u erase cycles\n", - erase_cycles); - kfree(bad_ebs); -out_check_buf: - kfree(check_buf); -out_patt_FF: - kfree(patt_FF); -out_patt_A5A: - kfree(patt_A5A); -out_patt_5A5: - kfree(patt_5A5); -out_mtd: - put_mtd_device(mtd); - if (err) - pr_info("error %d occurred during torturing\n", err); - printk(KERN_INFO "=================================================\n"); - return err; -} -module_init(tort_init); - -static void __exit tort_exit(void) -{ - return; -} -module_exit(tort_exit); - -static int countdiffs(unsigned char *buf, unsigned char *check_buf, - unsigned offset, unsigned len, unsigned *bytesp, - unsigned *bitsp); -static void print_bufs(unsigned char *read, unsigned char *written, int start, - int len); - -/* - * Report the detailed information about how the read EB differs from what was - * written. - */ -static void report_corrupt(unsigned char *read, unsigned char *written) -{ - int i; - int bytes, bits, pages, first; - int offset, len; - size_t check_len = mtd->erasesize; - - if (pgcnt) - check_len = pgcnt * pgsize; - - bytes = bits = pages = 0; - for (i = 0; i < check_len; i += pgsize) - if (countdiffs(written, read, i, pgsize, &bytes, - &bits) >= 0) - pages++; - - pr_info("verify fails on %d pages, %d bytes/%d bits\n", - pages, bytes, bits); - pr_info("The following is a list of all differences between" - " what was read from flash and what was expected\n"); - - for (i = 0; i < check_len; i += pgsize) { - cond_resched(); - bytes = bits = 0; - first = countdiffs(written, read, i, pgsize, &bytes, - &bits); - if (first < 0) - continue; - - printk("-------------------------------------------------------" - "----------------------------------\n"); - - pr_info("Page %zd has %d bytes/%d bits failing verify," - " starting at offset 0x%x\n", - (mtd->erasesize - check_len + i) / pgsize, - bytes, bits, first); - - offset = first & ~0x7; - len = ((first + bytes) | 0x7) + 1 - offset; - - print_bufs(read, written, offset, len); - } -} - -static void print_bufs(unsigned char *read, unsigned char *written, int start, - int len) -{ - int i = 0, j1, j2; - char *diff; - - printk("Offset Read Written\n"); - while (i < len) { - printk("0x%08x: ", start + i); - diff = " "; - for (j1 = 0; j1 < 8 && i + j1 < len; j1++) { - printk(" %02x", read[start + i + j1]); - if (read[start + i + j1] != written[start + i + j1]) - diff = "***"; - } - - while (j1 < 8) { - printk(" "); - j1 += 1; - } - - printk(" %s ", diff); - - for (j2 = 0; j2 < 8 && i + j2 < len; j2++) - printk(" %02x", written[start + i + j2]); - printk("\n"); - i += 8; - } -} - -/* - * Count the number of differing bytes and bits and return the first differing - * offset. - */ -static int countdiffs(unsigned char *buf, unsigned char *check_buf, - unsigned offset, unsigned len, unsigned *bytesp, - unsigned *bitsp) -{ - unsigned i, bit; - int first = -1; - - for (i = offset; i < offset + len; i++) - if (buf[i] != check_buf[i]) { - first = i; - break; - } - - while (i < offset + len) { - if (buf[i] != check_buf[i]) { - (*bytesp)++; - bit = 1; - while (bit < 256) { - if ((buf[i] & bit) != (check_buf[i] & bit)) - (*bitsp)++; - bit <<= 1; - } - } - i++; - } - - return first; -} - -MODULE_DESCRIPTION("Eraseblock torturing module"); -MODULE_AUTHOR("Artem Bityutskiy, Jarkko Lavinen, Adrian Hunter"); -MODULE_LICENSE("GPL"); |