aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/wl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/wl.c')
-rw-r--r--drivers/mtd/ubi/wl.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index b6be644e7b85..032fc57f1090 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -978,9 +978,10 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
978 int cancel) 978 int cancel)
979{ 979{
980 struct ubi_wl_entry *e = wl_wrk->e; 980 struct ubi_wl_entry *e = wl_wrk->e;
981 int pnum = e->pnum, err, need; 981 int pnum = e->pnum;
982 int vol_id = wl_wrk->vol_id; 982 int vol_id = wl_wrk->vol_id;
983 int lnum = wl_wrk->lnum; 983 int lnum = wl_wrk->lnum;
984 int err, available_consumed = 0;
984 985
985 if (cancel) { 986 if (cancel) {
986 dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); 987 dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
@@ -1045,20 +1046,14 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
1045 } 1046 }
1046 1047
1047 spin_lock(&ubi->volumes_lock); 1048 spin_lock(&ubi->volumes_lock);
1048 need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
1049 if (need > 0) {
1050 need = ubi->avail_pebs >= need ? need : ubi->avail_pebs;
1051 ubi->avail_pebs -= need;
1052 ubi->rsvd_pebs += need;
1053 ubi->beb_rsvd_pebs += need;
1054 if (need > 0)
1055 ubi_msg("reserve more %d PEBs", need);
1056 }
1057
1058 if (ubi->beb_rsvd_pebs == 0) { 1049 if (ubi->beb_rsvd_pebs == 0) {
1059 spin_unlock(&ubi->volumes_lock); 1050 if (ubi->avail_pebs == 0) {
1060 ubi_err("no reserved physical eraseblocks"); 1051 spin_unlock(&ubi->volumes_lock);
1061 goto out_ro; 1052 ubi_err("no reserved/available physical eraseblocks");
1053 goto out_ro;
1054 }
1055 ubi->avail_pebs -= 1;
1056 available_consumed = 1;
1062 } 1057 }
1063 spin_unlock(&ubi->volumes_lock); 1058 spin_unlock(&ubi->volumes_lock);
1064 1059
@@ -1068,19 +1063,36 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
1068 goto out_ro; 1063 goto out_ro;
1069 1064
1070 spin_lock(&ubi->volumes_lock); 1065 spin_lock(&ubi->volumes_lock);
1071 ubi->beb_rsvd_pebs -= 1; 1066 if (ubi->beb_rsvd_pebs > 0) {
1067 if (available_consumed) {
1068 /*
1069 * The amount of reserved PEBs increased since we last
1070 * checked.
1071 */
1072 ubi->avail_pebs += 1;
1073 available_consumed = 0;
1074 }
1075 ubi->beb_rsvd_pebs -= 1;
1076 }
1072 ubi->bad_peb_count += 1; 1077 ubi->bad_peb_count += 1;
1073 ubi->good_peb_count -= 1; 1078 ubi->good_peb_count -= 1;
1074 ubi_calculate_reserved(ubi); 1079 ubi_calculate_reserved(ubi);
1075 if (ubi->beb_rsvd_pebs) 1080 if (available_consumed)
1081 ubi_warn("no PEBs in the reserved pool, used an available PEB");
1082 else if (ubi->beb_rsvd_pebs)
1076 ubi_msg("%d PEBs left in the reserve", ubi->beb_rsvd_pebs); 1083 ubi_msg("%d PEBs left in the reserve", ubi->beb_rsvd_pebs);
1077 else 1084 else
1078 ubi_warn("last PEB from the reserved pool was used"); 1085 ubi_warn("last PEB from the reserve was used");
1079 spin_unlock(&ubi->volumes_lock); 1086 spin_unlock(&ubi->volumes_lock);
1080 1087
1081 return err; 1088 return err;
1082 1089
1083out_ro: 1090out_ro:
1091 if (available_consumed) {
1092 spin_lock(&ubi->volumes_lock);
1093 ubi->avail_pebs += 1;
1094 spin_unlock(&ubi->volumes_lock);
1095 }
1084 ubi_ro_mode(ubi); 1096 ubi_ro_mode(ubi);
1085 return err; 1097 return err;
1086} 1098}
@@ -1189,7 +1201,7 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum)
1189{ 1201{
1190 struct ubi_wl_entry *e; 1202 struct ubi_wl_entry *e;
1191 1203
1192 dbg_msg("schedule PEB %d for scrubbing", pnum); 1204 ubi_msg("schedule PEB %d for scrubbing", pnum);
1193 1205
1194retry: 1206retry:
1195 spin_lock(&ubi->wl_lock); 1207 spin_lock(&ubi->wl_lock);