[PATCH] NAND: nandsim bad block injection

Vijay Kumar vijaykumar at bravegnu.org
Sun Dec 24 08:08:45 EST 2006


Adds support for bad block creation on block erase and page program,
by returning erase/program failed in the status byte. The probability
of fault occurrence can be specified through module parameters.

Signed-off-by: Vijay Kumar <vijaykumar at bravegnu.org>

diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index c3bca95..ee71357 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -37,6 +37,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
+#include <linux/random.h>
 
 /* Default simulator parameters values */
 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE)  || \
@@ -70,6 +71,12 @@
 #ifndef CONFIG_NANDSIM_DO_DELAYS
 #define CONFIG_NANDSIM_DO_DELAYS  0
 #endif
+#ifndef CONFIG_NANDSIM_ERASE_FAIL_PROB
+#define CONFIG_NANDSIM_ERASE_FAIL_PROB 0
+#endif
+#ifndef CONFIG_NANDSIM_PROG_FAIL_PROB
+#define CONFIG_NANDSIM_PROG_FAIL_PROB 0
+#endif
 #ifndef CONFIG_NANDSIM_LOG
 #define CONFIG_NANDSIM_LOG        0
 #endif
@@ -77,6 +84,9 @@
 #define CONFIG_NANDSIM_DBG        0
 #endif
 
+#define PROB_SCALE_FACTOR         1000
+#define PROB_SCALE_FACTOR_STR     "1000"
+
 static uint first_id_byte  = CONFIG_NANDSIM_FIRST_ID_BYTE;
 static uint second_id_byte = CONFIG_NANDSIM_SECOND_ID_BYTE;
 static uint third_id_byte  = CONFIG_NANDSIM_THIRD_ID_BYTE;
@@ -88,6 +98,8 @@ static uint output_cycle   = CONFIG_NAND
 static uint input_cycle    = CONFIG_NANDSIM_INPUT_CYCLE;
 static uint bus_width      = CONFIG_NANDSIM_BUS_WIDTH;
 static uint do_delays      = CONFIG_NANDSIM_DO_DELAYS;
+static uint erase_fail_prob = CONFIG_NANDSIM_ERASE_FAIL_PROB;
+static uint prog_fail_prob = CONFIG_NANDSIM_PROG_FAIL_PROB;
 static uint log            = CONFIG_NANDSIM_LOG;
 static uint dbg            = CONFIG_NANDSIM_DBG;
 
@@ -102,6 +114,8 @@ module_param(output_cycle,   uint, 0400)
 module_param(input_cycle,    uint, 0400);
 module_param(bus_width,      uint, 0400);
 module_param(do_delays,      uint, 0400);
+module_param(erase_fail_prob, uint, 0400);
+module_param(prog_fail_prob, uint, 0400);
 module_param(log,            uint, 0400);
 module_param(dbg,            uint, 0400);
 
@@ -116,6 +130,8 @@ MODULE_PARM_DESC(output_cycle,   "Word o
 MODULE_PARM_DESC(input_cycle,    "Word input (to flash) time (nanodeconds)");
 MODULE_PARM_DESC(bus_width,      "Chip's bus width (8- or 16-bit)");
 MODULE_PARM_DESC(do_delays,      "Simulate NAND delays using busy-waits if not zero");
+MODULE_PARM_DESC(erase_fail_prob, "Probability (scaled by " PROB_SCALE_FACTOR_STR ") of erase failing, default 0");
+MODULE_PARM_DESC(prog_fail_prob, "Probability (scaled by " PROB_SCALE_FACTOR_STR ") of program failing, default 0");
 MODULE_PARM_DESC(log,            "Perform logging if not zero");
 MODULE_PARM_DESC(dbg,            "Output debug information if not zero");
 
@@ -875,6 +891,37 @@ static int prog_page(struct nandsim *ns,
 }
 
 /*
+ * Given the probability (scaled by PROB_SCALE_FACTOR) 'prob', the
+ * function determines whether fault has to be injected. 'prob' is
+ * specified in the range 0 - PROB_SCALE_FACTOR. Probability is
+ * calculated as 'prob'/PROB_SCALE_FACTOR.
+ *
+ * RETURNS: 1 if fault should be injected, 0 if fault should not be
+ * injected.
+ */
+static int inject_fault_with_prob(int prob)
+{
+	int rnd;
+
+	rnd = random32() % PROB_SCALE_FACTOR;
+
+	if (rnd < prob)
+		return 1;
+	else
+		return 0;
+}
+
+static inline int inject_erase_fault(void)
+{
+	return inject_fault_with_prob(erase_fail_prob);
+}
+
+static inline int inject_prog_fault(void)
+{
+	return inject_fault_with_prob(prog_fail_prob);
+}
+
+/*
  * If state has any action bit, perform this action.
  *
  * RETURNS: 0 if success, -1 if error.
@@ -948,6 +995,16 @@ static int do_state_action(struct nandsi
 
 		erase_sector(ns);
 
+		/* 
+		 * Injecting fault after erasing the sector, saves
+		 * memory since the memory used by the bad block is
+		 * freed.
+		 */
+		if (inject_erase_fault()) {
+			NS_DBG("do_state_action: injecting erase fault\n");
+			return -1;
+		}
+
 		NS_MDELAY(erase_delay);
 
 		break;
@@ -969,6 +1026,15 @@ static int do_state_action(struct nandsi
 			return -1;
 		}
 
+		/* 
+		 * Injecting fault before programming the sector,
+		 * helps to save memory.
+		 */
+		if (inject_prog_fault()) {
+			NS_DBG("do_state_action: injecting page prog fault\n");
+			return -1;
+		}
+
 		if (prog_page(ns, num) == -1)
 			return -1;
 





More information about the linux-mtd mailing list