[MTD][NAND] nandsim: modify report wear information function
xiaochuan-xu
xiaochuan-xu at cqu.edu.cn
Tue Jun 24 09:01:06 EDT 2008
a smart wear information report function, which can print wear leveling
information more obviously and vividly.
--- a/nandsim.c 2008-06-14 08:47:29.000000000 +0800
+++ b/nandsim.c 2008-06-14 08:47:29.000000000 +0800
@@ -101,6 +101,7 @@
static char *gravepages = NULL;
static unsigned int rptwear = 0;
static unsigned int overridesize = 0;
+static unsigned int pile_num = 10;
module_param(first_id_byte, uint, 0400);
module_param(second_id_byte, uint, 0400);
@@ -123,6 +124,7 @@
module_param(gravepages, charp, 0400);
module_param(rptwear, uint, 0400);
module_param(overridesize, uint, 0400);
+module_param(pile_num, uint,0400);
MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash
'read ID' command (manufacturer ID)");
MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND
Flash 'read ID' command (chip ID)");
@@ -154,6 +156,7 @@
MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size
overriding the ID bytes. "
"The size is specified in erase blocks and as the exponent of a
power of two"
" e.g. 5 means a size of 32 erase blocks");
+MODULE_PARM_DESC(pile_num, "Length of the array deciles[] and
decile_max[], 10 is default");
/* The largest possible page size */
#define NS_LARGEST_PAGE_SIZE 2048
@@ -842,7 +845,9 @@
static void update_wear(unsigned int erase_block_no)
{
unsigned long wmin = -1, wmax = 0, avg;
- unsigned long deciles[10], decile_max[10], tot = 0;
+ unsigned long *deciles = NULL, *decile_max = NULL;
+ unsigned long tot = 0, wear = 0;
+ unsigned long span;
unsigned int i;
if (!erase_block_wear)
@@ -857,25 +862,41 @@
if (rptwear_cnt < rptwear)
return;
rptwear_cnt = 0;
+
+ deciles = (unsigned long *)kzalloc(sizeof(unsigned long)*pile_num,
GFP_KERNEL);
+ if (!deciles) {
+ NS_ERR("Too many items for deciles\n");
+ return ;
+ }
+ decile_max = (unsigned long *)kmalloc(sizeof(unsigned long)*pile_num,
GFP_KERNEL);
+ if (!decile_max) {
+ NS_ERR("Too many items for decile_max\n");
+ kfree(deciles);
+ return;
+ }
+
/* Calc wear stats */
for (i = 0; i < wear_eb_count; ++i) {
- unsigned long wear = erase_block_wear[i];
+ wear = erase_block_wear[i];
if (wear < wmin)
wmin = wear;
if (wear > wmax)
wmax = wear;
tot += wear;
}
- for (i = 0; i < 9; ++i) {
- deciles[i] = 0;
- decile_max[i] = (wmax * (i + 1) + 5) / 10;
- }
- deciles[9] = 0;
- decile_max[9] = wmax;
+
+ span = wmax - wmin;
+
+ for (i = 0; i < pile_num - 1; ++i) {
+ decile_max[i] = (span * (i + 1) + (pile_num >> 1)) / pile_num + wmin;
+ }
+
+ decile_max[pile_num - 1] = wmax;
+
for (i = 0; i < wear_eb_count; ++i) {
int d;
unsigned long wear = erase_block_wear[i];
- for (d = 0; d < 10; ++d)
+ for (d = 0; d < pile_num; ++d)
if (wear <= decile_max[d]) {
deciles[d] += 1;
break;
@@ -883,22 +904,23 @@
}
avg = tot / wear_eb_count;
/* Output wear report */
- NS_INFO("*** Wear Report ***\n");
+ NS_INFO("****** Wear Report ******\n");
NS_INFO("Total numbers of erases: %lu\n", tot);
NS_INFO("Number of erase blocks: %u\n", wear_eb_count);
NS_INFO("Average number of erases: %lu\n", avg);
NS_INFO("Maximum number of erases: %lu\n", wmax);
NS_INFO("Minimum number of erases: %lu\n", wmin);
- for (i = 0; i < 10; ++i) {
- unsigned long from = (i ? decile_max[i - 1] + 1 : 0);
+ NS_INFO("Number of ebs with erase counts:\n");
+ for (i = 0; i < pile_num; ++i) {
+ unsigned long from = (i ? decile_max[i - 1] + 1 : wmin);
if (from > decile_max[i])
continue;
- NS_INFO("Number of ebs with erase counts from %lu to %lu : %lu\n",
- from,
- decile_max[i],
- deciles[i]);
+ NS_INFO("from %lu to %lu : %lu\n",from,decile_max[i],deciles[i]);
}
NS_INFO("*** End of Wear Report ***\n");
+
+ kfree(decile_max);
+ kfree(deciles);
}
/*
More information about the linux-mtd
mailing list