summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/tests/mtd_test.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-09 10:33:19 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-09 10:33:19 -0700
commitef9a61bef917e38f8e096f6df303329aed6cf467 (patch)
tree31cfe2444d0270e77ff8ef792df11591fed6075c /drivers/mtd/tests/mtd_test.c
parentb5f0998cae3d7ea56d3d8377e46328fe972b9546 (diff)
parent6c3b88970175e18a67eb8e55c4eba10614d0d5dc (diff)
Merge tag 'for-linus-20130909' of git://git.infradead.org/linux-mtd
Pull mtd updates from David Woodhouse: - factor out common code from MTD tests - nand-gpio cleanup and portability to non-ARM - m25p80 support for 4-byte addressing chips, other new chips - pxa3xx cleanup and support for new platforms - remove obsolete alauda, octagon-5066 drivers - erase/write support for bcm47xxsflash - improve detection of ECC requirements for NAND, controller setup - NFC acceleration support for atmel-nand, read/write via SRAM - etc * tag 'for-linus-20130909' of git://git.infradead.org/linux-mtd: (184 commits) mtd: chips: Add support for PMC SPI Flash chips in m25p80.c mtd: ofpart: use for_each_child_of_node() macro mtd: mtdswap: replace strict_strtoul() with kstrtoul() mtd cs553x_nand: use kzalloc() instead of memset mtd: atmel_nand: fix error return code in atmel_nand_probe() mtd: bcm47xxsflash: writing support mtd: bcm47xxsflash: implement erasing support mtd: bcm47xxsflash: convert to module_platform_driver instead of init/exit mtd: bcm47xxsflash: convert kzalloc to avoid invalid access mtd: remove alauda driver mtd: nand: mxc_nand: mark 'const' properly mtd: maps: cfi_flagadm: add missing __iomem annotation mtd: spear_smi: add missing __iomem annotation mtd: r852: Staticize local symbols mtd: nandsim: Staticize local symbols mtd: impa7: add missing __iomem annotation mtd: sm_ftl: Staticize local symbols mtd: m25p80: add support for mr25h10 mtd: m25p80: make CONFIG_M25PXX_USE_FAST_READ safe to enable mtd: m25p80: Pass flags through CAT25_INFO macro ...
Diffstat (limited to 'drivers/mtd/tests/mtd_test.c')
-rw-r--r--drivers/mtd/tests/mtd_test.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/mtd/tests/mtd_test.c b/drivers/mtd/tests/mtd_test.c
new file mode 100644
index 000000000000..c818a63532e7
--- /dev/null
+++ b/drivers/mtd/tests/mtd_test.c
@@ -0,0 +1,114 @@
+#define pr_fmt(fmt) "mtd_test: " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/printk.h>
+
+#include "mtd_test.h"
+
+int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned 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_info("error %d while erasing EB %d\n", err, ebnum);
+ return err;
+ }
+
+ if (ei.state == MTD_ERASE_FAILED) {
+ pr_info("some erase error occurred at EB %d\n", ebnum);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum)
+{
+ int ret;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ ret = mtd_block_isbad(mtd, addr);
+ if (ret)
+ pr_info("block %d is bad\n", ebnum);
+
+ return ret;
+}
+
+int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
+ unsigned int eb, int ebcnt)
+{
+ int i, bad = 0;
+
+ if (!mtd_can_have_bb(mtd))
+ return 0;
+
+ pr_info("scanning for bad eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ bbt[i] = is_block_bad(mtd, eb + i) ? 1 : 0;
+ if (bbt[i])
+ bad += 1;
+ cond_resched();
+ }
+ pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
+
+ return 0;
+}
+
+int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
+ unsigned int eb, int ebcnt)
+{
+ int err;
+ unsigned int i;
+
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = mtdtest_erase_eraseblock(mtd, eb + i);
+ if (err)
+ return err;
+ cond_resched();
+ }
+
+ return 0;
+}
+
+int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf)
+{
+ size_t read;
+ int err;
+
+ err = mtd_read(mtd, addr, size, &read, buf);
+ /* Ignore corrected ECC errors */
+ if (mtd_is_bitflip(err))
+ err = 0;
+ if (!err && read != size)
+ err = -EIO;
+ if (err)
+ pr_err("error: read failed at %#llx\n", addr);
+
+ return err;
+}
+
+int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
+ const void *buf)
+{
+ size_t written;
+ int err;
+
+ err = mtd_write(mtd, addr, size, &written, buf);
+ if (!err && written != size)
+ err = -EIO;
+ if (err)
+ pr_err("error: write failed at %#llx\n", addr);
+
+ return err;
+}