blob: c136a92be20b2871f14d096cdc67c8ca920edf18 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * Bad Block Management support for PXA3XX.
3 * Copyright (C) 2009 Marvell International Ltd.
4 * Lei Wen <leiwen@marvell.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/partitions.h>
14#include <asm/errno.h>
15#include <mtd/pxa3xx_bbm.h>
16#include <asm/arch/cpu.h>
17#include <asm/arch/config.h>
18#include <asm/arch-pxa182x/pxa182x.h>
19#include <asm/arch-pxa182x/cpu.h>
20#ifndef CONFIG_ASR1901
21#include <asm/arch-asr1802s/asr1802.h>
22#include <asm/arch-asr1802s/cpu.h>
23#endif
24#include <malloc.h>
25#include <common.h>
26
27#define mb() __asm__ __volatile__ ("" : : : "memory")
28
29#define NEW_BBM_RELOC_PERCENTAGE (5)
30#define MAX_SUPPRTED_PARTNUM (3)
31#define MAX_OBM_BLOCK (3)
32static struct mtd_partition *pxa3xx_check_partition(struct mtd_info *mtd,
33 struct mtd_partition *part, int *num);
34
35static int erase_success;
36static int should_reloc = 1;
37static int rd_scrubbing = 0;
38static int disable_reloc = 0;
39static int rd_disturb_cnt = 0;
40
41static inline unsigned short from32to16(unsigned int x)
42{
43 /* add up 16-bit and 16-bit for 16+c bit */
44 x = (x & 0xffff) + (x >> 16);
45 /* add up carry.. */
46 x = (x & 0xffff) + (x >> 16);
47 return x;
48}
49
50static unsigned int bbm_crc16(unsigned int crcu32,
51 const unsigned char *ptr, unsigned int buf_len)
52{
53 static const unsigned int s_crc32[16] = {
54 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
55 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
56 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
57 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
58 };
59 if (!ptr)
60 return 0;
61 crcu32 = ~crcu32;
62 while (buf_len--)
63 {
64 unsigned char b = *ptr++;
65 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
66 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
67 }
68
69 return from32to16(~crcu32);
70}
71
72static int is_empty(void *buf, int len)
73{
74 uint8_t *p = buf;
75 int i;
76
77 for (i = 0; i < len; i++)
78 if (*p++ != 0xff)
79 return 0;
80 return 1;
81}
82
83static void pxa3xx_bbm_callback(struct erase_info *instr)
84{
85 if (instr->fail_addr == MTD_FAIL_ADDR_UNKNOWN)
86 erase_success = 1;
87 else
88 erase_success = 0;
89}
90
91static void dump_reloc_table(struct reloc_item *item, int entry_num)
92{
93 int i;
94
95 if (entry_num == 0) {
96 printk(KERN_INFO "The reloc table is empty now\n");
97 return;
98 }
99
100 printk(KERN_INFO "Total %d entry:\n", entry_num);
101 for (i = 0; i < entry_num; i++) {
102 if (item[i].from == BLK_BAD && item[i].to == BLK_BAD)
103 continue;
104
105 printk(KERN_INFO "%d: block %8d ---> %d\n",
106 i + 1, item[i].from, item[i].to);
107 }
108}
109
110static void dump_fact_bads(struct pxa3xx_bbt *fbbt)
111{
112 uint32_t *fact_bad = (uint32_t *)&fbbt->fact_bad;
113 int i;
114
115 if (fbbt->entry_num == 0) {
116 printk(KERN_INFO "There is no factory bad block!!\n");
117 return;
118 }
119
120 for (i = 0; i < fbbt->entry_num; i ++)
121 printk(KERN_INFO "block %d is bad.\n", fact_bad[i]);
122}
123
124static void dump_part_info(struct mtd_info *mtd)
125{
126 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
127 struct pxa3xx_new_bbm *new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
128 struct pxa3xx_part *part = new_bbm->part;
129 struct pxa3xx_partinfo *partinfo;
130 struct pxa3xx_bbt *rbbt;
131 struct reloc_item *item;
132 char tmp[9];
133 int i;
134 uint32_t swap_temp;
135
136 printk(KERN_INFO "\nThere are totally %d parts", part->part_num);
137 for (i = 0; i < part->part_num; i ++) {
138 printk(KERN_INFO "\n===The part %d info:===\n", i);
139 partinfo = &new_bbm->partinfo[i];
140 if (partinfo->type == PART_LOGI)
141 printk(KERN_INFO "This part is Logi\n");
142 else
143 printk(KERN_INFO "This part is Phys\n");
144 if (partinfo->usage && partinfo->usage != 0xffffffff) {
145 memcpy(tmp, &partinfo->usage, 4);
146 tmp[4] = '\0';
147 printk(KERN_INFO "Part name %s\n", tmp);
148 }
149 if (partinfo->identifier && partinfo->identifier != 0xffffffff) {
150 memcpy(tmp, &partinfo->identifier, 4);
151 tmp[4] = '\0';
152 printk(KERN_INFO "identifier %s\n", tmp);
153 }
154 printk(KERN_INFO "Attr %16x\n", partinfo->attrs);
155 printk(KERN_INFO "This part start from %llx to %llx\n",
156 partinfo->start_addr, partinfo->end_addr);
157 printk(KERN_INFO "Reserved pool start from %llx, size %llx\n",
158 partinfo->rp_start, partinfo->rp_size);
159 if (partinfo->rp_algo == RP_UPWD)
160 printk(KERN_INFO "Reserved pool grow upwards\n");
161 else
162 printk(KERN_INFO "Reserved pool grow downwards\n");
163
164 swap_temp = partinfo->rbbt_type;
165 swab32s(&swap_temp);
166 memcpy(tmp, &swap_temp, 4);
167 tmp[4] = '\0';
168 printk(KERN_INFO "\nRBBT type %s\n", tmp);
169 printk(KERN_INFO "RBBT start at %llx, its back at %llx\n",
170 partinfo->rbbt_start, partinfo->rbbt_start_back);
171 rbbt = &new_bbm->rbbt[i];
172 printk(KERN_INFO "RBBT could max reloc %d blocks\n",
173 new_bbm->max_reloc_entry[i]);
174 printk(KERN_INFO "Current slot is at 0x%llx\n",
175 new_bbm->rbbt_offset[i] << mtd->writesize_shift);
176 item = (struct reloc_item *)&rbbt->reloc;
177 dump_reloc_table(item, new_bbm->rbbt->entry_num);
178 }
179}
180
181static void pxa3xx_uninit_reloc_tb(struct mtd_info *mtd)
182{
183 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
184 struct pxa3xx_legacy_bbm *legacy_bbm;
185 struct pxa3xx_new_bbm *new_bbm;
186
187 if (bbm) {
188 switch (bbm->bbm_type) {
189 case BBM_LEGACY:
190 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
191 kfree(legacy_bbm->table);
192 break;
193
194 case BBM_NEW:
195 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
196 kfree(new_bbm->rbbt);
197 kfree(new_bbm->fbbt);
198 kfree(new_bbm->part);
199 default:
200 break;
201 }
202
203 if (bbm->data_buf)
204 kfree(bbm->data_buf);
205 kfree(bbm);
206 mtd->bbm = NULL;
207 }
208}
209
210/*
211 * Found the block belong to which partition
212 */
213static int find_part(struct mtd_info *mtd, uint64_t offset)
214{
215 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
216 struct pxa3xx_new_bbm *new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
217 struct pxa3xx_part *part = new_bbm->part;
218 struct pxa3xx_partinfo *partinfo;
219 int i, found_part = -EINVAL;
220
221 for (i = 0; i < part->part_num; i ++) {
222 partinfo = &(new_bbm->partinfo[i]);
223 if (offset < partinfo->start_addr)
224 break;
225
226 if (offset < partinfo->end_addr) {
227 found_part = i;
228 break;
229 }
230 }
231
232 return found_part;
233}
234
235/*
236 * start_page and end_page should be in one block boundary
237 * direction: 1 for positive page grow order, 0 for the reversed order
238 * indicator should be meaningful bit order stand for BBT
239 */
240int page_search(struct mtd_info *mtd, int start_page, int end_page,
241 int direction, unsigned int indicator, void *buf, unsigned int mask)
242{
243 int found_page = -EINVAL, cur_page, ret;
244 unsigned int header;
245 size_t retlen;
246
247 cur_page = (direction == ORDER_POSITIVE) ? end_page : start_page;
248 while (start_page <= end_page) {
249 ret = mtd->_read(mtd, cur_page << mtd->writesize_shift,
250 mtd->writesize, &retlen, buf);
251 header = *(unsigned int *)buf & mask;
252 if (ret >= 0 && header == indicator) {
253 found_page = cur_page;
254 break;
255 }
256
257 if (direction == ORDER_POSITIVE) {
258 cur_page --;
259 if (cur_page < start_page)
260 break;
261 }
262 else {
263 cur_page ++;
264 if (cur_page > end_page)
265 break;
266 }
267 }
268
269 return found_page;
270}
271
272static int legacy_bbm_copy_peb(struct mtd_info *mtd, int from, int to,
273 int start_page, int end_page, int flag)
274{
275 int from_addr = from << mtd->erasesize_shift;
276 int to_addr = to << mtd->erasesize_shift;
277 int page_size = mtd->writesize;
278 int pages_per_block = mtd->erasesize >> mtd->writesize_shift;
279 int addr, end_addr, ret = 0;
280 size_t retlen;
281 void *buf, *rbuf;
282
283 buf = kzalloc(page_size * 2, GFP_KERNEL);
284 if (!buf)
285 return -ENOMEM;
286
287 rbuf = buf + page_size;
288
289 end_addr = min(end_page, pages_per_block - 1) << mtd->writesize_shift;
290 addr = start_page << mtd->writesize_shift;
291
292 if (flag & DEST_SKIP_ALL_FF_PAGE) {
293 /* skip ALL 0xFF page, since FS may write later */
294 while (1) {
295 ret = mtd->_read(mtd, from_addr + end_addr,
296 page_size, &retlen, buf);
297 if (ret < 0) {
298 ret = -EIO;
299 goto out;
300 }
301
302 if (!is_empty(buf, mtd->writesize)) {
303 pr_debug("will copy from page %d to %d\n",
304 start_page,
305 end_addr >> mtd->writesize_shift);
306 break;
307 }
308
309 end_addr -= mtd->writesize;
310 if (end_addr < addr)
311 break;
312 }
313 }
314
315 while (addr <= end_addr) {
316 ret = mtd->_read(mtd, from_addr + addr, page_size,
317 &retlen, buf);
318 if(ret < 0) {
319 ret = -EIO;
320 goto out;
321 }
322
323 if (flag & DEST_NOT_USE_RELOC)
324 disable_reloc = 1;
325
326 ret = mtd->_write(mtd, to_addr + addr, page_size,
327 &retlen, buf);
328 if (ret) {
329 if (flag & DEST_NOT_USE_RELOC)
330 disable_reloc = 0;
331
332 ret = -EAGAIN;
333 goto out;
334 }
335
336 /* Read back and compare */
337 memset(rbuf, 0xFF, page_size);
338 ret = mtd->_read(mtd, to_addr + addr, page_size,
339 &retlen, rbuf);
340
341 if (flag & DEST_NOT_USE_RELOC)
342 disable_reloc = 0;
343
344 if (ret < 0 || memcmp(buf, rbuf, page_size)) {
345 ret = -EAGAIN;
346 goto out;
347 }
348
349 ret = 0;
350 addr += page_size;
351 }
352out:
353 kfree(buf);
354 return ret;
355}
356
357static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
358
359static int check_pattern(const void *buf, uint8_t patt, int size)
360{
361 int i;
362
363 for (i = 0; i < size; i++)
364 if (((const uint8_t *)buf)[i] != patt)
365 return 0;
366 return 1;
367}
368
369static int torture_block(struct mtd_info *mtd, int block)
370{
371 struct erase_info instr;
372 int patt_count = ARRAY_SIZE(patterns);
373 int addr = block << mtd->erasesize_shift;
374 size_t retlen;
375 int i, ret = 0;
376 void *buf;
377
378 buf = kzalloc(mtd->erasesize, GFP_KERNEL);
379 if (!buf) {
380 printk(KERN_INFO "Failed to malloc erasesize memory\n");
381 return -ENOMEM;
382 }
383
384 disable_reloc = 1;
385 rd_disturb_cnt = 0;
386
387 for (i = 0; i < patt_count; i++) {
388 memset(&instr, 0, sizeof(struct erase_info));
389 instr.mtd = mtd;
390 instr.addr = (uint64_t)block << mtd->erasesize_shift;
391 instr.len = mtd->erasesize;
392 instr.callback = pxa3xx_bbm_callback;
393
394 should_reloc = 0;
395 mtd->_erase(mtd, &instr);
396 should_reloc = 1;
397 if (!erase_success) {
398 ret = -EIO;
399 goto out;
400 }
401
402 ret = mtd->_read(mtd, addr, mtd->erasesize, &retlen, buf);
403 if (ret < 0 || rd_disturb_cnt) {
404 goto out;
405 }
406
407 ret = check_pattern(buf, 0xff, mtd->erasesize);
408 if (ret == 0) {
409 ret = -EIO;
410 goto out;
411 }
412
413 memset(buf, patterns[i], mtd->erasesize);
414 ret = mtd->_write(mtd, addr, mtd->erasesize, &retlen, buf);
415 if (ret)
416 goto out;
417
418 memset(buf, ~patterns[i], mtd->erasesize);
419 ret = mtd->_read(mtd, addr, mtd->erasesize, &retlen, buf);
420 if (ret < 0 || rd_disturb_cnt)
421 goto out;
422
423 ret = check_pattern(buf, patterns[i], mtd->erasesize);
424 if (ret == 0) {
425 ret = -EIO;
426 goto out;
427 }
428 }
429
430 memset(&instr, 0, sizeof(struct erase_info));
431 instr.mtd = mtd;
432 instr.addr = (uint64_t)block << mtd->erasesize_shift;
433 instr.len = mtd->erasesize;
434 instr.callback = pxa3xx_bbm_callback;
435
436 should_reloc = 0;
437 mtd->_erase(mtd, &instr);
438 should_reloc = 1;
439 if (!erase_success) {
440 ret = -EIO;
441 goto out;
442 }
443
444 ret = 0;
445out:
446 if (rd_disturb_cnt) {
447 rd_disturb_cnt = 0;
448 printk(KERN_INFO "Find read disturb during torture %d!\n",
449 block);
450 ret = -EIO;
451 }
452
453 disable_reloc = 0;
454 kfree(buf);
455 if (!ret)
456 printk(KERN_INFO "Success to recycle block %d\n", block);
457 return ret;
458}
459
460int pxa3xx_abbt_recycle_blk(struct mtd_info *mtd)
461{
462 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
463 struct pxa3xx_legacy_bbm *legacy_bbm;
464 struct pxa3xx_legacy_abbm *abbm;
465 struct pxa3xx_abbt *abbt;
466 struct reloc_item *item_abbt;
467 int ret, i, total_abbt;
468
469 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
470 abbm = &legacy_bbm->abbm;
471 abbt = abbm->abbt;
472 item_abbt = abbt->reloc;
473 total_abbt = abbt->entry_num;
474
475 for (i = 0; i < total_abbt; i++) {
476 if (item_abbt[i].from == BLK_WAIT_RECYCLE) {
477 ret = torture_block(mtd, item_abbt[i].to);
478 if (ret == -ENOMEM) {
479 break;
480 } else if (ret) {
481 item_abbt[i].from = BLK_RECYCLE_FAIL;
482 } else {
483 item_abbt[i].from = BLK_RECYCLED;
484 abbt->recycled_num++;
485 }
486
487 abbt->wait_recycle_num--;
488 }
489 }
490
491 return 0;
492}
493
494static int ext_legacy_bbt_relocate(struct mtd_info *mtd, loff_t ofs, int scrub)
495{
496 struct pxa3xx_bbm *bbm = mtd->bbm;
497 struct pxa3xx_legacy_bbm *legacy_bbm = NULL;
498 struct pxa3xx_legacy_abbm *abbm;
499 struct pxa3xx_abbt *abbt;
500 struct reloc_item *item, *item_abbt;
501 struct erase_info instr;
502 int block = (int)(ofs >> mtd->erasesize_shift);
503 int reloc_block, entry_num = -1;
504 int i, _rel, max_entry, bitflip_entry, reloc_boundary;
505 int total, total_abbt, blk_index, blk_recyc = -1;
506 char *rp_tbl;
507 int ret;
508 int bitflip_cnt_entry = -1;
509
510 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
511 abbm = &legacy_bbm->abbm;
512 abbt = abbm->abbt;
513 item = legacy_bbm->reloc;
514 max_entry = legacy_bbm->reserved_blks;
515 reloc_boundary = mtd_div_by_eb(mtd->size, mtd) - max_entry;
516 total = legacy_bbm->table->total;
517 item_abbt = abbt->reloc;
518 total_abbt = abbt->entry_num;
519
520 if (block >= reloc_boundary &&
521 block < reloc_boundary + max_entry - ABBT_BLK_NUM)
522 return -EINVAL;
523
524 printk(KERN_INFO "ready to put %llx into the bbt\n", ofs);
525 /* clear cache reloc */
526 legacy_bbm->reloc_cache.from = 0xFFFF;
527
528 rp_tbl = bbm->rel_dist;
529 if (!rp_tbl) {
530 rp_tbl = kzalloc(max_entry, GFP_KERNEL);
531 /* need to save this */
532 bbm->rel_dist = rp_tbl;
533 } else {
534 memset(rp_tbl, 0, max_entry);
535 }
536
537 /* Scan and save reserved block pool usage by two-level bbt */
538 bitflip_entry = 0;
539 for (i = 0; i < total_abbt; i ++) {
540 _rel = item_abbt[i].to - reloc_boundary;
541 if (item_abbt[i].from == BLK_FLIP_COUNT)
542 bitflip_cnt_entry = i;
543 else if (_rel >= 0)
544 rp_tbl[_rel] = 1;
545 else if (item_abbt[i].from != BLK_BAD)
546 bitflip_entry++;
547 }
548
549 if (bitflip_cnt_entry == -1) {
550 item_abbt[total_abbt].from = BLK_FLIP_COUNT;
551 item_abbt[total_abbt].to = 0;
552 bitflip_cnt_entry = total_abbt;
553 total_abbt++;
554 }
555
556 /*
557 * Some ugly spi-nand may generate too many bit-flips, use up BBT table,
558 * limit max bit-flip blocks, so that markbad can be use used.
559 */
560 if (scrub == ABBT_SCRUB_ANY &&
561 ((bitflip_entry + (max_entry - ABBT_BLK_NUM) * 2) >= abbm->max_entry)) {
562 printk(KERN_ERR "bit-flip number reach threshold(%d, %d, %d), exit\n",
563 bitflip_entry, max_entry, abbm->max_entry);
564 return -EINVAL;
565 }
566
567 /* Identify whether the block has been relocated */
568 for(i = total_abbt - 1; i >= 0; i --) {
569 if(block == item_abbt[i].from)
570 entry_num = i;
571 }
572
573 /*
574 * Find the available block with the largest number in reservered area
575 */
576 while (1) {
577 if (block == abbm->main_blk || block == abbm->mirror_blk ||
578 block <= MAX_OBM_BLOCK) {
579 int bbt_max;
580
581 bbt_max = (mtd->writesize - sizeof(struct reloc_table)) /
582 sizeof(struct reloc_item);
583 if (total + 4 >= bbt_max) {
584 printk("bbt reach max(%d, %d)\n", total, bbt_max);
585 return -EINVAL;
586 }
587 }
588
589 if (total_abbt >= (abbm->max_entry - 2)) {
590 printk(KERN_ERR "ABBT table full: %ditems\n", total_abbt);
591 return -EINVAL;
592 }
593
594 /* Make sure that reloc_block is pointing to a valid block */
595 if (scrub == ABBT_SCRUB_BACK) {
596 reloc_block = -1;
597 } else {
598 for (reloc_block = max_entry - ABBT_BLK_NUM - 1;
599 reloc_block >= 0; reloc_block --) {
600 if (rp_tbl[reloc_block] == 0) {
601 reloc_block = reloc_block + reloc_boundary;
602 printk(KERN_INFO
603 "get block %d from reserved area\n",
604 reloc_block);
605 break;
606 }
607 }
608 }
609
610 if (reloc_block < 0) {
611 pxa3xx_abbt_recycle_blk(mtd);
612 /*
613 * No block from reserved pool, need to check if any
614 * recycled blocks exist
615 */
616 for (i = 0; i < total_abbt; i++) {
617 if (item_abbt[i].from == BLK_RECYCLED &&
618 (scrub != ABBT_SCRUB_BACK ||
619 item_abbt[i].to == block)) {
620 reloc_block = item_abbt[i].to;
621 blk_recyc = i;
622 printk(KERN_INFO
623 "get block %d from recycle area\n",
624 reloc_block);
625 abbt->recycled_num--;
626 break;
627 }
628 }
629 }
630
631 if (reloc_block < 0) {
632 /* if block failed to recycle, not map back to itself */
633 if (scrub == ABBT_SCRUB_BACK)
634 return -ENOSPC;
635
636 if (entry_num >= 0 && !scrub)
637 item_abbt[entry_num].from = BLK_BAD;
638
639 item_abbt[total_abbt].from = BLK_BAD;
640 item_abbt[total_abbt].to = block;
641 total_abbt++;
642 printk(KERN_ERR "Reserved area has no left blocks\n");
643 return -ENOSPC;
644 }
645
646 memset(&instr, 0, sizeof(struct erase_info));
647 instr.mtd = mtd;
648 instr.addr = (uint64_t)reloc_block << mtd->erasesize_shift;
649 instr.len = mtd->erasesize;
650 instr.callback = pxa3xx_bbm_callback;
651
652 disable_reloc = 1;
653 should_reloc = 0;
654 mtd->_erase(mtd, &instr);
655 should_reloc = 1;
656 disable_reloc = 0;
657
658 ret = 0;
659 if (erase_success) {
660 if (scrub)
661 ret = legacy_bbm_copy_peb(
662 mtd, block, reloc_block, 0,
663 (mtd->erasesize >>
664 mtd->writesize_shift) - 1,
665 DEST_NOT_USE_RELOC | DEST_SKIP_ALL_FF_PAGE);
666 if (!ret)
667 break;
668 if (ret != -EAGAIN) {
669 printk(KERN_INFO "%s: fatal error, exit\n",
670 __func__);
671 return ret;
672 }
673 }
674
675 /* reach here means erase or copy failure */
676 if (scrub == ABBT_SCRUB_BACK ||
677 (!ret && instr.fail_addr != instr.addr))
678 return -EINVAL;
679 /*
680 * skip it if the reloc_block is also a bad block(erase or
681 * write fail).
682 */
683 if (blk_recyc != -1) {
684 item_abbt[blk_recyc].from = BLK_WAIT_RECYCLE;
685 } else {
686 item_abbt[total_abbt].from = BLK_WAIT_RECYCLE;
687 item_abbt[total_abbt].to = reloc_block;
688 total_abbt++;
689 legacy_bbm->status |= ABBT_CHANGED;
690 }
691
692 blk_recyc = -1;
693 _rel = reloc_block - reloc_boundary;
694 if (_rel >= 0)
695 rp_tbl[_rel] = 1;
696 }
697
698 if (total_abbt >= (abbm->max_entry - 2)) {
699 printk(KERN_ERR "ABBT table full: %ditems\n", total_abbt);
700 return -EINVAL;
701 }
702
703 /*
704 * Create the relocated block information in the table
705 * when the block is relocated before, blob should modify
706 * the original entry to new relocated block and the old
707 * relocated block point to 65535. If not the situation,
708 * create a new entry
709 */
710 if (blk_recyc != -1) {
711 blk_index = blk_recyc;
712 } else {
713 blk_index = total_abbt;
714 total_abbt++;
715 }
716
717 /*
718 * Move recycle block to bbt tail, avoid being used repeatedly
719 * Use torture test to check if it is a true bad block later
720 */
721 if (entry_num != -1) {
722 item_abbt[blk_index].from = item_abbt[total_abbt - 1].from;
723 item_abbt[blk_index].to = item_abbt[total_abbt - 1].to;
724 item_abbt[total_abbt - 1].from = BLK_WAIT_RECYCLE;
725 item_abbt[total_abbt - 1].to = item_abbt[entry_num].to;
726 item_abbt[entry_num].to = reloc_block;
727 } else {
728 item_abbt[blk_index].from = block;
729 item_abbt[blk_index].to = reloc_block;
730 item_abbt[total_abbt].from = BLK_WAIT_RECYCLE;
731 item_abbt[total_abbt].to = block;
732 total_abbt++;
733
734 entry_num = blk_index;
735 }
736
737 /* Update bitfilp count statistics */
738 if (scrub == ABBT_SCRUB_ANY)
739 item_abbt[bitflip_cnt_entry].to++;
740
741 /* Update first level bbt for blocks which second bbt located */
742 if (block == abbm->main_blk || block == abbm->mirror_blk ||
743 block <= MAX_OBM_BLOCK) {
744 unsigned int *pver, *pcsum;
745 unsigned short csum;
746
747 for (i = 0; i < total; i++) {
748 if (item[i].from == block) {
749 /*
750 * make a fake entry for legacy bbm, so that
751 * new bbt has more entries than old, then we
752 * can find out which one is the latest.
753 */
754 item[i].from = BLK_BAD;
755 item[i].to = BLK_BAD;
756 break;
757 }
758 }
759
760 /* bootrom not support A --> A in BBT */
761 if (block == reloc_block) {
762 item[total].from = BLK_BAD;
763 item[total].to = BLK_BAD;
764 } else {
765 item[total].from = block;
766 item[total].to = reloc_block;
767 }
768 total++;
769 legacy_bbm->table->total = total;
770 legacy_bbm->status |= BBT_CHANGED;
771
772 /*
773 * update BBT crc:
774 * BBT layout (Append ABB version and crc at tail)
775 * | magic(2B) |
776 * | entry number(2B) |
777 * | entry(4B)... |
778 * | ABB version(4B) |
779 * | Owner(2bit) |
780 * | reserved(14bit) |
781 * | CRC(2B) |
782 */
783 pver = (unsigned int *)(item + total);
784 *pver = ABBT_VERSION_2001;
785 pcsum = pver + 1;
786 *pcsum = BBT_UBOOT; /* owner at lower 2bit */
787 mb();
788 csum = bbm_crc16(0, (unsigned char *)legacy_bbm->table,
789 (sizeof(struct reloc_table) +
790 total * sizeof(struct reloc_item) + 4 + 2));
791
792 *pcsum |= csum << 16;
793 }
794
795 /* Remove redundant entry such as A -> A */
796 if (block == reloc_block) {
797 for (i = entry_num; i < total_abbt - 1; i++) {
798 item_abbt[i].from = item_abbt[i+1].from;
799 item_abbt[i].to = item_abbt[i+1].to;
800 }
801
802 item_abbt[total_abbt - 1].from = BLK_BAD;
803 item_abbt[total_abbt - 1].to = BLK_BAD;
804
805 total_abbt--;
806 }
807
808 abbt->wait_recycle_num++;
809 abbt->refcnt++;
810 abbt->entry_num = total_abbt;
811 legacy_bbm->status |= ABBT_CHANGED;
812
813 /* update ABBT crc */
814 if (abbt->ver == ABBT_VERSION_2001) {
815 abbt->owner = BBT_UBOOT;
816 abbt->reserved = 0;
817 abbt->crc = 0;
818 mb();
819 abbt->crc = bbm_crc16(0, (unsigned char *)abbt,
820 (sizeof(struct pxa3xx_abbt) +
821 abbt->entry_num * sizeof(struct reloc_item)));
822 }
823
824 /* clear cache reloc */
825 legacy_bbm->reloc_cache.from = 0xFFFF;
826 printk(KERN_INFO "%s: block %d --> %d\n", __func__,
827 block, reloc_block);
828 return 0;
829}
830
831/* add the relocation entry into the relocation table
832 * It's valid on MOBM V3.
833 * If the relocated block is bad, an new entry will be added into the
834 * bottom of the relocation table.
835 */
836static int sync_pxa3xx_bbt(struct mtd_info *mtd, loff_t ofs)
837{
838 struct pxa3xx_bbm *bbm = mtd->bbm;
839 struct pxa3xx_legacy_bbm *legacy_bbm = NULL;
840 struct pxa3xx_new_bbm *new_bbm;
841 struct pxa3xx_partinfo *partinfo;
842 struct pxa3xx_bbt *bbt = NULL;
843 struct reloc_item *item;
844 struct erase_info instr;
845 int reloc_block, entry_num = -1;
846 char *rel_dist;
847 int i, block, _rel, max_reloc_entry, reloc_boundary, total, part;
848
849 printk(KERN_INFO "ready to put %llx into the bbt\n", ofs);
850 if (bbm->bbm_type == BBM_LEGACY) {
851 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
852 item = legacy_bbm->reloc;
853 reloc_boundary = mtd_div_by_eb(mtd->size, mtd)
854 - legacy_bbm->max_reloc_entry;
855 max_reloc_entry = legacy_bbm->max_reloc_entry;
856 total = legacy_bbm->table->total;
857 }
858 else {
859 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
860 part = find_part(mtd, ofs);
861 if (part < 0)
862 return -EINVAL;
863 new_bbm->update_indicator |= 1 << part;
864 max_reloc_entry = new_bbm->max_reloc_entry[part];
865 bbt = &new_bbm->rbbt[part];
866 partinfo = &new_bbm->partinfo[part];
867 item = (struct reloc_item *)&bbt->reloc;
868 reloc_boundary = mtd_div_by_eb(partinfo->rp_start, mtd);
869 total = bbt->entry_num;
870 }
871
872 block = (int)(ofs >> mtd->erasesize_shift);
873 if (total >= max_reloc_entry) {
874 printk(KERN_WARNING "Relocation table currently have %d\n"
875 "Exceed max num %d, cannot relocate block %d!!\n",
876 total, max_reloc_entry, block);
877 return -ENOSPC;
878 }
879
880 if (block >= reloc_boundary)
881 return -EINVAL;
882
883 //identify whether the block has been relocated
884 for(i = total - 1; i >= 0; i --) {
885 if(block == item[i].from)
886 entry_num = i;
887 }
888
889 rel_dist = bbm->rel_dist;
890 if (!rel_dist) {
891 rel_dist = kzalloc(max_reloc_entry, GFP_KERNEL);
892 /* need to save this */
893 bbm->rel_dist = rel_dist;
894 }
895 else
896 memset(rel_dist, 0, max_reloc_entry);
897 //find the available block with the largest number in reservered area
898 for (i = 0; i < total; i ++) {
899 _rel = (item[i].to != 65535) ? item[i].to : item[i].from;
900 rel_dist[_rel - reloc_boundary] = 1;
901 }
902
903 while (1) {
904 /* Make sure that reloc_block is pointing to a valid block */
905 for (reloc_block = max_reloc_entry - 1;
906 reloc_block >= 0; reloc_block --) {
907 if (rel_dist[reloc_block] == 0) {
908 printk(KERN_INFO "get block %d from reserved area\n", reloc_block + reloc_boundary);
909 break;
910 }
911 }
912
913 if (reloc_block < 0) {
914 if (entry_num >= 0) {
915 item[entry_num].from = item[entry_num].to;
916 item[entry_num].to = 65535;
917 }
918 printk(KERN_ERR "Reserved ared has no left blocks\n");
919 return -ENOSPC;
920 }
921
922 reloc_block = reloc_block + reloc_boundary;
923 memset(&instr, 0, sizeof(struct erase_info));
924 instr.mtd = mtd;
925 instr.addr = (uint64_t)reloc_block << mtd->erasesize_shift;
926 instr.len = mtd->erasesize;
927 instr.callback = pxa3xx_bbm_callback;
928
929 should_reloc = 0;
930 mtd->_erase(mtd, &instr);
931 should_reloc = 1;
932 if (erase_success) {
933 printk(KERN_INFO "The block is verified\n");
934 break;
935 }
936 else {
937 /* skip it if the reloc_block is also a
938 * bad block
939 */
940 if (instr.fail_addr == instr.addr) {
941 item[total].from = reloc_block;
942 item[total].to = 65535;
943 total ++;
944 rel_dist[reloc_block - reloc_boundary] = 1;;
945 continue;
946 } else
947 return -EINVAL;
948 }
949 }
950
951 /*
952 * Create the relocated block information in the table
953 * when the block is relocated before, blob should modify
954 * the original entry to new relocated block and the old
955 * relocated block point to 65535. If not the situation,
956 * create a new entry
957 */
958 if (entry_num != -1) {
959 item[total].from = item[entry_num].to;
960 item[total].to = 65535;
961 total ++;
962 item[entry_num].to = reloc_block;
963 } else {
964 item[total].from = block;
965 item[total].to = reloc_block;
966 total ++;
967 }
968
969 if (bbm->bbm_type == BBM_LEGACY)
970 legacy_bbm->table->total = total;
971 else
972 bbt->entry_num = total;
973
974 return 0;
975}
976
977static int pxa3xx_update_ext_legacy_abbt(struct mtd_info *mtd, int main_bbt,
978 int erase, int *bbt_changed)
979{
980 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
981 struct pxa3xx_legacy_bbm *legacy_bbm;
982 struct pxa3xx_legacy_abbm *abbm;
983 struct erase_info instr;
984 int update_blk, backup_blk;
985 size_t retlen;
986 loff_t offset = 0;
987 int ret = 1, pages;
988 int slot, start_slot, end_slot;
989 void *buf, *rbuf;
990
991 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
992 abbm = &legacy_bbm->abbm;
993
994 if (bbt_changed)
995 *bbt_changed = 0;
996
997 if(!(legacy_bbm->status & ABBT_CHANGED))
998 return 0;
999
1000 rbuf = kzalloc(mtd->writesize, GFP_KERNEL);
1001 if (!rbuf)
1002 return -ENOMEM;
1003
1004 if (main_bbt) {
1005 update_blk = abbm->main_blk;
1006 backup_blk = abbm->mirror_blk;
1007 } else {
1008 update_blk = abbm->mirror_blk;
1009 backup_blk = abbm->main_blk;
1010 }
1011
1012 while (erase) {
1013 memset(&instr, 0, sizeof(struct erase_info));
1014 instr.mtd = mtd;
1015 instr.addr = (uint64_t)update_blk << mtd->erasesize_shift;
1016 instr.len = mtd->erasesize;
1017 instr.callback = pxa3xx_bbm_callback;
1018
1019 should_reloc = 0;
1020 mtd->_erase(mtd, &instr);
1021 should_reloc = 1;
1022 if (erase_success) {
1023 printk(KERN_INFO "Success to erase block %d\n",
1024 update_blk);
1025 break;
1026 }
1027
1028 ret = ext_legacy_bbt_relocate(mtd,
1029 update_blk << mtd->erasesize_shift, ABBT_SCRUB_NONE);
1030 if (ret) {
1031 printk(KERN_INFO "%s: relocate failed, exit\n",
1032 __func__);
1033 goto exit;
1034 }
1035
1036 if (bbt_changed)
1037 *bbt_changed = 1;
1038 }
1039
1040 buf = abbm->abbt;
1041 pages = mtd->erasesize >> mtd->writesize_shift;
1042 if (abbm->order == ORDER_REVERSE) {
1043 start_slot = abbm->cur_slot;
1044 end_slot = erase ? (pages - 1) : abbm->cur_slot;
1045 } else {
1046 start_slot = erase ? 0 : abbm->cur_slot;
1047 end_slot = abbm->cur_slot;
1048 }
1049
1050 while (1) {
1051 /*
1052 * If abbt block is erased, need to write abbt from
1053 * current slot page to end slot page.
1054 */
1055 for (slot = start_slot; slot <= end_slot; slot++) {
1056 offset = slot << mtd->writesize_shift;
1057 offset += update_blk << mtd->erasesize_shift;
1058 ret = mtd->_write(mtd, offset, mtd->writesize, &retlen,
1059 buf);
1060 if (ret)
1061 break;
1062
1063 /* Read back and compare */
1064 memset(rbuf, 0xFF, mtd->writesize);
1065 ret = mtd->_read(mtd, offset, mtd->writesize,
1066 &retlen, rbuf);
1067 if (ret < 0 || memcmp(buf, rbuf, mtd->writesize)) {
1068 ret = -EIO;
1069 break;
1070 }
1071 ret = 0;
1072 }
1073
1074 /* return if write succeed */
1075 if (!ret)
1076 break;
1077
1078 while (1) {
1079 ret = ext_legacy_bbt_relocate(mtd,
1080 update_blk << mtd->erasesize_shift,
1081 ABBT_SCRUB_NONE);
1082 if (ret) {
1083 printk(KERN_INFO "%s: relocate failed, exit\n",
1084 __func__);
1085 goto exit;
1086 }
1087
1088 if (!erase) {
1089 if (abbm->order == ORDER_REVERSE)
1090 ret = legacy_bbm_copy_peb(mtd,
1091 backup_blk, update_blk,
1092 abbm->cur_slot + 1, pages - 1, 0);
1093 else
1094 ret = legacy_bbm_copy_peb(mtd,
1095 backup_blk, update_blk,
1096 0, abbm->cur_slot - 1, 0);
1097 }
1098
1099 if (!ret)
1100 break;
1101
1102 if (ret != -EAGAIN) {
1103 printk(KERN_INFO "%s: fatal error, exit\n",
1104 __func__);
1105 goto exit;
1106 }
1107 }
1108
1109 if (bbt_changed)
1110 *bbt_changed = 1;
1111 }
1112
1113exit:
1114 kfree(rbuf);
1115 return ret;
1116}
1117
1118static void pxa3xx_bbt_remove_dummy(struct pxa3xx_legacy_bbm *legacy_bbm)
1119{
1120 struct reloc_item *item;
1121 int total, i;
1122
1123 item = legacy_bbm->reloc;
1124 total = legacy_bbm->table->total;
1125
1126 for (i = 0; i < total; i++) {
1127 if ((item[i].from == BLK_BAD) && (item[i].to == BLK_BAD)) {
1128 item[i].from = item[total - 1].from;
1129 item[i].to = item[total - 1].to;
1130 item[total - 1].from = BLK_BAD;
1131 item[total - 1].to = BLK_BAD;
1132 total--;
1133 i--;
1134 }
1135 }
1136
1137 legacy_bbm->table->total = total;
1138}
1139
1140int __pxa3xx_update_legacy_bbt(struct mtd_info *mtd, int block, int cur_slot)
1141{
1142 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
1143 struct pxa3xx_legacy_bbm *legacy_bbm;
1144 struct erase_info instr;
1145 size_t retlen;
1146 loff_t offset = 0;
1147 int pages, erase_bbt;
1148 int ret;
1149 void *buf, *rbuf;
1150 int max_retries = 3;
1151
1152 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1153 pages = mtd->erasesize >> mtd->writesize_shift;
1154 erase_bbt = 0;
1155
1156 rbuf = kzalloc(mtd->writesize, GFP_KERNEL);
1157 if (!rbuf)
1158 return -ENOMEM;
1159retry:
1160 if (max_retries-- <= 0)
1161 goto ERR_EXIT2;
1162
1163 /* should write to the next slot */
1164 if (legacy_bbm->order == ORDER_REVERSE) {
1165 cur_slot--;
1166 if (cur_slot < bbm->begin_slot) {
1167 erase_bbt = 1;
1168 cur_slot = pages - 1;
1169 }
1170 } else {
1171 cur_slot++;
1172 if (cur_slot >= pages) {
1173 erase_bbt = 1;
1174 cur_slot = bbm->begin_slot;
1175 }
1176 }
1177
1178 if (erase_bbt) {
1179 buf = kzalloc(mtd->writesize * bbm->begin_slot, GFP_KERNEL);
1180 if (!buf)
1181 return -ENOMEM;
1182
1183 ret = mtd->_read(mtd, (block << mtd->erasesize_shift),
1184 mtd->writesize * bbm->begin_slot,
1185 &retlen, buf);
1186 if (ret < 0)
1187 goto ERR_EXIT;
1188
1189 memset(&instr, 0, sizeof(struct erase_info));
1190 instr.mtd = mtd;
1191 instr.addr = (uint64_t)block << mtd->erasesize_shift;
1192 instr.len = mtd->erasesize;
1193 instr.callback = pxa3xx_bbm_callback;
1194
1195 should_reloc = 0;
1196 mtd->_erase(mtd, &instr);
1197 should_reloc = 1;
1198 if (!erase_success) {
1199 printk(KERN_ERR "Failed to erase block 0!\n");
1200 goto ERR_EXIT;
1201 }
1202 printk(KERN_INFO "Success to erase block 0!\n");
1203
1204 ret = mtd->_write(mtd, (block << mtd->erasesize_shift),
1205 mtd->writesize * bbm->begin_slot,
1206 &retlen, buf);
1207 if (ret)
1208 goto ERR_EXIT;
1209
1210 kfree(buf);
1211
1212 pxa3xx_bbt_remove_dummy(legacy_bbm);
1213 }
1214
1215 buf = legacy_bbm->table;
1216 offset = (block << mtd->erasesize_shift) +
1217 (cur_slot << mtd->writesize_shift);
1218 ret = mtd->_write(mtd, offset, mtd->writesize, &retlen, buf);
1219 if (ret) {
1220 erase_bbt = 1;
1221 goto retry;
1222 }
1223
1224 /* Read back and compare */
1225 memset(rbuf, 0xFF, mtd->writesize);
1226 ret = mtd->_read(mtd, offset, mtd->writesize, &retlen, rbuf);
1227 if (ret < 0 || memcmp(buf, rbuf, mtd->writesize)) {
1228 erase_bbt = 1;
1229 goto retry;
1230 }
1231
1232 legacy_bbm->status &= ~BBT_CHANGED;
1233 kfree(rbuf);
1234 return cur_slot;
1235
1236ERR_EXIT:
1237 kfree(buf);
1238ERR_EXIT2:
1239 kfree(rbuf);
1240 return -EINVAL;
1241}
1242
1243int pxa3xx_update_legacy_bbt(struct mtd_info *mtd, int block, int cur_slot)
1244{
1245 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
1246 struct pxa3xx_legacy_bbm *legacy_bbm;
1247 struct pxa3xx_legacy_abbm *abbm;
1248 struct pxa3xx_abbt *abbt;
1249 struct erase_info instr;
1250 int allow_reloc;
1251 int ret;
1252
1253 legacy_bbm = (struct asr_legacy_bbm *)bbm->data_buf;
1254 abbm = &legacy_bbm->abbm;
1255 abbt = abbm->abbt;
1256
1257 if ((abbt->ver == ABBT_VERSION_1102 ||
1258 abbt->ver == ABBT_VERSION_2001) && abbt->backup_bbt_loc > 0)
1259 allow_reloc = 1;
1260 else
1261 allow_reloc = 0;
1262
1263 ret = __pxa3xx_update_legacy_bbt(mtd, block, cur_slot);
1264 if (allow_reloc && ret < 0 && ret != -ENOMEM) {
1265 /*
1266 * Relocate BBT block and erase it, so that booting from
1267 * another backup is available.
1268 */
1269 while (1) {
1270 ret = ext_legacy_bbt_relocate(mtd,
1271 block << mtd->erasesize_shift, ABBT_SCRUB_NONE);
1272 if (ret) {
1273 printk(KERN_INFO "%s: relocate failed, exit\n",
1274 __func__);
1275 return ret;
1276 }
1277
1278 memset(&instr, 0, sizeof(struct erase_info));
1279 instr.mtd = mtd;
1280 instr.addr = (uint64_t)block << mtd->erasesize_shift;
1281 instr.len = mtd->erasesize;
1282 instr.callback = pxa3xx_bbm_callback;
1283
1284 should_reloc = 0;
1285 mtd->_erase(mtd, &instr);
1286 should_reloc = 1;
1287 if (!erase_success) {
1288 printk(KERN_INFO "erase bbt block %d success\n",
1289 block);
1290 break;
1291 }
1292
1293 printk(KERN_INFO "erase block %d failed\n", block);
1294 }
1295 }
1296
1297 return ret;
1298}
1299
1300int pxa3xx_update_ext_legacy_bbt(struct mtd_info *mtd, loff_t offs)
1301{
1302 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
1303 struct pxa3xx_legacy_bbm *legacy_bbm;
1304 struct pxa3xx_legacy_abbm *abbm;
1305 struct pxa3xx_abbt *abbt;
1306 struct erase_info instr;
1307 struct mtd_ecc_stats stats;
1308 size_t retlen;
1309 loff_t offset = 0;
1310 int pages, erase_main, erase_mirror;
1311 void *buf;
1312 int ret, renew = 0;
1313 int bbt_slot;
1314
1315 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1316 abbm = &legacy_bbm->abbm;
1317 abbt = abbm->abbt;
1318 pages = mtd->erasesize >> mtd->writesize_shift;
1319
1320 if(!(legacy_bbm->status & ABBT_CHANGED))
1321 goto update_bbt;
1322
1323 /*
1324 * abbt may be changed during update mirror blk, so need to
1325 * update main blk agagin for this situation
1326 */
1327 do {
1328 erase_main = erase_mirror = 0;
1329 if (abbm->order == ORDER_REVERSE) {
1330 abbm->cur_slot--;
1331 if (abbm->cur_slot < 0) {
1332 erase_main = erase_mirror = 1;
1333 abbm->cur_slot = pages - 1;
1334 }
1335 } else {
1336 abbm->cur_slot++;
1337 if (abbm->cur_slot >= pages) {
1338 erase_main = erase_mirror = 1;
1339 abbm->cur_slot = 0;
1340 }
1341 }
1342 if (erase_main == 0) {
1343 /* Check if next page is all 0xff, and can be written */
1344 buf = kzalloc(mtd->writesize, GFP_KERNEL);
1345 if (!buf)
1346 return -ENOMEM;
1347 offset = abbm->cur_slot << mtd->writesize_shift;
1348 offset += abbm->main_blk << mtd->erasesize_shift;
1349 stats.failed = mtd->ecc_stats.failed;
1350 ret = mtd->_read(mtd, offset, mtd->writesize, &retlen, buf);
1351 if (ret < 0 || !check_pattern(buf, 0xff, mtd->writesize)) {
1352 erase_main = 1;
1353 printk(KERN_ERR "abbt main block slot %d not writtable, ret=%d\n",
1354 abbm->cur_slot, ret);
1355 }
1356
1357 offset = abbm->cur_slot << mtd->writesize_shift;
1358 offset += abbm->mirror_blk << mtd->erasesize_shift;
1359 ret = mtd->_read(mtd, offset, mtd->writesize, &retlen, buf);
1360 if (ret < 0 || !check_pattern(buf, 0xff, mtd->writesize)) {
1361 erase_mirror = 1;
1362 printk(KERN_ERR "abbt mirror block slot %d not writtable, ret=%d\n",
1363 abbm->cur_slot, ret);
1364 }
1365 mtd->ecc_stats.failed = stats.failed;
1366
1367 kfree(buf);
1368 }
1369
1370 /* Update legacy abbt main and mirror block */
1371 pxa3xx_update_ext_legacy_abbt(mtd, 1, erase_main, NULL);
1372 pxa3xx_update_ext_legacy_abbt(mtd, 0, erase_mirror, &renew);
1373 } while(renew);
1374
1375 legacy_bbm->status &= ~ABBT_CHANGED;
1376
1377update_bbt:
1378 if(!(legacy_bbm->status & BBT_CHANGED))
1379 return 0;
1380
1381 bbt_slot = legacy_bbm->current_slot;
1382 ret = pxa3xx_update_legacy_bbt(mtd, legacy_bbm->bbt_blk, bbt_slot);
1383 if (abbt->ver == ABBT_VERSION_1102 || abbt->ver == ABBT_VERSION_2001) {
1384 int backup_blk = abbt->backup_bbt_loc >> mtd->erasesize_shift;
1385 if (backup_blk != legacy_bbm->bbt_blk)
1386 ret = pxa3xx_update_legacy_bbt(mtd, backup_blk,
1387 bbt_slot);
1388 }
1389 if (ret >= 0) {
1390 legacy_bbm->current_slot = ret;
1391 ret = 0;
1392 } else {
1393 printk(KERN_INFO "Can't write relocation table to device any more.\n");
1394 }
1395
1396 return ret;
1397}
1398
1399static int pxa3xx_scrub_read_disturb(struct mtd_info *mtd, loff_t ofs)
1400{
1401 struct pxa3xx_bbm *bbm = mtd->bbm;
1402 struct pxa3xx_legacy_bbm *legacy_bbm = NULL;
1403 struct pxa3xx_legacy_abbm *abbm;
1404 struct pxa3xx_abbt *abbt;
1405 int block = (int)(ofs >> mtd->erasesize_shift);
1406
1407 /* Should not relocate block 0 since bootrom must use it */
1408 if (!bbm || !block || rd_scrubbing || disable_reloc) {
1409 if (disable_reloc)
1410 rd_disturb_cnt++;
1411
1412 if (!block )
1413 printk(KERN_INFO "warn: block0 bit-flip, not relocate\n");
1414 return 0;
1415 }
1416
1417 rd_scrubbing = 1;
1418 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1419 abbm = &legacy_bbm->abbm;
1420 abbt = abbm->abbt;
1421 if (abbt->ver == ABBT_VERSION_1102 || abbt->ver == ABBT_VERSION_2001) {
1422 int backup_blk = abbt->backup_bbt_loc >> mtd->erasesize_shift;
1423 if (block == backup_blk) {
1424 printk(KERN_INFO "warn: bbt backup block%d bit-flip, not relocate\n",
1425 block);
1426 return 0;
1427 }
1428 }
1429
1430 if (bbm->is_init == BBT_NOINIT) {
1431 if (block == abbm->main_blk)
1432 legacy_bbm->status |= ABBT_MAIN_SCRUB;
1433 else if (block == abbm->mirror_blk)
1434 legacy_bbm->status |= ABBT_MIRROR_SCRUB;
1435 goto out;
1436 } else if (abbm->cur_slot < 0) {
1437 /* If ABBT not supported, skip scrubing flow */
1438 goto out;
1439 }
1440
1441 if (abbt->entry_num >= (abbm->max_entry - 2)) {
1442 printk(KERN_ERR "ABBT table full: %ditems\n", abbt->entry_num);
1443 goto out;
1444 }
1445
1446 /*
1447 * First relocate block A to any valid block B, after this:
1448 * 65522 --> A
1449 * A --> B
1450 */
1451 ext_legacy_bbt_relocate(mtd, ofs, ABBT_SCRUB_ANY);
1452 pxa3xx_update_ext_legacy_bbt(mtd, 0);
1453
1454 /*
1455 * Try to recycle block A, after this:
1456 * 65521 --> A
1457 * A --> B
1458 */
1459 pxa3xx_abbt_recycle_blk(mtd);
1460
1461 /*
1462 * Try to map block A back to itself to decrease abbt entry,
1463 * after this:
1464 * 65522 --> B
1465 * A --> A (redundant entry to be removed)
1466 */
1467 ext_legacy_bbt_relocate(mtd, ofs, ABBT_SCRUB_BACK);
1468 pxa3xx_update_ext_legacy_bbt(mtd, 0);
1469
1470 /*
1471 * Try to recycle block B, after this:
1472 * 65521 --> B
1473 */
1474 pxa3xx_abbt_recycle_blk(mtd);
1475out:
1476 rd_scrubbing = 0;
1477 return 0;
1478}
1479
1480/* Write the relocation table back to device, if there's room. */
1481int pxa3xx_update_bbt(struct mtd_info *mtd, loff_t offs)
1482{
1483 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
1484 struct pxa3xx_legacy_bbm *legacy_bbm;
1485 struct pxa3xx_new_bbm *new_bbm;
1486 size_t retlen;
1487 loff_t offset = 0;
1488 void *buf;
1489 int ret = 1, part = 0, pages, is_continue = 1, backup_size;
1490 struct erase_info instr = {
1491 .callback = NULL,
1492 };
1493
1494 while (is_continue) {
1495 switch (bbm->bbm_type) {
1496 case BBM_LEGACY:
1497 if (!ret) {
1498 printk(KERN_INFO "update legacy bbt"
1499 " at %llx\n", offset);
1500 return 0;
1501 }
1502
1503 pages = mtd->erasesize >> mtd->writesize_shift;
1504 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1505 if (legacy_bbm->current_slot <= bbm->begin_slot
1506 || legacy_bbm->current_slot > pages)
1507 {
1508 backup_size = mtd->writesize*bbm->begin_slot;
1509 buf = kmalloc(backup_size, GFP_KERNEL);
1510 if (!buf) {
1511 printk(KERN_ERR "Fail to allocate backup memory!!\n");
1512 goto ERR_EXIT;
1513 }
1514 ret = mtd->_read(mtd, 0, backup_size, &retlen, buf);
1515 if(ret < 0)
1516 {
1517 printk(KERN_ERR "read backup two page failed!!\n");
1518 goto ERR_EXIT;
1519 }
1520 instr.mtd = mtd;
1521 instr.addr = 0;
1522 instr.len = mtd->erasesize;
1523 instr.callback = pxa3xx_bbm_callback;
1524 printk(KERN_INFO "erasing..");
1525
1526 should_reloc = 0;
1527 mtd->_erase(mtd, &instr);
1528 should_reloc = 1;
1529 if (!erase_success) {
1530 printk(KERN_ERR "erase block 0 failed!!!\n");
1531 goto ERR_EXIT;
1532 }
1533
1534 ret = mtd->_write(mtd, 0, backup_size, &retlen, buf);
1535 kfree(buf);
1536 if(ret)
1537 {
1538 printk(KERN_ERR "restore backup two page failed!!\n");
1539 goto ERR_EXIT;
1540 }
1541 legacy_bbm->current_slot = (mtd->erasesize >> mtd->writesize_shift) - 1;
1542 }else{
1543 /* should write to the next slot */
1544 legacy_bbm->current_slot --;
1545 }
1546
1547 buf = legacy_bbm->table;
1548 offset = legacy_bbm->current_slot
1549 << mtd->writesize_shift;
1550 break;
1551
1552 case BBM_NEW:
1553 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
1554 if (!ret) {
1555 printk(KERN_INFO "update new bbm bbt"
1556 " at %llx\n", offset);
1557 new_bbm->update_indicator &= ~(1 << part);
1558 }
1559 for (; part < MAX_SUPPRTED_PARTNUM; part ++)
1560 if (new_bbm->update_indicator & (1 << part))
1561 break;
1562
1563 if (part >= MAX_SUPPRTED_PARTNUM)
1564 return 0;
1565
1566 offset = (new_bbm->rbbt_offset[part] + 1)
1567 << mtd->writesize_shift;
1568 if (!(unsigned int)(offset & mtd->erasesize_mask))
1569 goto ERR_EXIT;
1570
1571 new_bbm->rbbt_offset[part] ++;
1572 buf = new_bbm->rbbt;
1573 break;
1574
1575 default:
1576 return 0;
1577 }
1578
1579 ret = mtd->_write(mtd, offset, mtd->writesize, &retlen, buf);
1580 }
1581
1582 return 0;
1583
1584ERR_EXIT:
1585 printk(KERN_ERR "Can't write relocation table to device any more.\n");
1586 return -EINVAL;
1587}
1588
1589/* Find the relocated block of the bad one.
1590 * If it's a good block, return 0. Otherwise, return a relocated one.
1591 * idx points to the next relocation entry
1592 * If the relocated block is bad, an new entry will be added into the
1593 * bottom of the relocation table.
1594 */
1595static loff_t pxa3xx_ext_legacy_search_reloc(struct mtd_info *mtd, loff_t ofs)
1596{
1597 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
1598 struct pxa3xx_legacy_bbm *legacy_bbm;
1599 struct pxa3xx_legacy_abbm *abbm;
1600 struct pxa3xx_abbt *abbt;
1601 struct reloc_item *item;
1602 int i, block, max_reloc, total;
1603
1604 if (!bbm || disable_reloc)
1605 return ofs;
1606
1607 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1608 if (legacy_bbm->current_slot < 0)
1609 return ofs;
1610
1611 block = ofs >> mtd->erasesize_shift;
1612 if (block == legacy_bbm->reloc_cache.from) {
1613 ofs -= block << mtd->erasesize_shift;
1614 block = legacy_bbm->reloc_cache.to;
1615 ofs += block << mtd->erasesize_shift;
1616 return ofs;
1617 }
1618
1619 abbm = &legacy_bbm->abbm;
1620 abbt = abbm->abbt;
1621 max_reloc = mtd_div_by_eb(mtd->size, mtd) - legacy_bbm->reserved_blks;
1622
1623 if (block == abbm->main_blk || block == abbm->mirror_blk) {
1624 item = legacy_bbm->reloc;
1625 total = legacy_bbm->table->total;
1626 } else {
1627 item = abbt->reloc;
1628 total = abbt->entry_num;
1629 }
1630
1631 if ((block >= max_reloc &&
1632 (block < mtd_div_by_eb(mtd->size, mtd) - ABBT_BLK_NUM)) ||
1633 total == 0)
1634 return ofs;
1635
1636 legacy_bbm->reloc_cache.from = block;
1637 ofs -= block << mtd->erasesize_shift;
1638 for (i = 0; i < total; i++) {
1639 if (block == item[i].from) {
1640 block = item[i].to;
1641 break;
1642 }
1643 }
1644 ofs += block << mtd->erasesize_shift;
1645 legacy_bbm->reloc_cache.to = block;
1646 return ofs;
1647}
1648
1649static loff_t pxa3xx_search_reloc_tb(struct mtd_info *mtd, loff_t ofs)
1650{
1651 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
1652 struct pxa3xx_legacy_bbm *legacy_bbm;
1653 struct pxa3xx_legacy_abbm *abbm;
1654 struct pxa3xx_new_bbm *new_bbm;
1655 struct reloc_item *item;
1656 int i, block, max_allow_relocated, entry_num, part;
1657
1658 if (!bbm)
1659 return ofs;
1660
1661 block = ofs >> mtd->erasesize_shift;
1662 switch (bbm->bbm_type) {
1663 case BBM_LEGACY:
1664 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1665 abbm = &legacy_bbm->abbm;
1666 if (abbm->cur_slot >= 0)
1667 return pxa3xx_ext_legacy_search_reloc(mtd, ofs);
1668
1669 if (legacy_bbm->current_slot < 0)
1670 return ofs;
1671 /*
1672 * In case abbt blocks are bad, find these two block relocation
1673 * from legacy bbm. This can happen during abbt table scan after
1674 * legacy bbm scan finished.
1675 */
1676 max_allow_relocated = mtd_div_by_eb(mtd->size, mtd);
1677 if (bbm->is_init == BBT_INITED)
1678 max_allow_relocated -= legacy_bbm->max_reloc_entry;
1679
1680 item = legacy_bbm->reloc;
1681 entry_num = legacy_bbm->table->total;
1682 break;
1683
1684 case BBM_NEW:
1685 if (bbm->is_init == BBT_NOINIT)
1686 return ofs;
1687
1688 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
1689 part = find_part(mtd, ofs);
1690 if (part < 0)
1691 return ofs;
1692 item = (struct reloc_item *)&new_bbm->rbbt[part].reloc;
1693 entry_num = new_bbm->rbbt[part].entry_num;
1694 max_allow_relocated =
1695 mtd_div_by_eb(new_bbm->partinfo[part].end_addr, mtd);
1696 break;
1697
1698 default:
1699 return ofs;
1700 }
1701
1702 if (block >= max_allow_relocated || entry_num == 0)
1703 return ofs;
1704
1705 ofs -= block * mtd->erasesize;
1706 for (i = 0; i < entry_num; i ++)
1707 if (block == item[i].from)
1708 /* !!! NOT add break here, repeat is needed */
1709 block = item[i].to;
1710
1711 ofs += block * mtd->erasesize;
1712
1713 return ofs;
1714}
1715
1716static int pxa3xx_init_bbm(struct mtd_info *mtd, int bbm_type)
1717{
1718 struct pxa3xx_bbm *bbm = mtd->bbm;
1719 struct pxa3xx_legacy_bbm *legacy_bbm;
1720 struct pxa3xx_new_bbm *new_bbm;
1721 int size, ret, entrys, max_relcs;
1722
1723 if (bbm_type != BBM_NEW && bbm_type != BBM_LEGACY)
1724 return -EFAULT;
1725
1726 bbm = kzalloc(sizeof(struct pxa3xx_bbm), GFP_KERNEL);
1727 if (!bbm)
1728 return -ENOMEM;
1729
1730 bbm->search = pxa3xx_search_reloc_tb;
1731 bbm->scrub_read_disturb = pxa3xx_scrub_read_disturb;
1732 bbm->uninit = pxa3xx_uninit_reloc_tb;
1733 bbm->check_partition = pxa3xx_check_partition;
1734 mtd->bbm = bbm;
1735 size = (bbm_type == BBM_NEW) ? sizeof(struct pxa3xx_new_bbm) :
1736 sizeof(struct pxa3xx_legacy_bbm);
1737 bbm->is_init = BBT_NOINIT;
1738 bbm->no_sync = 0;
1739 bbm->data_buf = kzalloc(size, GFP_KERNEL);
1740 if (!bbm->data_buf) {
1741 ret = -ENOMEM;
1742 goto ERR_EXIT;
1743 }
1744
1745 if (bbm_type == BBM_NEW) {
1746 bbm->bbm_type = BBM_NEW;
1747 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
1748 new_bbm->main_block = -1;
1749 new_bbm->back_block = -1;
1750 new_bbm->fbbt = kzalloc(mtd->writesize, GFP_KERNEL);
1751 new_bbm->part = kzalloc(mtd->writesize, GFP_KERNEL);
1752 new_bbm->rbbt =
1753 kzalloc(mtd->writesize * MAX_SUPPRTED_PARTNUM, GFP_KERNEL);
1754 new_bbm->rbbt_offset =
1755 kzalloc(sizeof(loff_t) * MAX_SUPPRTED_PARTNUM, GFP_KERNEL);
1756 new_bbm->max_reloc_entry =
1757 kzalloc(sizeof(int) * MAX_SUPPRTED_PARTNUM, GFP_KERNEL);
1758 if (!new_bbm->rbbt
1759 || !new_bbm->rbbt_offset
1760 || !new_bbm->max_reloc_entry
1761 || !new_bbm->fbbt
1762 || !new_bbm->part) {
1763 kfree(bbm->data_buf);
1764 ret = -ENOMEM;
1765 goto ERR_EXIT;
1766 }
1767
1768 new_bbm->partinfo =
1769 (struct pxa3xx_partinfo *)&new_bbm->part[1];
1770 memset(new_bbm->fbbt, 0xff, mtd->writesize);
1771 memset(new_bbm->part, 0xff, mtd->writesize);
1772 }
1773 else {
1774 bbm->bbm_type = BBM_LEGACY;
1775 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1776 entrys = mtd_div_by_eb(mtd->size, mtd);
1777 entrys = ABBT_BLK_NUM +
1778 (entrys * LEGACY_BBM_RELOC_PERCENTAGE + 99) / 100;
1779 max_relcs = (mtd->writesize - sizeof(struct reloc_table))
1780 / sizeof(struct reloc_item);
1781
1782 legacy_bbm->reserved_blks = entrys;
1783 legacy_bbm->max_reloc_entry = (entrys < max_relcs) ?
1784 entrys : max_relcs;
1785
1786 /* max entry for legacy abbm */
1787 max_relcs = (mtd->writesize - sizeof(struct pxa3xx_abbt))
1788 / sizeof(struct reloc_item);
1789 legacy_bbm->abbm.max_entry = max_relcs;
1790
1791 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1792 legacy_bbm->table = kzalloc(mtd->writesize, GFP_KERNEL);
1793 if (!legacy_bbm->table) {
1794 kfree(bbm->data_buf);
1795 ret = -ENOMEM;
1796 goto ERR_EXIT;
1797 }
1798
1799 legacy_bbm->abbm.abbt = kzalloc(mtd->writesize, GFP_KERNEL);
1800 if (!legacy_bbm->abbm.abbt) {
1801 kfree(legacy_bbm->table);
1802 kfree(bbm->data_buf);
1803 ret = -ENOMEM;
1804 goto ERR_EXIT;
1805 }
1806
1807 memset(legacy_bbm->table, 0xff, mtd->writesize);
1808 legacy_bbm->reloc = (struct reloc_item *)&legacy_bbm->table[1];
1809 legacy_bbm->current_slot = -1;
1810 legacy_bbm->table->total = 0;
1811
1812 memset(legacy_bbm->abbm.abbt, 0xff, mtd->writesize);
1813 legacy_bbm->abbm.main_blk =
1814 mtd_div_by_eb(mtd->size, mtd) - 1;
1815 legacy_bbm->abbm.mirror_blk =
1816 legacy_bbm->abbm.main_blk - 1;
1817 legacy_bbm->abbm.cur_slot = -1;
1818 legacy_bbm->abbm.abbt->entry_num = 0;
1819 legacy_bbm->reloc_cache.from = 0xFFFF;
1820 }
1821
1822 return 0;
1823
1824ERR_EXIT:
1825 kfree(bbm);
1826 mtd->bbm = NULL;
1827 return ret;
1828}
1829
1830/*
1831 * BBT layout (Append ABB version and Checksum at tail)
1832 * | magic(2B) |
1833 * | entry number(2B) |
1834 * | entry(4B)... |
1835 * | ABB version(4B) |
1836 * | Owner(2bit) |
1837 * | reserved(14bit) |
1838 * | CRC(2B) |
1839 */
1840static bool pxa3xx_check_bbt(struct pxa3xx_legacy_bbm *legacy_bbm)
1841{
1842 struct reloc_table *table = legacy_bbm->table;
1843 struct reloc_item *item = legacy_bbm->reloc;
1844 unsigned int *pver, *pcsum;
1845 unsigned short csum;
1846
1847 pver = (int*)(item + table->total);
1848 if (*pver == 0xFFFFFFFF)
1849 return true;
1850
1851 csum = bbm_crc16(0, (unsigned char *)legacy_bbm->table,
1852 (sizeof(struct reloc_table) +
1853 table->total * sizeof(struct reloc_item) + 4 + 2));
1854
1855 /* BBT crc locate at the end of all entries */
1856 pcsum = (unsigned int *)(item + table->total) + 1;
1857 return ((unsigned short)(*pcsum >> 16) == csum);
1858}
1859
1860static bool pxa3xx_check_abbt(struct pxa3xx_abbt *abbt)
1861{
1862 unsigned short csum;
1863
1864 if (abbt->ver == ABBT_VERSION || abbt->ver == ABBT_VERSION_1102)
1865 return true;
1866
1867 csum = abbt->crc;
1868 abbt->crc = 0;
1869 mb();
1870 abbt->crc = bbm_crc16(0, (unsigned char *)abbt,
1871 (sizeof(struct pxa3xx_abbt) +
1872 abbt->entry_num * sizeof(struct reloc_item)));
1873
1874 return (csum == abbt->crc);
1875}
1876
1877static void __pxa3xx_fix_bbt_from_abbt(struct pxa3xx_legacy_bbm *legacy_bbm,
1878 struct pxa3xx_abbt *abbt, int from)
1879{
1880 struct reloc_item *item, *item_abbt;
1881 int total, total_abbt;
1882 int bbt_to = -1, abbt_to = -1;
1883 int index, i;
1884
1885 item = legacy_bbm->reloc;
1886 total = legacy_bbm->table->total;
1887 item_abbt = abbt->reloc;
1888 total_abbt = abbt->entry_num;
1889
1890 for (i = 0; i < total; i++) {
1891 if (item[i].from == from) {
1892 bbt_to = item[i].to;
1893 index = i;
1894 break;
1895 }
1896 }
1897
1898 for (i = 0; i < total_abbt; i++) {
1899 if (item_abbt[i].from == from) {
1900 abbt_to = item_abbt[i].to;
1901 break;
1902 }
1903 }
1904
1905 /* Check if any mis-match exist */
1906 if (bbt_to != abbt_to) {
1907 if (bbt_to != -1) {
1908 item[index].from = BLK_BAD;
1909 item[index].to = BLK_BAD;
1910 }
1911 if (abbt_to != -1) {
1912 item[total].from = from;
1913 item[total].to = abbt_to;
1914 } else {
1915 item[total].from = BLK_BAD;
1916 item[total].to = BLK_BAD;
1917 }
1918 total++;
1919 legacy_bbm->status |= BBT_CHANGED;
1920 printk("!!! bbt fixup: from %d --> %d to %d --> %d\n",
1921 from, bbt_to, from, abbt_to);
1922 }
1923
1924 legacy_bbm->table->total = total;
1925 if(legacy_bbm->status & BBT_CHANGED) {
1926 unsigned int *pver, *pcsum;
1927 unsigned short csum;
1928
1929 /*
1930 * update BBT crc:
1931 * BBT layout (Append ABB version and Checksum at tail)
1932 * | magic(2B) |
1933 * | entry number(2B) |
1934 * | entry(4B)... |
1935 * | ABB version(4B) |
1936 * | Owner(2bit) |
1937 * | reserved(14bit) |
1938 * | CRC(2B) |
1939 */
1940 pver = (unsigned int *)(item + total);
1941 *pver = ABBT_VERSION_2001;
1942 pcsum = pver + 1;
1943 *pcsum = BBT_UBOOT; /* owner at lower 2bit */
1944 mb();
1945 csum = bbm_crc16(0, (unsigned char *)legacy_bbm->table,
1946 (sizeof(struct reloc_table) +
1947 total * sizeof(struct reloc_item) + 4 + 2));
1948
1949 *pcsum |= csum << 16;
1950 }
1951}
1952
1953static void pxa3xx_fix_bbt_from_abbt(struct mtd_info *mtd)
1954{
1955 struct pxa3xx_bbm *bbm = mtd->bbm;
1956 struct pxa3xx_legacy_bbm *legacy_bbm;
1957 struct pxa3xx_legacy_abbm *abbm;
1958 int i;
1959
1960 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1961 abbm = &legacy_bbm->abbm;
1962
1963 for (i = 0; i < MAX_OBM_BLOCK; i++)
1964 __pxa3xx_fix_bbt_from_abbt(legacy_bbm, abbm->abbt, i);
1965
1966 __pxa3xx_fix_bbt_from_abbt(legacy_bbm, abbm->abbt, abbm->main_blk);
1967 __pxa3xx_fix_bbt_from_abbt(legacy_bbm, abbm->abbt, abbm->mirror_blk);
1968
1969 pxa3xx_update_ext_legacy_bbt(mtd, 0);
1970}
1971
1972static int ext_legacy_abbm_scan(struct mtd_info *mtd)
1973{
1974 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
1975 struct pxa3xx_legacy_bbm *legacy_bbm =
1976 (struct pxa3xx_legacy_bbm *)bbm->data_buf;
1977 struct pxa3xx_legacy_abbm *abbm = &legacy_bbm->abbm;
1978 struct pxa3xx_abbt *abbt = abbm->abbt;
1979 int start_page, end_page;
1980 int slot, start_slot, end_slot;
1981 int low_valid, high_valid;
1982 int low_refcnt, high_refcnt;
1983 int ret, retlen;
1984 int order = ORDER_REVERSE;
1985 int backup_abbt = 0;
1986
1987backup:
1988 legacy_bbm->status &= ~(ABBT_MAIN_SCRUB | ABBT_MIRROR_SCRUB);
1989 start_page = backup_abbt ? abbm->mirror_blk : abbm->main_blk;
1990 start_page <<= (mtd->erasesize_shift - mtd->writesize_shift);
1991 end_page = start_page + (mtd->erasesize >> mtd->writesize_shift) - 1;
1992
1993 start_slot = 0;
1994 end_slot = (mtd->erasesize >> mtd->writesize_shift) - 1;
1995 slot = start_slot;
1996 do {
1997 ret = mtd->_read(mtd, (start_page + slot) << mtd->writesize_shift,
1998 mtd->writesize, &retlen, (void *)abbt);
1999 if (ret >= 0)
2000 break;
2001 } while (++slot <= end_slot);
2002 if (ret >= 0 && abbt->ident == BBT_TYPE_ASR) {
2003 low_valid = 1;
2004 low_refcnt = abbt->refcnt;
2005 } else {
2006 low_valid = 0;
2007 }
2008
2009 slot = end_slot;
2010 do {
2011 ret = mtd->_read(mtd, (start_page + slot) << mtd->writesize_shift,
2012 mtd->writesize, &retlen, (void *)abbt);
2013 if (ret >= 0)
2014 break;
2015 } while (--slot >= start_slot);
2016
2017 if (ret >= 0 && abbt->ident == BBT_TYPE_ASR) {
2018 high_valid = 1;
2019 high_refcnt = abbt->refcnt;
2020 } else {
2021 high_valid = 0;
2022 }
2023
2024 if (low_valid && !high_valid) {
2025 order = ORDER_POSITIVE;
2026 } else if (!low_valid && high_valid) {
2027 order = ORDER_REVERSE;
2028 } else if (low_valid && high_valid) {
2029 if (low_refcnt < high_refcnt)
2030 order = ORDER_POSITIVE;
2031 else
2032 order = ORDER_REVERSE;
2033 } else {
2034 pr_err("ERR: No valid ABBT\n");
2035 }
2036 abbm->order = order;
2037 abbm->cur_slot = page_search(mtd, start_page, end_page,
2038 order, BBT_TYPE_ASR,
2039 abbt, BBM_FULL_MASK);
2040 abbm->cur_slot -= start_page;
2041 if (abbm->cur_slot >= 0) {
2042 if (!pxa3xx_check_abbt(abbt)) {
2043 if (!backup_abbt) {
2044 printk(KERN_INFO "abbt use backup block\n");
2045 backup_abbt = 1;
2046 goto backup;
2047 } else {
2048 printk(KERN_INFO "abbt crc failed\n");
2049 }
2050 }
2051
2052 if (legacy_bbm->status & ABBT_MAIN_SCRUB)
2053 ext_legacy_bbt_relocate(mtd,
2054 abbm->main_blk << mtd->erasesize_shift, ABBT_SCRUB_ANY);
2055 if (legacy_bbm->status & ABBT_MIRROR_SCRUB)
2056 ext_legacy_bbt_relocate(mtd,
2057 abbm->mirror_blk << mtd->erasesize_shift, ABBT_SCRUB_ANY);
2058 legacy_bbm->status &= ~(ABBT_MAIN_SCRUB |
2059 ABBT_MIRROR_SCRUB);
2060
2061 pxa3xx_update_ext_legacy_bbt(mtd, 0);
2062 printk(KERN_INFO "[abbt] at page:%d, order:%s, max:%d\n",
2063 abbm->cur_slot,
2064 order == ORDER_POSITIVE ? "positive" : "reverse",
2065 abbm->max_entry);
2066 dump_reloc_table(abbt->reloc, abbt->entry_num);
2067
2068 /* recover main ABBT from backup */
2069 bbm->is_init = BBT_INITED;
2070 if (backup_abbt) {
2071 struct erase_info instr;
2072
2073 memset(&instr, 0, sizeof(struct erase_info));
2074 instr.mtd = mtd;
2075 instr.addr = (uint64_t)abbm->main_blk << mtd->erasesize_shift;
2076 instr.len = mtd->erasesize;
2077 ret = mtd_erase(mtd, &instr);
2078 if (!ret) {
2079 ret = legacy_bbm_copy_peb(
2080 mtd, abbm->mirror_blk, abbm->main_blk,
2081 0, (mtd->erasesize >> mtd->writesize_shift) - 1,
2082 DEST_SKIP_ALL_FF_PAGE);
2083 if (!ret)
2084 printk(KERN_INFO "Main ABBT recoverd\n");
2085 }
2086 }
2087 return 0;
2088 }
2089
2090 if (!backup_abbt) {
2091 printk(KERN_INFO "try abbt backup block...\n");
2092 backup_abbt = 1;
2093 goto backup;
2094 }
2095
2096 /* There should be a valid relocation table slot at least. */
2097 printk(KERN_ERR "abbt: NO VALID reloc table can be recognized\n");
2098 return -EINVAL;
2099}
2100
2101static int legacy_bbm_scan(struct mtd_info *mtd, int block)
2102{
2103 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
2104 struct pxa3xx_legacy_bbm *legacy_bbm;
2105 struct reloc_table *table;
2106 int slot, start_slot, end_slot;
2107 int low_valid, high_valid;
2108 int low_entrys, high_entrys;
2109 int ret, retlen;
2110 int order = ORDER_REVERSE;
2111 int start_page = block << (mtd->erasesize_shift - mtd->writesize_shift);
2112
2113 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
2114 table = legacy_bbm->table;
2115
2116 start_slot = bbm->begin_slot;
2117 end_slot = (mtd->erasesize >> mtd->writesize_shift) - 1;
2118
2119 slot = start_slot;
2120 do {
2121 ret = mtd->_read(mtd, (slot + start_page) << mtd->writesize_shift,
2122 mtd->writesize, &retlen, (void *)table);
2123 if (ret >= 0)
2124 break;
2125 } while (++slot <= end_slot);
2126 if (ret >= 0 && table->header == PXA_RELOC_HEADER) {
2127 low_valid = 1;
2128 low_entrys = table->total;
2129 } else {
2130 low_valid = 0;
2131 }
2132
2133 slot = end_slot;
2134 do {
2135 ret = mtd->_read(mtd, (slot + start_page) << mtd->writesize_shift,
2136 mtd->writesize, &retlen, (void *)table);
2137 if (ret >= 0)
2138 break;
2139 } while (--slot >= start_slot);
2140
2141 if (ret >= 0 && *(unsigned short *)table == PXA_RELOC_HEADER) {
2142 high_valid = 1;
2143 high_entrys = table->total;
2144 } else {
2145 high_valid = 0;
2146 }
2147
2148 if (low_valid && !high_valid) {
2149 order = ORDER_POSITIVE;
2150 } else if (!low_valid && high_valid) {
2151 order = ORDER_REVERSE;
2152 } else if (low_valid && high_valid) {
2153 if (low_entrys < high_entrys)
2154 order = ORDER_POSITIVE;
2155 else
2156 order = ORDER_REVERSE;
2157 } else {
2158 pr_err("ERR: No valid BBT in block %d!!!\n", block);
2159 }
2160 legacy_bbm->order = order;
2161 legacy_bbm->current_slot = page_search(mtd,
2162 start_page + bbm->begin_slot,
2163 start_page + (mtd->erasesize >> mtd->writesize_shift) - 1,
2164 order, PXA_RELOC_HEADER, table, BBM_HALF_MASK);
2165
2166 if (legacy_bbm->current_slot >= 0) {
2167 printk(KERN_INFO "Max capacity of BBM is %d blocks!!\n",
2168 legacy_bbm->max_reloc_entry);
2169 legacy_bbm->current_slot -= start_page;
2170 legacy_bbm->bbt_blk = block;
2171 ext_legacy_abbm_scan(mtd);
2172
2173 if (!pxa3xx_check_bbt(legacy_bbm)) {
2174 printk(KERN_INFO "bbt crc fail in blk%d\n", block);
2175 return -EINVAL;
2176 }
2177
2178 /* Restore bbt from abbt if mis-match exist */
2179 pxa3xx_fix_bbt_from_abbt(mtd);
2180
2181 printk(KERN_INFO "[bbt] at block:%d page:%d, begin:%d, order:%s\n",
2182 block, legacy_bbm->current_slot, bbm->begin_slot,
2183 order == ORDER_POSITIVE ? "positive" : "reverse");
2184 dump_reloc_table(legacy_bbm->reloc, table->total);
2185 return 0;
2186 }
2187
2188 return -EINVAL;
2189}
2190
2191#define FOUND_FBBT 0x1
2192#define FOUND_PART 0x2
2193#define BBM_NOCOPY 0x1
2194static int scan_fbbt_part(struct mtd_info *mtd, int block, void *buf, int flag)
2195{
2196 /*
2197 * NTIM header at least occupy by one page,
2198 * so search the FBBT or part from second page,
2199 * and this search should be ended at the fifth page
2200 */
2201 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
2202 struct pxa3xx_new_bbm *new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
2203 struct pxa3xx_part *part;
2204 struct pxa3xx_partinfo *partinfo;
2205 int page, ret, part_num, found = 0, i, max_reloc_entry, rp_num;
2206 int start_page, end_page;
2207 loff_t offset;
2208 size_t retlen;
2209
2210 max_reloc_entry = (mtd->writesize - 40) / sizeof(struct reloc_item);
2211 for (page = 1; page < 5; page ++) {
2212 if (found == (FOUND_PART | FOUND_FBBT))
2213 break;
2214
2215 offset = ((uint64_t)block << mtd->erasesize_shift)
2216 + (page << mtd->writesize_shift);
2217 ret = mtd->_read(mtd, offset, mtd->writesize, &retlen, buf);
2218
2219 /* found FBBT */
2220 if (ret >= 0 && *(unsigned int *)buf == PXA_NEW_BBM_HEADER) {
2221 if (flag == BBM_NOCOPY)
2222 return 1;
2223
2224 found |= FOUND_FBBT;
2225 memcpy(new_bbm->fbbt, buf, retlen);
2226 }
2227
2228 /* found partition table */
2229 if (ret >= 0 && *(unsigned int *)buf == PXA_PART_IDET_1) {
2230 if (*((unsigned int *)buf + 1) != PXA_PART_IDET_2)
2231 continue;
2232
2233 if (flag == BBM_NOCOPY)
2234 return 1;
2235
2236 found |= FOUND_PART;
2237 memcpy(new_bbm->part, buf, retlen);
2238 part = new_bbm->part;
2239 part_num = part->part_num;
2240
2241 for (i = 0; i < part_num; i ++) {
2242 partinfo = &new_bbm->partinfo[i];
2243 start_page =
2244 do_div(partinfo->rbbt_start, mtd->writesize);
2245 end_page = start_page - 1 +
2246 (mtd->erasesize >> mtd->writesize_shift);
2247 new_bbm->rbbt_offset[i] =
2248 page_search(mtd, start_page, end_page,
2249 ORDER_POSITIVE, PXA_NEW_BBM_HEADER,
2250 &new_bbm->rbbt[i], BBM_FULL_MASK);
2251 rp_num = mtd_div_by_eb(partinfo->rp_size, mtd);
2252 new_bbm->max_reloc_entry[i] =
2253 (max_reloc_entry < rp_num) ?
2254 max_reloc_entry : rp_num;
2255 }
2256 }
2257 }
2258
2259 return found == (FOUND_PART | FOUND_FBBT);
2260}
2261
2262static int new_bbm_scan(struct mtd_info *mtd)
2263{
2264 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
2265 struct pxa3xx_new_bbm *new_bbm;
2266 int block, ret, flag;
2267 void *buf;
2268
2269 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
2270 buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
2271 if (!buf)
2272 return -ENOMEM;
2273 flag = 0;
2274 for (block = 0; block < 10; block ++) {
2275 ret = scan_fbbt_part(mtd, block, buf, flag);
2276 if (ret) {
2277 flag = BBM_NOCOPY;
2278 if (new_bbm->main_block == -1)
2279 new_bbm->main_block = block;
2280 else if (new_bbm->back_block == -1) {
2281 new_bbm->back_block = block;
2282 break;
2283 }
2284 }
2285 }
2286 kfree(buf);
2287
2288 if (new_bbm->main_block == -1 && new_bbm->back_block == -1) {
2289 printk(KERN_ERR "New BBM initilization failed!!!!!!\n");
2290 return -EINVAL;
2291 }
2292
2293 printk(KERN_INFO "Found main block at %d, back at %d\n",
2294 new_bbm->main_block, new_bbm->back_block);
2295 new_bbm->update_indicator = 0;
2296 printk(KERN_INFO "Factory marked bad blocks:\n");
2297 dump_fact_bads(new_bbm->fbbt);
2298 dump_part_info(mtd);
2299 return 0;
2300}
2301
2302int pxa3xx_get_bbt_type(struct mtd_info *mtd, int begin_slot)
2303{
2304 size_t retlen;
2305 int ret, bbm_type;
2306 void *buf;
2307 int slot, base_slot, end_slot;
2308 int i;
2309
2310 buf = kzalloc(mtd->writesize, GFP_KERNEL);
2311 if (!buf)
2312 return -ENOMEM;
2313
2314 bbm_type = BBM_NEW;
2315 end_slot = (mtd->erasesize >> mtd->writesize_shift) - 1;
2316 for (i = 0; i < 10; i++) {
2317 base_slot = i << (mtd->erasesize_shift - mtd->writesize_shift);
2318 slot = end_slot;
2319 /* Serach from downward */
2320 do {
2321 ret = mtd->_read(mtd,
2322 (slot + base_slot) << mtd->writesize_shift,
2323 mtd->writesize, &retlen, buf);
2324 if (ret >= 0)
2325 break;
2326 } while (--slot >= begin_slot);
2327
2328 /* Serach from upward */
2329 if (ret >= 0 && *(unsigned short *)buf != PXA_RELOC_HEADER) {
2330 slot = begin_slot;
2331 do {
2332 ret = mtd->_read(mtd,
2333 (slot + base_slot) << mtd->writesize_shift,
2334 mtd->writesize, &retlen, buf);
2335 if (ret >= 0)
2336 break;
2337 } while (++slot <= end_slot);
2338 }
2339
2340 /* This flash chip is using legacy BBM */
2341 if (ret >= 0 && *(unsigned short *)buf == PXA_RELOC_HEADER) {
2342 bbm_type = BBM_LEGACY;
2343 break;
2344 }
2345 }
2346
2347 kfree(buf);
2348 return bbm_type;
2349}
2350
2351int pxa3xx_scan_bbt(struct mtd_info *mtd)
2352{
2353 struct pxa3xx_bbm *bbm;
2354 int ret, bbm_type;
2355 int begin_slot;
2356 int i;
2357
2358 mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
2359 mtd->writesize_shift = ffs(mtd->writesize) - 1;
2360
2361 if (cpu_is_pxa1826() || cpu_is_asr1802s())
2362 begin_slot = (4*1024) / mtd->writesize;
2363 else if (cpu_is_asr1803() || cpu_is_asr1826s())
2364 begin_slot = (8*1024) / mtd->writesize;
2365 else
2366 begin_slot = (16*1024)/ mtd->writesize;
2367
2368 if (!mtd->bbm) {
2369 bbm_type = pxa3xx_get_bbt_type(mtd, begin_slot);
2370 ret = pxa3xx_init_bbm(mtd, bbm_type);
2371 if (ret)
2372 return ret;
2373 bbm = (struct pxa3xx_bbm *)mtd->bbm;
2374 } else {
2375 bbm = (struct pxa3xx_bbm *)mtd->bbm;
2376 bbm_type = bbm->bbm_type;
2377 }
2378
2379 bbm->begin_slot = begin_slot;
2380 if (bbm->is_init != BBT_NOINIT)
2381 return 0;
2382
2383 if (bbm_type == BBM_LEGACY) {
2384 for (i = 0; i < 10; i++) {
2385 /* Scan first 10 block to find valid BBT */
2386 ret = legacy_bbm_scan(mtd, i);
2387 if (!ret)
2388 break;
2389 }
2390
2391 if (ret) {
2392 /* There should be a valid relocation table slot at least. */
2393 printk(KERN_ERR "NO VALID reloc table can be recognized\n");
2394 printk(KERN_ERR "CAUTION: It may cause unpredicated error\n");
2395 printk(KERN_ERR "Please re-initialize the flash.\n");
2396 kfree(bbm->data_buf);
2397 }
2398 } else {
2399 ret = new_bbm_scan(mtd);
2400 }
2401
2402 if (!ret)
2403 bbm->is_init = BBT_INITED;
2404 else {
2405 printk(KERN_ERR "BBM NOT Initialized, "
2406 "Please re-init the flash!!!\n\n");
2407 bbm->is_init = BBT_NOINIT;
2408 }
2409
2410 return ret;
2411}
2412
2413static int checkbad(struct mtd_info *mtd, loff_t ofs)
2414{
2415 struct mtd_oob_ops ops;
2416 uint32_t bad_mark;
2417
2418 ops.ooboffs = 0;
2419 ops.ooblen = 2;
2420 ops.len = 2;
2421 ops.datbuf = NULL;
2422 ops.oobbuf = (uint8_t *)&bad_mark;
2423 ops.mode = MTD_OPS_PLACE_OOB;
2424
2425 mtd->_read_oob(mtd, ofs, &ops);
2426 if ((bad_mark & 0xFF) != 0xFF)
2427 return 1;
2428 else
2429 return 0;
2430}
2431
2432static int boot_part_bad(struct mtd_info *mtd, loff_t ofs)
2433{
2434 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
2435 struct pxa3xx_new_bbm *new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
2436 struct pxa3xx_bbt *fbbt = new_bbm->fbbt;
2437 int block = ofs >> mtd->erasesize_shift, i;
2438 uint32_t *fact_bad = (uint32_t *)&fbbt->fact_bad;
2439
2440 for (i = 0; i < fbbt->entry_num; i ++)
2441 if (fact_bad[i] == block)
2442 return 1;
2443
2444 return 0;
2445}
2446
2447int pxa3xx_block_bad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
2448{
2449 struct pxa3xx_bbm *bbm;
2450 struct pxa3xx_legacy_bbm *legacy_bbm;
2451 struct pxa3xx_new_bbm *new_bbm;
2452 struct reloc_table *table;
2453 int part;
2454
2455 bbm = (struct pxa3xx_bbm *)mtd->bbm;
2456 if (bbm && (bbm->is_init != BBT_NOINIT)) {
2457 if (bbm->is_init == BBT_FORCE_NOINIT)
2458 return 0;
2459
2460 bbm = (struct pxa3xx_bbm *)mtd->bbm;
2461 switch (bbm->bbm_type) {
2462 case BBM_LEGACY:
2463 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
2464 table = legacy_bbm->table;
2465 /*
2466 * If relocation table is not yet full, then any block
2467 * in the flash should be good
2468 */
2469 if (legacy_bbm->current_slot >= bbm->begin_slot
2470 && table->total <= legacy_bbm->max_reloc_entry)
2471 return 0;
2472
2473 return checkbad(mtd, ofs);
2474 case BBM_NEW:
2475 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
2476 part = find_part(mtd, ofs);
2477 if (part >= 0) {
2478 if (new_bbm->rbbt[part].entry_num
2479 < new_bbm->max_reloc_entry[part])
2480 return 0;
2481 else
2482 return 1;
2483 }
2484 default:
2485 break;
2486 }
2487 }
2488
2489 return 0;
2490}
2491
2492int pxa3xx_block_markbad(struct mtd_info *mtd, loff_t ofs)
2493{
2494 struct pxa3xx_bbm *bbm = mtd->bbm;
2495 struct pxa3xx_legacy_bbm *legacy_bbm =
2496 (struct pxa3xx_legacy_bbm *)bbm->data_buf;
2497 struct pxa3xx_legacy_abbm *abbm = &legacy_bbm->abbm;
2498 int ret;
2499
2500 if (!should_reloc)
2501 return 0;
2502
2503 if (bbm) {
2504 if (bbm->bbm_type != BBM_LEGACY && bbm->bbm_type != BBM_NEW) {
2505 printk(KERN_WARNING "There is no way"
2506 " to mark bad at %llx", ofs);
2507 return 0;
2508 }
2509
2510 if (bbm->is_init == BBT_NOINIT) {
2511 printk(KERN_WARNING "You should scan bbm first!!\n");
2512 return 0;
2513 }
2514
2515 if (abbm->cur_slot >= 0) {
2516 ret = ext_legacy_bbt_relocate(mtd, ofs, ABBT_SCRUB_NONE);
2517 if (!ret && !bbm->no_sync)
2518 ret = pxa3xx_update_ext_legacy_bbt(mtd, 0);
2519 } else {
2520 ret = sync_pxa3xx_bbt(mtd, ofs);
2521 if (!ret && !bbm->no_sync)
2522 ret = pxa3xx_update_bbt(mtd, 0);
2523 }
2524 return ret;
2525 }
2526 else {
2527 printk(KERN_ERR "Unable to mark bad block at %llx\n", ofs);
2528 return -EFAULT;
2529 }
2530}
2531
2532static int recover_legacy_bbm(struct mtd_info *mtd, int backup)
2533{
2534 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
2535 struct pxa3xx_legacy_bbm *legacy_bbm;
2536 struct pxa3xx_legacy_abbm *abbm;
2537 struct reloc_table *table;
2538 struct erase_info instr = {
2539 .callback = NULL,
2540 };
2541 int backup_size, ret = 0;
2542 loff_t ofs;
2543 void *buf;
2544 size_t retlen;
2545
2546 backup_size = mtd->writesize * bbm->begin_slot;
2547 bbm->is_init = BBT_FORCE_NOINIT;
2548 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
2549 legacy_bbm->current_slot = mtd->erasesize >> mtd->writesize_shift;
2550 abbm = &legacy_bbm->abbm;
2551 table = legacy_bbm->table;
2552 table->header = PXA_RELOC_HEADER;
2553 table->total = 0;
2554
2555 if (backup) {
2556 buf = kzalloc(backup_size, GFP_KERNEL);
2557 if (!buf) {
2558 printk(KERN_ERR "MEM alloc failed!!\n");
2559 return -ENOMEM;
2560 }
2561 printk(KERN_INFO "Ready to read..");
2562 mtd->_read(mtd, 0, backup_size, &retlen, buf);
2563 }
2564
2565 instr.mtd = mtd;
2566 instr.addr = 0;
2567 instr.len = mtd->erasesize;
2568 instr.callback = pxa3xx_bbm_callback;
2569 printk(KERN_INFO "erasing..");
2570
2571 should_reloc = 0;
2572 mtd->_erase(mtd, &instr);
2573 should_reloc = 1;
2574 if (!erase_success) {
2575 printk(KERN_ERR "erase block 0 failed!!!\n");
2576 return -EFAULT;
2577 }
2578
2579 if (backup) {
2580 printk(KERN_INFO "write back..");
2581 mtd->_write(mtd, 0, backup_size, &retlen, buf);
2582 kfree(buf);
2583 }
2584
2585 printk(KERN_INFO "collect bad info..");
2586 for (ofs = mtd->erasesize; ofs < mtd->size; ofs += mtd->erasesize)
2587 if (checkbad(mtd, ofs)) {
2588 printk(KERN_INFO "\nmark %llx as bad in bbt\n", ofs);
2589 if (abbm->cur_slot >= 0)
2590 ext_legacy_bbt_relocate(mtd, ofs, ABBT_SCRUB_NONE);
2591 else
2592 sync_pxa3xx_bbt(mtd, ofs);
2593 }
2594
2595 if (!bbm->no_sync) {
2596 printk(KERN_INFO "update bbt..");
2597 if (abbm->cur_slot >= 0)
2598 ret = pxa3xx_update_ext_legacy_bbt(mtd, 0);
2599 else
2600 ret = pxa3xx_update_bbt(mtd, 0);
2601 }
2602 printk(KERN_INFO "done\n");
2603
2604 return ret;
2605}
2606
2607static int update_fbbt(struct pxa3xx_bbt *fbbt, int block)
2608{
2609 uint32_t *fact_bad = (uint32_t *)&fbbt->fact_bad;
2610 int i;
2611
2612 for (i = 0; i < fbbt->entry_num; i ++)
2613 if (fact_bad[i] == block)
2614 return 0;
2615
2616 fact_bad[i] = block;
2617 fbbt->entry_num ++;
2618
2619 return fbbt->entry_num;
2620}
2621
2622/*
2623 * recover_new_bbm only try to rebuild the fbbt and use the
2624 * default partition table to build the pt
2625 */
2626static int recover_new_bbm(struct mtd_info *mtd, struct reloc_item * item,
2627 int num, int reserve_last_page)
2628{
2629 struct pxa3xx_bbm *bbm = (struct pxa3xx_bbm *)mtd->bbm;
2630 struct pxa3xx_new_bbm *new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
2631 struct pxa3xx_bbt *fbbt = new_bbm->fbbt;
2632 struct pxa3xx_part *part = new_bbm->part;
2633 struct erase_info instr = {
2634 .callback = NULL,
2635 };
2636 int boot_block, block, total_block, reserved_block, ret;
2637 int rbbt, rbbt_back, max_reloc_entry, len, failed = 0;
2638 loff_t ofs;
2639 size_t retlen;
2640 u_char *backup_buf = NULL;
2641
2642 /*
2643 * This should be the most init state
2644 * should try to find two good blocks without the fbbt's help
2645 * then build up a new fbbt
2646 */
2647 backup_buf = kmalloc(mtd->erasesize, GFP_KERNEL);
2648 if (!backup_buf) {
2649 printk(KERN_ERR "Fail to allocate recovery memory!!\n");
2650 return -ENOMEM;
2651 }
2652 bbm->is_init = BBT_FORCE_NOINIT;
2653 if (new_bbm->main_block == -1) {
2654 memset(new_bbm->rbbt, 0xff, mtd->writesize);
2655 new_bbm->rbbt->ident = PXA_NEW_BBM_HEADER;
2656 new_bbm->rbbt->type = BBT_TYPE_RUNT;
2657 if (item != NULL && num > 0) {
2658 memcpy(&(new_bbm->rbbt->reloc), (void *)item,
2659 sizeof(struct reloc_item) * num);
2660 new_bbm->rbbt->entry_num = num;
2661 }
2662 else
2663 new_bbm->rbbt->entry_num = 0;
2664 max_reloc_entry = (mtd->writesize - sizeof(struct pxa3xx_bbt))
2665 / sizeof(struct reloc_item) + 1;
2666
2667 fbbt->ident = PXA_NEW_BBM_HEADER;
2668 fbbt->type = BBT_TYPE_FACT;
2669 fbbt->entry_num = 0;
2670 instr.mtd = mtd;
2671 instr.len = mtd->erasesize;
2672 instr.callback = pxa3xx_bbm_callback;
2673 printk(KERN_INFO "Rebuild new bbm as init state..\n");
2674 for (boot_block = 0; boot_block < BOOT_PRAT_MAX; boot_block ++) {
2675 if (failed) {
2676 ofs = (uint64_t)(boot_block - 1) << mtd->erasesize_shift;
2677 new_bbm->main_block = -1;
2678 update_fbbt(fbbt, boot_block - 1);
2679 failed = 0;
2680 }
2681 instr.addr = (uint64_t)boot_block << mtd->erasesize_shift;
2682 ret = mtd->_read(mtd, instr.addr, mtd->erasesize,
2683 &retlen, backup_buf);
2684 if (ret < 0) {
2685 printk(KERN_ERR "Cannot backup block %d!!\n", boot_block);
2686 failed = 1;
2687 continue;
2688 }
2689 if (!reserve_last_page)
2690 memset(backup_buf + mtd->erasesize - mtd->writesize, 0xff,
2691 mtd->writesize);
2692
2693 should_reloc = 0;
2694 mtd->_erase(mtd, &instr);
2695 should_reloc = 1;
2696 if (!erase_success) {
2697 printk(KERN_ERR "erase %llx failed!!\n", instr.addr);
2698 failed = 1;
2699 continue;
2700 }
2701 else {
2702 ret = mtd->_write(mtd, instr.addr,
2703 mtd->writesize * bbm->begin_slot,
2704 &retlen, backup_buf);
2705 if (ret) {
2706 printk(KERN_ERR "restore backup two page failed!!\n");
2707 failed = 1;
2708 continue;
2709 }
2710 new_bbm->main_block = boot_block;
2711 }
2712
2713 printk(KERN_INFO "Get main block at %d\n", new_bbm->main_block);
2714 part->identifier = (uint64_t)PXA_PART_IDET_2 << 32 | PXA_PART_IDET_1;
2715
2716 // calculate part range under defaut setting of only one part
2717 // The first BOOT_PRAT_MAX block should be used as boot partition
2718 // and next two block should be reversed as run time bbt
2719 part->part_num = 1;
2720 new_bbm->partinfo->type = PART_LOGI;
2721 total_block = mtd_div_by_eb(mtd->size, mtd);
2722 rbbt = rbbt_back = -1;
2723 instr.mtd = mtd;
2724 instr.callback = pxa3xx_bbm_callback;
2725 instr.len = mtd->erasesize;
2726 for (block = BOOT_PRAT_MAX; block < total_block; block ++) {
2727 instr.addr = (uint64_t)block << mtd->erasesize_shift;
2728 should_reloc = 0;
2729 mtd->_erase(mtd, &instr);
2730 should_reloc = 1;
2731 if (!erase_success) {
2732 printk(KERN_ERR "Erase %llx failed!!\n", instr.addr);
2733 sync_pxa3xx_bbt(mtd, instr.addr);
2734 update_fbbt(fbbt, block);
2735 }
2736 else {
2737 ofs = (uint64_t)block << mtd->erasesize_shift;
2738 if (rbbt == -1) {
2739 ret = mtd->_write(mtd, ofs, mtd->writesize,
2740 &retlen, (void *)new_bbm->rbbt);
2741 if (ret)
2742 continue;
2743 rbbt = block;
2744 }
2745 else if (rbbt_back == -1) {
2746 ret = mtd->_write(mtd, ofs, mtd->writesize,
2747 &retlen, (void *)new_bbm->rbbt);
2748 if (ret)
2749 continue;
2750 rbbt_back = block ++;
2751 break;
2752 }
2753 }
2754 }
2755
2756 printk(KERN_INFO "\nGet RBBT at block %d, its back at %d\n",
2757 rbbt, rbbt_back);
2758 reserved_block = ((total_block - block) / 100)
2759 * NEW_BBM_RELOC_PERCENTAGE;
2760 new_bbm->partinfo->start_addr = (uint64_t)block << mtd->erasesize_shift;
2761 new_bbm->partinfo->end_addr = ((uint64_t)(total_block - reserved_block)
2762 << mtd->erasesize_shift) - 1;
2763 new_bbm->partinfo->rp_start = (uint64_t)(total_block - reserved_block)
2764 << mtd->erasesize_shift;
2765 new_bbm->partinfo->rp_size = (uint64_t)reserved_block << mtd->erasesize_shift;
2766 new_bbm->partinfo->rp_algo = RP_UPWD;
2767 new_bbm->partinfo->rbbt_type = PXA_NEW_BBM_HEADER;
2768 new_bbm->partinfo->rbbt_start = (uint64_t)rbbt
2769 << mtd->erasesize_shift;
2770 new_bbm->partinfo->rbbt_start_back = (uint64_t)rbbt_back
2771 << mtd->erasesize_shift;
2772
2773 new_bbm->rbbt_offset[0] = do_div(new_bbm->partinfo->rbbt_start, mtd->writesize);
2774 new_bbm->max_reloc_entry[0] = (max_reloc_entry < reserved_block) ?
2775 max_reloc_entry : reserved_block;
2776
2777 ofs = (bbm->begin_slot << mtd->writesize_shift)
2778 + ((uint64_t)new_bbm->main_block << mtd->erasesize_shift);
2779
2780 printk(KERN_INFO "\nBegin to write main block..\n");
2781 ret = mtd->_write(mtd, ofs, mtd->writesize, &retlen, (void *)fbbt);
2782 if (ret) {
2783 printk(KERN_ERR "Write fbbt failed at %llx\n", ofs);
2784 failed = 1;
2785 continue;
2786 }
2787
2788 ofs = ((bbm->begin_slot + 1) << mtd->writesize_shift)
2789 + ((uint64_t)new_bbm->main_block << mtd->erasesize_shift);
2790 ret = mtd->_write(mtd, ofs, mtd->writesize, &retlen, (void *)part);
2791 if (ret) {
2792 printk(KERN_ERR "Write part failed at %llx\n", ofs);
2793 failed = 1;
2794 continue;
2795 }
2796
2797 ofs = ((bbm->begin_slot + 2) << mtd->writesize_shift)
2798 + ((uint64_t)new_bbm->main_block << mtd->erasesize_shift);
2799 len = mtd->erasesize - (mtd->writesize * (bbm->begin_slot + 2));
2800 ret = mtd->_write(mtd, ofs, len, &retlen, backup_buf
2801 + (mtd->writesize * (bbm->begin_slot + 2)));
2802 if (ret) {
2803 printk(KERN_ERR "restore obm part failed!!\n");
2804 failed = 1;
2805 }
2806 else
2807 break;
2808 }
2809
2810 if (boot_block >= BOOT_PRAT_MAX) {
2811 new_bbm->main_block = -1;
2812 printk(KERN_ERR "There is no good blocks in first %d"
2813 " blocks!\n You should use another"
2814 " flash now!!\n", BOOT_PRAT_MAX);
2815 return -EFAULT;
2816 }
2817 }
2818
2819 /*
2820 * try to find a good block with fbbt's help
2821 * and back the main block to back block
2822 */
2823 if (new_bbm->back_block == -1) {
2824 ofs = (uint64_t)new_bbm->main_block << mtd->erasesize_shift;
2825 ret = mtd->_read(mtd, ofs, mtd->erasesize, &retlen, backup_buf);
2826 if (ret < 0) {
2827 printk(KERN_ERR "Cannot load main boot block!!\n");
2828 return -EFAULT;
2829 }
2830
2831 instr.mtd = mtd;
2832 instr.callback = pxa3xx_bbm_callback;
2833 instr.len = mtd->erasesize;
2834 instr.addr = 0;
2835 for (block = 0; block < BOOT_PRAT_MAX; block ++,
2836 instr.addr += mtd->erasesize) {
2837 if (block == new_bbm->main_block
2838 || boot_part_bad(mtd, instr.addr))
2839 continue;
2840
2841 ret = mtd->_erase(mtd, &instr);
2842 if (!ret) {
2843 printk(KERN_INFO "Got backup block at block %d\n", block);
2844 printk(KERN_INFO "\nBegin to write backup block..\n");
2845 ret = mtd->_write(mtd, instr.addr, mtd->erasesize,
2846 &retlen, backup_buf);
2847 if (ret) {
2848 printk("Failed to backup to %llx\n", instr.addr);
2849 continue;
2850 }
2851
2852 new_bbm->back_block = block;
2853 break;
2854 }
2855 }
2856
2857 if (new_bbm->back_block == -1)
2858 printk(KERN_WARNING "Unable to recover backup boot block!!\n");
2859 }
2860
2861 if (backup_buf)
2862 kfree(backup_buf);
2863
2864 printk(KERN_INFO "done!!\n");
2865 return 0;
2866}
2867
2868/*
2869 * bbm_type:
2870 * BBM_NONE: recover the bbm according to original setting
2871 * BBM_LEGACY: recover bbm as legacy bbm
2872 * BBM_NEW: recover bbm as new bbm
2873 */
2874int pxa3xx_bbm_recovery(struct mtd_info *mtd, int bbm_type, struct reloc_item *item,
2875 int num, int reserve_last_page)
2876{
2877 struct pxa3xx_bbm *bbm = mtd->bbm;
2878 int ret;
2879
2880 if (bbm && bbm->bbm_type != bbm_type) {
2881 pxa3xx_uninit_reloc_tb(mtd);
2882 bbm = mtd->bbm;
2883 }
2884
2885 if (!bbm) {
2886 ret = pxa3xx_init_bbm(mtd, bbm_type);
2887 if (ret) {
2888 printk(KERN_ERR "Init failed!!!\n");
2889 return -EFAULT;
2890 }
2891 }
2892
2893 if (bbm_type == BBM_NONE)
2894 bbm_type = bbm->bbm_type;
2895
2896 switch (bbm_type) {
2897 case BBM_LEGACY:
2898 printk(KERN_INFO "Ready to recover bbm as legacy!\n");
2899 ret = recover_legacy_bbm(mtd, 1);
2900 break;
2901
2902 case BBM_NEW:
2903 printk(KERN_INFO "Ready to recover bbm as new!\n");
2904 ret = recover_new_bbm(mtd, item, num, reserve_last_page);
2905 break;
2906
2907 case BBM_NONE:
2908 default:
2909 printk(KERN_ERR "Cannot fulfill recovery bbm task!!!\n");
2910 ret = -EFAULT;
2911 }
2912
2913 return ret;
2914}
2915
2916static char *bbm_name = "MRVL_BBM";
2917static int do_check_part(struct mtd_info *mtd, struct mtd_partition *part_orig,
2918 struct mtd_partition *part, int *num)
2919{
2920 struct pxa3xx_bbm *bbm = mtd->bbm;
2921 struct pxa3xx_new_bbm *new_bbm;
2922 struct pxa3xx_legacy_bbm *legacy_bbm;
2923 struct pxa3xx_partinfo *partinfo;
2924 uint64_t boundary_offset, orig_size;
2925 int reloc_boundary, i, j, err, last_add, last_add_orig;
2926
2927 if (bbm->bbm_type == BBM_LEGACY) {
2928 legacy_bbm = (struct pxa3xx_legacy_bbm *)bbm->data_buf;
2929 reloc_boundary = mtd_div_by_eb(mtd->size, mtd)
2930 - legacy_bbm->max_reloc_entry;
2931 boundary_offset = (uint64_t)reloc_boundary << mtd->erasesize_shift;
2932
2933 if (boundary_offset < part[*num - 1].offset) {
2934 printk(KERN_ERR "The last part overlay with the reserved area!!\n");
2935 return -EFAULT;
2936 }
2937
2938 memcpy(part, part_orig, *num * sizeof(struct mtd_partition));
2939 if (part[*num - 1].size == MTDPART_SIZ_FULL ||
2940 (boundary_offset < part[*num - 1].size
2941 + part[*num - 1].offset)) {
2942
2943 part[*num - 1].size = boundary_offset - part[*num - 1].offset;
2944 part[*num].name = bbm_name;
2945 part[*num].offset = boundary_offset;
2946 part[*num].size = MTDPART_SIZ_FULL;
2947 part[*num].mask_flags = MTD_WRITEABLE;
2948 *num = *num + 1;
2949 }
2950 return 0;
2951 }
2952
2953 /*
2954 * The following is for new BBM scheme
2955 * reserved pool should be included in one of defined partition,
2956 * or would cause chech fail
2957 */
2958 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
2959 last_add_orig = last_add = err = 0;
2960 for (i = 0, j = 0; i < new_bbm->part->part_num && j < *num && !err; i ++) {
2961 partinfo = &new_bbm->partinfo[i];
2962 for (; j < *num; j ++) {
2963 if (part_orig[j].size == MTDPART_SIZ_FULL)
2964 orig_size = mtd->size - part_orig[j].offset;
2965 else
2966 orig_size = part_orig[j].size;
2967
2968 if ((orig_size + part_orig[j].offset)
2969 < partinfo->rp_start)
2970 continue;
2971 if (part_orig[j].offset > partinfo->rp_start) {
2972 err = 1;
2973 break;
2974 }
2975 if ((orig_size + part_orig[j].offset)
2976 != (partinfo->rp_start + partinfo->rp_size)) {
2977 err = 1;
2978 break;
2979 }
2980 else {
2981 memcpy(&part[last_add], &part_orig[last_add_orig],
2982 (j - last_add + 1) * sizeof(struct mtd_partition));
2983 last_add += (j - last_add_orig) + 1;
2984 last_add_orig = j;
2985 part[last_add - 1].size = partinfo->rp_start
2986 - part[last_add -1].offset;
2987 part[last_add].name = bbm_name;
2988 part[last_add].offset = partinfo->rp_start;
2989 part[last_add].size = partinfo->rp_size;
2990 part[last_add].mask_flags = MTD_WRITEABLE;
2991 last_add += 1;
2992 }
2993 }
2994 }
2995
2996 if (!err)
2997 *num += (last_add - last_add_orig - 1);
2998
2999 return err;
3000}
3001
3002static struct mtd_partition *pxa3xx_check_partition(struct mtd_info *mtd,
3003 struct mtd_partition *part, int *num)
3004{
3005 struct pxa3xx_bbm *bbm = mtd->bbm;
3006 struct pxa3xx_new_bbm *new_bbm;
3007 struct mtd_partition *new_part;
3008 int part_num, alloc_size;
3009
3010 if (bbm->bbm_type == BBM_LEGACY)
3011 part_num = 1;
3012 else {
3013 new_bbm = (struct pxa3xx_new_bbm *)bbm->data_buf;
3014 part_num = new_bbm->part->part_num;
3015 }
3016
3017 alloc_size = (*num + part_num) * sizeof(struct mtd_partition);
3018 new_part = kzalloc(alloc_size, GFP_KERNEL);
3019 if (!new_part) {
3020 printk(KERN_ERR "OUT of memory!!\n");
3021 return NULL;
3022 }
3023
3024 if (!do_check_part(mtd, part, new_part, num))
3025 return new_part;
3026 else
3027 return NULL;
3028}