Changes to series and rx51_defconfig file for BFQ
[kernel-bfs] / kernel-bfs-2.6.28 / debian / patches / mtd-nandsim-add-cache_file-option.diff
1 --- linux-2.6.28.orig/drivers/mtd/nand/nandsim.c        2008-12-25 00:26:37.000000000 +0100
2 +++ linux-2.6.28/drivers/mtd/nand/nandsim.c     2011-01-28 15:36:55.284094498 +0100
3 @@ -38,6 +38,9 @@
4  #include <linux/delay.h>
5  #include <linux/list.h>
6  #include <linux/random.h>
7 +#include <linux/fs.h>
8 +
9 +#include <asm/uaccess.h>
10  
11  /* Default simulator parameters values */
12  #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE)  || \
13 @@ -100,6 +103,7 @@ static unsigned int bitflips = 0;
14  static char *gravepages = NULL;
15  static unsigned int rptwear = 0;
16  static unsigned int overridesize = 0;
17 +static char *cache_file = NULL;
18  
19  module_param(first_id_byte,  uint, 0400);
20  module_param(second_id_byte, uint, 0400);
21 @@ -122,12 +126,13 @@ module_param(bitflips,       uint, 0400)
22  module_param(gravepages,     charp, 0400);
23  module_param(rptwear,        uint, 0400);
24  module_param(overridesize,   uint, 0400);
25 +module_param(cache_file,     charp, 0400);
26  
27  MODULE_PARM_DESC(first_id_byte,  "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)");
28  MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
29  MODULE_PARM_DESC(third_id_byte,  "The third byte returned by NAND Flash 'read ID' command");
30  MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command");
31 -MODULE_PARM_DESC(access_delay,   "Initial page access delay (microiseconds)");
32 +MODULE_PARM_DESC(access_delay,   "Initial page access delay (microseconds)");
33  MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds");
34  MODULE_PARM_DESC(erase_delay,    "Sector erase delay (milliseconds)");
35  MODULE_PARM_DESC(output_cycle,   "Word output (from flash) time (nanodeconds)");
36 @@ -153,6 +158,7 @@ MODULE_PARM_DESC(rptwear,        "Number
37  MODULE_PARM_DESC(overridesize,   "Specifies the NAND Flash size overriding the ID bytes. "
38                                  "The size is specified in erase blocks and as the exponent of a power of two"
39                                  " e.g. 5 means a size of 32 erase blocks");
40 +MODULE_PARM_DESC(cache_file,     "File to use to cache nand pages instead of memory");
41  
42  /* The largest possible page size */
43  #define NS_LARGEST_PAGE_SIZE   2048
44 @@ -335,6 +341,11 @@ struct nandsim {
45                  int ale; /* address Latch Enable */
46                  int wp;  /* write Protect */
47          } lines;
48 +
49 +       /* Fields needed when using a cache file */
50 +       struct file *cfile; /* Open file */
51 +       unsigned char *pages_written; /* Which pages have been written */
52 +       void *file_buf;
53  };
54  
55  /*
56 @@ -427,11 +438,43 @@ static u_char ns_verify_buf[NS_LARGEST_P
57   */
58  static int alloc_device(struct nandsim *ns)
59  {
60 -       int i;
61 +       struct file *cfile;
62 +       int i, err;
63 +
64 +       if (cache_file) {
65 +               cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0640);
66 +               if (IS_ERR(cfile))
67 +                       return PTR_ERR(cfile);
68 +               if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) {
69 +                       NS_ERR("alloc_device: cache file not readable\n");
70 +                       err = -EINVAL;
71 +                       goto err_close;
72 +               }
73 +               if (!cfile->f_op->write && !cfile->f_op->aio_write) {
74 +                       NS_ERR("alloc_device: cache file not writeable\n");
75 +                       err = -EINVAL;
76 +                       goto err_close;
77 +               }
78 +               ns->pages_written = vmalloc(ns->geom.pgnum);
79 +               if (!ns->pages_written) {
80 +                       NS_ERR("alloc_device: unable to allocate pages written array\n");
81 +                       err = -ENOMEM;
82 +                       goto err_close;
83 +               }
84 +               ns->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
85 +               if (!ns->file_buf) {
86 +                       NS_ERR("alloc_device: unable to allocate file buf\n");
87 +                       err = -ENOMEM;
88 +                       goto err_free;
89 +               }
90 +               ns->cfile = cfile;
91 +               memset(ns->pages_written, 0, ns->geom.pgnum);
92 +               return 0;
93 +       }
94  
95         ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
96         if (!ns->pages) {
97 -               NS_ERR("alloc_map: unable to allocate page array\n");
98 +               NS_ERR("alloc_device: unable to allocate page array\n");
99                 return -ENOMEM;
100         }
101         for (i = 0; i < ns->geom.pgnum; i++) {
102 @@ -439,6 +482,12 @@ static int alloc_device(struct nandsim *
103         }
104  
105         return 0;
106 +
107 +err_free:
108 +       vfree(ns->pages_written);
109 +err_close:
110 +       filp_close(cfile, NULL);
111 +       return err;
112  }
113  
114  /*
115 @@ -448,6 +497,13 @@ static void free_device(struct nandsim *
116  {
117         int i;
118  
119 +       if (ns->cfile) {
120 +               kfree(ns->file_buf);
121 +               vfree(ns->pages_written);
122 +               filp_close(ns->cfile, NULL);
123 +               return;
124 +       }
125 +
126         if (ns->pages) {
127                 for (i = 0; i < ns->geom.pgnum; i++) {
128                         if (ns->pages[i].byte)
129 @@ -1211,6 +1267,30 @@ static int find_operation(struct nandsim
130         return -1;
131  }
132  
133 +static ssize_t read_file(struct file *file, void *buf, size_t count, loff_t *pos)
134 +{
135 +       mm_segment_t old_fs;
136 +       ssize_t tx;
137 +
138 +       old_fs = get_fs();
139 +       set_fs(get_ds());
140 +       tx = vfs_read(file, (char __user *)buf, count, pos);
141 +       set_fs(old_fs);
142 +       return tx;
143 +}
144 +
145 +static ssize_t write_file(struct file *file, void *buf, size_t count, loff_t *pos)
146 +{
147 +       mm_segment_t old_fs;
148 +       ssize_t tx;
149 +
150 +       old_fs = get_fs();
151 +       set_fs(get_ds());
152 +       tx = vfs_write(file, (char __user *)buf, count, pos);
153 +       set_fs(old_fs);
154 +       return tx;
155 +}
156 +
157  /*
158   * Returns a pointer to the current page.
159   */
160 @@ -1227,6 +1307,38 @@ static inline u_char *NS_PAGE_BYTE_OFF(s
161         return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
162  }
163  
164 +int do_read_error(struct nandsim *ns, int num)
165 +{
166 +       unsigned int page_no = ns->regs.row;
167 +
168 +       if (read_error(page_no)) {
169 +               int i;
170 +               memset(ns->buf.byte, 0xFF, num);
171 +               for (i = 0; i < num; ++i)
172 +                       ns->buf.byte[i] = random32();
173 +               NS_WARN("simulating read error in page %u\n", page_no);
174 +               return 1;
175 +       }
176 +       return 0;
177 +}
178 +
179 +void do_bit_flips(struct nandsim *ns, int num)
180 +{
181 +       if (bitflips && random32() < (1 << 22)) {
182 +               int flips = 1;
183 +               if (bitflips > 1)
184 +                       flips = (random32() % (int) bitflips) + 1;
185 +               while (flips--) {
186 +                       int pos = random32() % (num * 8);
187 +                       ns->buf.byte[pos / 8] ^= (1 << (pos % 8));
188 +                       NS_WARN("read_page: flipping bit %d in page %d "
189 +                               "reading from %d ecc: corrected=%u failed=%u\n",
190 +                               pos, ns->regs.row, ns->regs.column + ns->regs.off,
191 +                               nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed);
192 +               }
193 +       }
194 +}
195 +
196  /*
197   * Fill the NAND buffer with data read from the specified page.
198   */
199 @@ -1234,36 +1346,40 @@ static void read_page(struct nandsim *ns
200  {
201         union ns_mem *mypage;
202  
203 +       if (ns->cfile) {
204 +               if (!ns->pages_written[ns->regs.row]) {
205 +                       NS_DBG("read_page: page %d not written\n", ns->regs.row);
206 +                       memset(ns->buf.byte, 0xFF, num);
207 +               } else {
208 +                       loff_t pos;
209 +                       ssize_t tx;
210 +
211 +                       NS_DBG("read_page: page %d written, reading from %d\n",
212 +                               ns->regs.row, ns->regs.column + ns->regs.off);
213 +                       if (do_read_error(ns, num))
214 +                               return;
215 +                       pos = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off;
216 +                       tx = read_file(ns->cfile, ns->buf.byte, num, &pos);
217 +                       if (tx != num) {
218 +                               NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx);
219 +                               return;
220 +                       }
221 +                       do_bit_flips(ns, num);
222 +               }
223 +               return;
224 +       }
225 +
226         mypage = NS_GET_PAGE(ns);
227         if (mypage->byte == NULL) {
228                 NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
229                 memset(ns->buf.byte, 0xFF, num);
230         } else {
231 -               unsigned int page_no = ns->regs.row;
232                 NS_DBG("read_page: page %d allocated, reading from %d\n",
233                         ns->regs.row, ns->regs.column + ns->regs.off);
234 -               if (read_error(page_no)) {
235 -                       int i;
236 -                       memset(ns->buf.byte, 0xFF, num);
237 -                       for (i = 0; i < num; ++i)
238 -                               ns->buf.byte[i] = random32();
239 -                       NS_WARN("simulating read error in page %u\n", page_no);
240 +               if (do_read_error(ns, num))
241                         return;
242 -               }
243                 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
244 -               if (bitflips && random32() < (1 << 22)) {
245 -                       int flips = 1;
246 -                       if (bitflips > 1)
247 -                               flips = (random32() % (int) bitflips) + 1;
248 -                       while (flips--) {
249 -                               int pos = random32() % (num * 8);
250 -                               ns->buf.byte[pos / 8] ^= (1 << (pos % 8));
251 -                               NS_WARN("read_page: flipping bit %d in page %d "
252 -                                       "reading from %d ecc: corrected=%u failed=%u\n",
253 -                                       pos, ns->regs.row, ns->regs.column + ns->regs.off,
254 -                                       nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed);
255 -                       }
256 -               }
257 +               do_bit_flips(ns, num);
258         }
259  }
260  
261 @@ -1275,6 +1391,15 @@ static void erase_sector(struct nandsim 
262         union ns_mem *mypage;
263         int i;
264  
265 +       if (ns->cfile) {
266 +               for (i = 0; i < ns->geom.pgsec; i++)
267 +                       if (ns->pages_written[ns->regs.row + i]) {
268 +                               NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i);
269 +                               ns->pages_written[ns->regs.row + i] = 0;
270 +                       }
271 +               return;
272 +       }
273 +
274         mypage = NS_GET_PAGE(ns);
275         for (i = 0; i < ns->geom.pgsec; i++) {
276                 if (mypage->byte != NULL) {
277 @@ -1295,6 +1420,47 @@ static int prog_page(struct nandsim *ns,
278         union ns_mem *mypage;
279         u_char *pg_off;
280  
281 +       if (ns->cfile) {
282 +               loff_t off, pos;
283 +               ssize_t tx;
284 +               int all;
285 +
286 +               NS_DBG("prog_page: writing page %d\n", ns->regs.row);
287 +               pg_off = ns->file_buf + ns->regs.column + ns->regs.off;
288 +               off = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off;
289 +               if (!ns->pages_written[ns->regs.row]) {
290 +                       all = 1;
291 +                       memset(ns->file_buf, 0xff, ns->geom.pgszoob);
292 +               } else {
293 +                       all = 0;
294 +                       pos = off;
295 +                       tx = read_file(ns->cfile, pg_off, num, &pos);
296 +                       if (tx != num) {
297 +                               NS_ERR("prog_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx);
298 +                               return -1;
299 +                       }
300 +               }
301 +               for (i = 0; i < num; i++)
302 +                       pg_off[i] &= ns->buf.byte[i];
303 +               if (all) {
304 +                       pos = (loff_t)ns->regs.row * ns->geom.pgszoob;
305 +                       tx = write_file(ns->cfile, ns->file_buf, ns->geom.pgszoob, &pos);
306 +                       if (tx != ns->geom.pgszoob) {
307 +                               NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx);
308 +                               return -1;
309 +                       }
310 +                       ns->pages_written[ns->regs.row] = 1;
311 +               } else {
312 +                       pos = off;
313 +                       tx = write_file(ns->cfile, pg_off, num, &pos);
314 +                       if (tx != num) {
315 +                               NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx);
316 +                               return -1;
317 +                       }
318 +               }
319 +               return 0;
320 +       }
321 +
322         mypage = NS_GET_PAGE(ns);
323         if (mypage->byte == NULL) {
324                 NS_DBG("prog_page: allocating page %d\n", ns->regs.row);