Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define pr_fmt(fmt) "mtd_test: " fmt
0003 
0004 #include <linux/module.h>
0005 #include <linux/sched.h>
0006 #include <linux/printk.h>
0007 
0008 #include "mtd_test.h"
0009 
0010 int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum)
0011 {
0012     int err;
0013     struct erase_info ei;
0014     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0015 
0016     memset(&ei, 0, sizeof(struct erase_info));
0017     ei.addr = addr;
0018     ei.len  = mtd->erasesize;
0019 
0020     err = mtd_erase(mtd, &ei);
0021     if (err) {
0022         pr_info("error %d while erasing EB %d\n", err, ebnum);
0023         return err;
0024     }
0025 
0026     return 0;
0027 }
0028 
0029 static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum)
0030 {
0031     int ret;
0032     loff_t addr = (loff_t)ebnum * mtd->erasesize;
0033 
0034     ret = mtd_block_isbad(mtd, addr);
0035     if (ret)
0036         pr_info("block %d is bad\n", ebnum);
0037 
0038     return ret;
0039 }
0040 
0041 int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
0042                     unsigned int eb, int ebcnt)
0043 {
0044     int i, bad = 0;
0045 
0046     if (!mtd_can_have_bb(mtd))
0047         return 0;
0048 
0049     pr_info("scanning for bad eraseblocks\n");
0050     for (i = 0; i < ebcnt; ++i) {
0051         bbt[i] = is_block_bad(mtd, eb + i) ? 1 : 0;
0052         if (bbt[i])
0053             bad += 1;
0054         cond_resched();
0055     }
0056     pr_info("scanned %d eraseblocks, %d are bad\n", i, bad);
0057 
0058     return 0;
0059 }
0060 
0061 int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
0062                 unsigned int eb, int ebcnt)
0063 {
0064     int err;
0065     unsigned int i;
0066 
0067     for (i = 0; i < ebcnt; ++i) {
0068         if (bbt[i])
0069             continue;
0070         err = mtdtest_erase_eraseblock(mtd, eb + i);
0071         if (err)
0072             return err;
0073         cond_resched();
0074     }
0075 
0076     return 0;
0077 }
0078 
0079 int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf)
0080 {
0081     size_t read;
0082     int err;
0083 
0084     err = mtd_read(mtd, addr, size, &read, buf);
0085     /* Ignore corrected ECC errors */
0086     if (mtd_is_bitflip(err))
0087         err = 0;
0088     if (!err && read != size)
0089         err = -EIO;
0090     if (err)
0091         pr_err("error: read failed at %#llx\n", addr);
0092 
0093     return err;
0094 }
0095 
0096 int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
0097         const void *buf)
0098 {
0099     size_t written;
0100     int err;
0101 
0102     err = mtd_write(mtd, addr, size, &written, buf);
0103     if (!err && written != size)
0104         err = -EIO;
0105     if (err)
0106         pr_err("error: write failed at %#llx\n", addr);
0107 
0108     return err;
0109 }