aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/eba.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r--drivers/mtd/ubi/eba.c70
1 files changed, 24 insertions, 46 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 89193104c6c8..81bb6a33b555 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -495,16 +495,18 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
495 int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0; 495 int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
496 struct ubi_volume *vol = ubi->volumes[idx]; 496 struct ubi_volume *vol = ubi->volumes[idx];
497 struct ubi_vid_hdr *vid_hdr; 497 struct ubi_vid_hdr *vid_hdr;
498 unsigned char *new_buf;
499 498
500 vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); 499 vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
501 if (!vid_hdr) { 500 if (!vid_hdr) {
502 return -ENOMEM; 501 return -ENOMEM;
503 } 502 }
504 503
504 mutex_lock(&ubi->buf_mutex);
505
505retry: 506retry:
506 new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN); 507 new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
507 if (new_pnum < 0) { 508 if (new_pnum < 0) {
509 mutex_unlock(&ubi->buf_mutex);
508 ubi_free_vid_hdr(ubi, vid_hdr); 510 ubi_free_vid_hdr(ubi, vid_hdr);
509 return new_pnum; 511 return new_pnum;
510 } 512 }
@@ -524,31 +526,22 @@ retry:
524 goto write_error; 526 goto write_error;
525 527
526 data_size = offset + len; 528 data_size = offset + len;
527 new_buf = vmalloc(data_size); 529 memset(ubi->peb_buf1 + offset, 0xFF, len);
528 if (!new_buf) {
529 err = -ENOMEM;
530 goto out_put;
531 }
532 memset(new_buf + offset, 0xFF, len);
533 530
534 /* Read everything before the area where the write failure happened */ 531 /* Read everything before the area where the write failure happened */
535 if (offset > 0) { 532 if (offset > 0) {
536 err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset); 533 err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
537 if (err && err != UBI_IO_BITFLIPS) { 534 if (err && err != UBI_IO_BITFLIPS)
538 vfree(new_buf);
539 goto out_put; 535 goto out_put;
540 }
541 } 536 }
542 537
543 memcpy(new_buf + offset, buf, len); 538 memcpy(ubi->peb_buf1 + offset, buf, len);
544 539
545 err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size); 540 err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
546 if (err) { 541 if (err)
547 vfree(new_buf);
548 goto write_error; 542 goto write_error;
549 }
550 543
551 vfree(new_buf); 544 mutex_unlock(&ubi->buf_mutex);
552 ubi_free_vid_hdr(ubi, vid_hdr); 545 ubi_free_vid_hdr(ubi, vid_hdr);
553 546
554 vol->eba_tbl[lnum] = new_pnum; 547 vol->eba_tbl[lnum] = new_pnum;
@@ -558,6 +551,7 @@ retry:
558 return 0; 551 return 0;
559 552
560out_put: 553out_put:
554 mutex_unlock(&ubi->buf_mutex);
561 ubi_wl_put_peb(ubi, new_pnum, 1); 555 ubi_wl_put_peb(ubi, new_pnum, 1);
562 ubi_free_vid_hdr(ubi, vid_hdr); 556 ubi_free_vid_hdr(ubi, vid_hdr);
563 return err; 557 return err;
@@ -570,6 +564,7 @@ write_error:
570 ubi_warn("failed to write to PEB %d", new_pnum); 564 ubi_warn("failed to write to PEB %d", new_pnum);
571 ubi_wl_put_peb(ubi, new_pnum, 1); 565 ubi_wl_put_peb(ubi, new_pnum, 1);
572 if (++tries > UBI_IO_RETRIES) { 566 if (++tries > UBI_IO_RETRIES) {
567 mutex_unlock(&ubi->buf_mutex);
573 ubi_free_vid_hdr(ubi, vid_hdr); 568 ubi_free_vid_hdr(ubi, vid_hdr);
574 return err; 569 return err;
575 } 570 }
@@ -965,7 +960,6 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
965 int err, vol_id, lnum, data_size, aldata_size, pnum, idx; 960 int err, vol_id, lnum, data_size, aldata_size, pnum, idx;
966 struct ubi_volume *vol; 961 struct ubi_volume *vol;
967 uint32_t crc; 962 uint32_t crc;
968 void *buf, *buf1 = NULL;
969 963
970 vol_id = be32_to_cpu(vid_hdr->vol_id); 964 vol_id = be32_to_cpu(vid_hdr->vol_id);
971 lnum = be32_to_cpu(vid_hdr->lnum); 965 lnum = be32_to_cpu(vid_hdr->lnum);
@@ -979,19 +973,15 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
979 data_size = aldata_size = 973 data_size = aldata_size =
980 ubi->leb_size - be32_to_cpu(vid_hdr->data_pad); 974 ubi->leb_size - be32_to_cpu(vid_hdr->data_pad);
981 975
982 buf = vmalloc(aldata_size);
983 if (!buf)
984 return -ENOMEM;
985
986 /* 976 /*
987 * We do not want anybody to write to this logical eraseblock while we 977 * We do not want anybody to write to this logical eraseblock while we
988 * are moving it, so we lock it. 978 * are moving it, so we lock it.
989 */ 979 */
990 err = leb_write_lock(ubi, vol_id, lnum); 980 err = leb_write_lock(ubi, vol_id, lnum);
991 if (err) { 981 if (err)
992 vfree(buf);
993 return err; 982 return err;
994 } 983
984 mutex_lock(&ubi->buf_mutex);
995 985
996 /* 986 /*
997 * But the logical eraseblock might have been put by this time. 987 * But the logical eraseblock might have been put by this time.
@@ -1023,7 +1013,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1023 /* OK, now the LEB is locked and we can safely start moving it */ 1013 /* OK, now the LEB is locked and we can safely start moving it */
1024 1014
1025 dbg_eba("read %d bytes of data", aldata_size); 1015 dbg_eba("read %d bytes of data", aldata_size);
1026 err = ubi_io_read_data(ubi, buf, from, 0, aldata_size); 1016 err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size);
1027 if (err && err != UBI_IO_BITFLIPS) { 1017 if (err && err != UBI_IO_BITFLIPS) {
1028 ubi_warn("error %d while reading data from PEB %d", 1018 ubi_warn("error %d while reading data from PEB %d",
1029 err, from); 1019 err, from);
@@ -1042,10 +1032,10 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1042 */ 1032 */
1043 if (vid_hdr->vol_type == UBI_VID_DYNAMIC) 1033 if (vid_hdr->vol_type == UBI_VID_DYNAMIC)
1044 aldata_size = data_size = 1034 aldata_size = data_size =
1045 ubi_calc_data_len(ubi, buf, data_size); 1035 ubi_calc_data_len(ubi, ubi->peb_buf1, data_size);
1046 1036
1047 cond_resched(); 1037 cond_resched();
1048 crc = crc32(UBI_CRC32_INIT, buf, data_size); 1038 crc = crc32(UBI_CRC32_INIT, ubi->peb_buf1, data_size);
1049 cond_resched(); 1039 cond_resched();
1050 1040
1051 /* 1041 /*
@@ -1076,23 +1066,18 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1076 } 1066 }
1077 1067
1078 if (data_size > 0) { 1068 if (data_size > 0) {
1079 err = ubi_io_write_data(ubi, buf, to, 0, aldata_size); 1069 err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
1080 if (err) 1070 if (err)
1081 goto out_unlock; 1071 goto out_unlock;
1082 1072
1073 cond_resched();
1074
1083 /* 1075 /*
1084 * We've written the data and are going to read it back to make 1076 * We've written the data and are going to read it back to make
1085 * sure it was written correctly. 1077 * sure it was written correctly.
1086 */ 1078 */
1087 buf1 = vmalloc(aldata_size);
1088 if (!buf1) {
1089 err = -ENOMEM;
1090 goto out_unlock;
1091 }
1092 1079
1093 cond_resched(); 1080 err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
1094
1095 err = ubi_io_read_data(ubi, buf1, to, 0, aldata_size);
1096 if (err) { 1081 if (err) {
1097 if (err != UBI_IO_BITFLIPS) 1082 if (err != UBI_IO_BITFLIPS)
1098 ubi_warn("cannot read data back from PEB %d", 1083 ubi_warn("cannot read data back from PEB %d",
@@ -1102,7 +1087,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1102 1087
1103 cond_resched(); 1088 cond_resched();
1104 1089
1105 if (memcmp(buf, buf1, aldata_size)) { 1090 if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
1106 ubi_warn("read data back from PEB %d - it is different", 1091 ubi_warn("read data back from PEB %d - it is different",
1107 to); 1092 to);
1108 goto out_unlock; 1093 goto out_unlock;
@@ -1112,16 +1097,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1112 ubi_assert(vol->eba_tbl[lnum] == from); 1097 ubi_assert(vol->eba_tbl[lnum] == from);
1113 vol->eba_tbl[lnum] = to; 1098 vol->eba_tbl[lnum] = to;
1114 1099
1115 leb_write_unlock(ubi, vol_id, lnum);
1116 vfree(buf);
1117 vfree(buf1);
1118
1119 return 0;
1120
1121out_unlock: 1100out_unlock:
1101 mutex_unlock(&ubi->buf_mutex);
1122 leb_write_unlock(ubi, vol_id, lnum); 1102 leb_write_unlock(ubi, vol_id, lnum);
1123 vfree(buf);
1124 vfree(buf1);
1125 return err; 1103 return err;
1126} 1104}
1127 1105