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.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index dcb6dac1dc54..667f5f451c2b 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -359,19 +359,18 @@ static int in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root)
359 * @ubi: UBI device description object 359 * @ubi: UBI device description object
360 * @e: the physical eraseblock to add 360 * @e: the physical eraseblock to add
361 * @pe: protection entry object to use 361 * @pe: protection entry object to use
362 * @abs_ec: absolute erase counter value when this physical eraseblock has 362 * @ec: for how many erase operations this PEB should be protected
363 * to be removed from the protection trees.
364 * 363 *
365 * @wl->lock has to be locked. 364 * @wl->lock has to be locked.
366 */ 365 */
367static void prot_tree_add(struct ubi_device *ubi, struct ubi_wl_entry *e, 366static void prot_tree_add(struct ubi_device *ubi, struct ubi_wl_entry *e,
368 struct ubi_wl_prot_entry *pe, int abs_ec) 367 struct ubi_wl_prot_entry *pe, int ec)
369{ 368{
370 struct rb_node **p, *parent = NULL; 369 struct rb_node **p, *parent = NULL;
371 struct ubi_wl_prot_entry *pe1; 370 struct ubi_wl_prot_entry *pe1;
372 371
373 pe->e = e; 372 pe->e = e;
374 pe->abs_ec = ubi->abs_ec + abs_ec; 373 pe->abs_ec = ubi->abs_ec + ec;
375 374
376 p = &ubi->prot.pnum.rb_node; 375 p = &ubi->prot.pnum.rb_node;
377 while (*p) { 376 while (*p) {
@@ -739,7 +738,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
739static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, 738static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
740 int cancel) 739 int cancel)
741{ 740{
742 int err, put = 0, scrubbing = 0, protect = 0; 741 int err, put = 0, scrubbing = 0;
743 struct ubi_wl_prot_entry *uninitialized_var(pe); 742 struct ubi_wl_prot_entry *uninitialized_var(pe);
744 struct ubi_wl_entry *e1, *e2; 743 struct ubi_wl_entry *e1, *e2;
745 struct ubi_vid_hdr *vid_hdr; 744 struct ubi_vid_hdr *vid_hdr;
@@ -864,17 +863,28 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
864 goto out_error; 863 goto out_error;
865 } 864 }
866 865
867 protect = 1; 866 ubi_free_vid_hdr(ubi, vid_hdr);
867 spin_lock(&ubi->wl_lock);
868 prot_tree_add(ubi, e1, pe, U_PROTECTION);
869 ubi_assert(!ubi->move_to_put);
870 ubi->move_from = ubi->move_to = NULL;
871 ubi->wl_scheduled = 0;
872 spin_unlock(&ubi->wl_lock);
873
874 err = schedule_erase(ubi, e2, 0);
875 if (err)
876 goto out_error;
877 mutex_unlock(&ubi->move_mutex);
878 return 0;
868 } 879 }
869 880
881 /* The PEB has been successfully moved */
870 ubi_free_vid_hdr(ubi, vid_hdr); 882 ubi_free_vid_hdr(ubi, vid_hdr);
871 if (scrubbing && !protect) 883 if (scrubbing)
872 ubi_msg("scrubbed PEB %d, data moved to PEB %d", 884 ubi_msg("scrubbed PEB %d, data moved to PEB %d",
873 e1->pnum, e2->pnum); 885 e1->pnum, e2->pnum);
874 886
875 spin_lock(&ubi->wl_lock); 887 spin_lock(&ubi->wl_lock);
876 if (protect)
877 prot_tree_add(ubi, e1, pe, protect);
878 if (!ubi->move_to_put) 888 if (!ubi->move_to_put)
879 wl_tree_add(e2, &ubi->used); 889 wl_tree_add(e2, &ubi->used);
880 else 890 else
@@ -883,6 +893,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
883 ubi->move_to_put = ubi->wl_scheduled = 0; 893 ubi->move_to_put = ubi->wl_scheduled = 0;
884 spin_unlock(&ubi->wl_lock); 894 spin_unlock(&ubi->wl_lock);
885 895
896 err = schedule_erase(ubi, e1, 0);
897 if (err)
898 goto out_error;
899
886 if (put) { 900 if (put) {
887 /* 901 /*
888 * Well, the target PEB was put meanwhile, schedule it for 902 * Well, the target PEB was put meanwhile, schedule it for
@@ -894,13 +908,6 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
894 goto out_error; 908 goto out_error;
895 } 909 }
896 910
897 if (!protect) {
898 err = schedule_erase(ubi, e1, 0);
899 if (err)
900 goto out_error;
901 }
902
903
904 dbg_wl("done"); 911 dbg_wl("done");
905 mutex_unlock(&ubi->move_mutex); 912 mutex_unlock(&ubi->move_mutex);
906 return 0; 913 return 0;