mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
e50606cea5
MTD tests run only on erased partitions. This module takes care of erasing the partition before running any test. This test is especially helpful when the MTD tests are to be run in automation one after the other. Change-Id: I6a2566fce662bf132ff4a73ae2417807f1d17810 Signed-off-by: Murali Nalajala <mnalajal@qualcomm.com>
174 lines
3.9 KiB
C
174 lines
3.9 KiB
C
/*
|
|
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
|
* Copyright (C) 2006-2008 Nokia Corporation
|
|
*
|
|
* 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.
|
|
*
|
|
* Erase the given MTD partition.
|
|
*
|
|
*/
|
|
|
|
#include <asm/div64.h>
|
|
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/err.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/slab.h>
|
|
|
|
#define PRINT_PREF KERN_INFO "mtd_erasepart: "
|
|
|
|
static int dev;
|
|
module_param(dev, int, S_IRUGO);
|
|
MODULE_PARM_DESC(dev, "MTD device number to use");
|
|
|
|
static struct mtd_info *mtd;
|
|
static unsigned char *bbt;
|
|
static int ebcnt;
|
|
|
|
static 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) {
|
|
printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
|
|
return err;
|
|
}
|
|
|
|
if (ei.state == MTD_ERASE_FAILED) {
|
|
printk(PRINT_PREF "some erase error occurred at EB %d\n",
|
|
ebnum);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int erase_whole_device(void)
|
|
{
|
|
int err;
|
|
unsigned int i;
|
|
|
|
printk(PRINT_PREF "erasing whole device\n");
|
|
for (i = 0; i < ebcnt; ++i) {
|
|
if (bbt[i])
|
|
continue;
|
|
err = erase_eraseblock(i);
|
|
if (err)
|
|
return err;
|
|
cond_resched();
|
|
}
|
|
printk(PRINT_PREF "erased %u eraseblocks\n", i);
|
|
return 0;
|
|
}
|
|
|
|
static int is_block_bad(int ebnum)
|
|
{
|
|
int ret;
|
|
loff_t addr = ebnum * mtd->erasesize;
|
|
|
|
ret = mtd_block_isbad(mtd, addr);
|
|
if (ret)
|
|
printk(PRINT_PREF "block %d is bad\n", ebnum);
|
|
return ret;
|
|
}
|
|
|
|
static int scan_for_bad_eraseblocks(void)
|
|
{
|
|
int i, bad = 0;
|
|
|
|
bbt = kmalloc(ebcnt, GFP_KERNEL);
|
|
if (!bbt) {
|
|
printk(PRINT_PREF "error: cannot allocate memory\n");
|
|
return -ENOMEM;
|
|
}
|
|
memset(bbt, 0 , ebcnt);
|
|
|
|
printk(PRINT_PREF "scanning for bad eraseblocks\n");
|
|
for (i = 0; i < ebcnt; ++i) {
|
|
bbt[i] = is_block_bad(i) ? 1 : 0;
|
|
if (bbt[i])
|
|
bad += 1;
|
|
cond_resched();
|
|
}
|
|
printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
|
|
return 0;
|
|
}
|
|
|
|
static int __init mtd_erasepart_init(void)
|
|
{
|
|
int err = 0;
|
|
uint64_t tmp;
|
|
|
|
printk(KERN_INFO "\n");
|
|
printk(KERN_INFO "=================================================\n");
|
|
printk(PRINT_PREF "MTD device: %d\n", dev);
|
|
|
|
mtd = get_mtd_device(NULL, dev);
|
|
if (IS_ERR(mtd)) {
|
|
err = PTR_ERR(mtd);
|
|
printk(PRINT_PREF "error: cannot get MTD device\n");
|
|
return err;
|
|
}
|
|
|
|
if (mtd->type != MTD_NANDFLASH) {
|
|
printk(PRINT_PREF "this test requires NAND flash\n");
|
|
err = -ENODEV;
|
|
goto out2;
|
|
}
|
|
|
|
tmp = mtd->size;
|
|
do_div(tmp, mtd->erasesize);
|
|
ebcnt = tmp;
|
|
|
|
printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
|
|
"page size %u, count of eraseblocks %u",
|
|
(unsigned long long)mtd->size, mtd->erasesize,
|
|
mtd->writesize, ebcnt);
|
|
|
|
err = scan_for_bad_eraseblocks();
|
|
if (err)
|
|
goto out1;
|
|
|
|
printk(PRINT_PREF "Erasing the whole mtd partition\n");
|
|
|
|
err = erase_whole_device();
|
|
out1:
|
|
kfree(bbt);
|
|
out2:
|
|
put_mtd_device(mtd);
|
|
if (err)
|
|
printk(PRINT_PREF "error %d occurred\n", err);
|
|
printk(KERN_INFO "=================================================\n");
|
|
return err;
|
|
}
|
|
module_init(mtd_erasepart_init);
|
|
|
|
static void __exit mtd_erasepart_exit(void)
|
|
{
|
|
return;
|
|
}
|
|
module_exit(mtd_erasepart_exit);
|
|
|
|
MODULE_DESCRIPTION("Erase a given MTD partition");
|
|
MODULE_LICENSE("GPL v2");
|