linux/drivers/mtd/tests/mtd_test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#define pr_fmt(fmt) "mtd_test: " fmt
   3
   4#include <linux/module.h>
   5#include <linux/sched.h>
   6#include <linux/printk.h>
   7
   8#include "mtd_test.h"
   9
  10int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum)
  11{
  12        int err;
  13        struct erase_info ei;
  14        loff_t addr = (loff_t)ebnum * mtd->erasesize;
  15
  16        memset(&ei, 0, sizeof(struct erase_info));
  17        ei.addr = addr;
  18        ei.len  = mtd->erasesize;
  19
  20        err = mtd_erase(mtd, &ei);
  21        if (err) {
  22                pr_info("error %d while erasing EB %d\n", err, ebnum);
  23                return err;
  24        }
  25
  26        return 0;
  27}
  28
  29static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum)
  30{
  31        int ret;
  32        loff_t addr = (loff_t)ebnum * mtd->erasesize;
  33
  34        ret = mtd_block_isbad(mtd, addr);
  35        if (ret)
  36                pr_info("block %d is bad\n", ebnum);
  37
  38        return ret;
  39}
  40
  41int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
  42                                        unsigned int eb, int ebcnt)
  43{
  44        int i, bad = 0;
  45
  46        if (!mtd_can_have_bb(mtd))
  47                return 0;
  48
  49        pr_info("scanning for bad eraseblocks\n");
  50        for (i = 0; i < ebcnt; ++i) {
  51                bbt[i] = is_block_bad(mtd, eb + i) ? 1 : 0;
  52                if (bbt[i])
  53                        bad += 1;
  54                cond_resched();
  55        }
  56        pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
  57
  58        return 0;
  59}
  60
  61int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
  62                                unsigned int eb, int ebcnt)
  63{
  64        int err;
  65        unsigned int i;
  66
  67        for (i = 0; i < ebcnt; ++i) {
  68                if (bbt[i])
  69                        continue;
  70                err = mtdtest_erase_eraseblock(mtd, eb + i);
  71                if (err)
  72                        return err;
  73                cond_resched();
  74        }
  75
  76        return 0;
  77}
  78
  79int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf)
  80{
  81        size_t read;
  82        int err;
  83
  84        err = mtd_read(mtd, addr, size, &read, buf);
  85        /* Ignore corrected ECC errors */
  86        if (mtd_is_bitflip(err))
  87                err = 0;
  88        if (!err && read != size)
  89                err = -EIO;
  90        if (err)
  91                pr_err("error: read failed at %#llx\n", addr);
  92
  93        return err;
  94}
  95
  96int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
  97                const void *buf)
  98{
  99        size_t written;
 100        int err;
 101
 102        err = mtd_write(mtd, addr, size, &written, buf);
 103        if (!err && written != size)
 104                err = -EIO;
 105        if (err)
 106                pr_err("error: write failed at %#llx\n", addr);
 107
 108        return err;
 109}
 110