diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug index 1e2ee22..fa1a92c 100644 --- a/drivers/mtd/ubi/Kconfig.debug +++ b/drivers/mtd/ubi/Kconfig.debug @@ -59,6 +59,14 @@ config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES This option emulates write failures with probability 1/100. Useful for debugging and testing how UBI handlines errors. +config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES_SAFE_ERASE + bool "Prevent write failure during the sync erase" + depends on MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES + default n + help + This option prevents write failures during the sync erase that may + cause marking the block as bad. + config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES bool "Emulate flash erase failures" depends on MTD_UBI_DEBUG diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index c949cb4..8ff0d6a 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -194,6 +194,23 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) printk(KERN_DEBUG "\t1st 16 characters of name: %s\n", nm); } +#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES +/** + * ubi_dbg_is_write_failure - if it is time to emulate a write failure. + * + * Returns non-zero if a write failure should be emulated, otherwise returns + * zero. + */ +int ubi_dbg_is_write_failure(struct ubi_device *ubi) +{ +#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES_SAFE_ERASE + return (!ubi->write_failure_masked && !(random32() % 500)); +#else + return !(random32() % 500); +#endif +} +#endif + #endif /* CONFIG_MTD_UBI_DEBUG */ /* diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index fa4cffe..ff77a26 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -114,18 +114,9 @@ static inline int ubi_dbg_is_bitflip(void) #endif #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES -/** - * ubi_dbg_is_write_failure - if it is time to emulate a write failure. - * - * Returns non-zero if a write failure should be emulated, otherwise returns - * zero. - */ -static inline int ubi_dbg_is_write_failure(void) -{ - return !(random32() % 500); -} +int ubi_dbg_is_write_failure(struct ubi_device *ubi); #else -#define ubi_dbg_is_write_failure() 0 +#define ubi_dbg_is_write_failure(ubi) 0 #endif #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES @@ -165,7 +156,7 @@ static inline int ubi_dbg_is_erase_failure(void) #define UBI_IO_DEBUG 0 #define DBG_DISABLE_BGT 0 #define ubi_dbg_is_bitflip() 0 -#define ubi_dbg_is_write_failure() 0 +#define ubi_dbg_is_write_failure(ubi) 0 #define ubi_dbg_is_erase_failure() 0 #endif /* !CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 2904991..c164299 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -259,7 +259,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, return err > 0 ? -EINVAL : err; } - if (ubi_dbg_is_write_failure()) { + if (ubi_dbg_is_write_failure(ubi)) { dbg_err("cannot write %d bytes to PEB %d:%d " "(emulated)", len, pnum, offset); ubi_dbg_dump_stack(); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index d8f5915..1194549 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -438,6 +438,9 @@ struct ubi_device { #ifdef CONFIG_MTD_UBI_DEBUG void *dbg_peb_buf; struct mutex dbg_buf_mutex; +#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES_SAFE_ERASE + int write_failure_masked; +#endif #endif }; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index dc38fc5..6799c25 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -615,10 +615,15 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, ec_hdr->ec = cpu_to_be64(ec); +#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES_SAFE_ERASE + ubi->write_failure_masked = 1; +#endif + err = ubi_io_write_ec_hdr(ubi, e->pnum, ec_hdr); if (err) goto out_free; + e->ec = ec; spin_lock(&ubi->wl_lock); if (e->ec > ubi->max_ec) @@ -626,6 +631,9 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, spin_unlock(&ubi->wl_lock); out_free: +#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES_SAFE_ERASE + ubi->write_failure_masked = 0; +#endif kfree(ec_hdr); return err; }