aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/ubi/cdev.c2
-rw-r--r--drivers/mtd/ubi/kapi.c29
-rw-r--r--drivers/mtd/ubi/ubi.h2
-rw-r--r--drivers/mtd/ubi/upd.c4
-rw-r--r--drivers/mtd/ubi/vmt.c2
-rw-r--r--drivers/mtd/ubi/wl.c61
-rw-r--r--include/linux/mtd/ubi.h1
7 files changed, 70 insertions, 31 deletions
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 2364c00f66d0..acec85deb6af 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -514,7 +514,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
514 if (err) 514 if (err)
515 break; 515 break;
516 516
517 err = ubi_wl_flush(ubi); 517 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
518 break; 518 break;
519 } 519 }
520 520
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index d76fe47477e5..3aac1acceeb4 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -551,7 +551,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
551 if (err) 551 if (err)
552 return err; 552 return err;
553 553
554 return ubi_wl_flush(ubi); 554 return ubi_wl_flush(ubi, vol->vol_id, lnum);
555} 555}
556EXPORT_SYMBOL_GPL(ubi_leb_erase); 556EXPORT_SYMBOL_GPL(ubi_leb_erase);
557 557
@@ -704,6 +704,33 @@ int ubi_sync(int ubi_num)
704} 704}
705EXPORT_SYMBOL_GPL(ubi_sync); 705EXPORT_SYMBOL_GPL(ubi_sync);
706 706
707/**
708 * ubi_flush - flush UBI work queue.
709 * @ubi_num: UBI device to flush work queue
710 * @vol_id: volume id to flush for
711 * @lnum: logical eraseblock number to flush for
712 *
713 * This function executes all pending works for a particular volume id / logical
714 * eraseblock number pair. If either value is set to %UBI_ALL, then it acts as
715 * a wildcard for all of the corresponding volume numbers or logical
716 * eraseblock numbers. It returns zero in case of success and a negative error
717 * code in case of failure.
718 */
719int ubi_flush(int ubi_num, int vol_id, int lnum)
720{
721 struct ubi_device *ubi;
722 int err = 0;
723
724 ubi = ubi_get_device(ubi_num);
725 if (!ubi)
726 return -ENODEV;
727
728 err = ubi_wl_flush(ubi, vol_id, lnum);
729 ubi_put_device(ubi);
730 return err;
731}
732EXPORT_SYMBOL_GPL(ubi_flush);
733
707BLOCKING_NOTIFIER_HEAD(ubi_notifiers); 734BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
708 735
709/** 736/**
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 38cfb0f2adf2..a1a81c9ea8ce 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -669,7 +669,7 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
669int ubi_wl_get_peb(struct ubi_device *ubi); 669int ubi_wl_get_peb(struct ubi_device *ubi);
670int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, 670int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
671 int pnum, int torture); 671 int pnum, int torture);
672int ubi_wl_flush(struct ubi_device *ubi); 672int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum);
673int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); 673int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
674int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai); 674int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
675void ubi_wl_close(struct ubi_device *ubi); 675void ubi_wl_close(struct ubi_device *ubi);
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 11a28f9ce0db..9f2ebd8750e7 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -147,7 +147,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
147 } 147 }
148 148
149 if (bytes == 0) { 149 if (bytes == 0) {
150 err = ubi_wl_flush(ubi); 150 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
151 if (err) 151 if (err)
152 return err; 152 return err;
153 153
@@ -361,7 +361,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
361 361
362 ubi_assert(vol->upd_received <= vol->upd_bytes); 362 ubi_assert(vol->upd_received <= vol->upd_bytes);
363 if (vol->upd_received == vol->upd_bytes) { 363 if (vol->upd_received == vol->upd_bytes) {
364 err = ubi_wl_flush(ubi); 364 err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
365 if (err) 365 if (err)
366 return err; 366 return err;
367 /* The update is finished, clear the update marker */ 367 /* The update is finished, clear the update marker */
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index e4b897ab4543..0669cff8ac3c 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -280,7 +280,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
280 * Finish all pending erases because there may be some LEBs belonging 280 * Finish all pending erases because there may be some LEBs belonging
281 * to the same volume ID. 281 * to the same volume ID.
282 */ 282 */
283 err = ubi_wl_flush(ubi); 283 err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
284 if (err) 284 if (err)
285 goto out_acc; 285 goto out_acc;
286 286
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 70ebfa7bc384..9df100a4ec38 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1241,44 +1241,55 @@ retry:
1241/** 1241/**
1242 * ubi_wl_flush - flush all pending works. 1242 * ubi_wl_flush - flush all pending works.
1243 * @ubi: UBI device description object 1243 * @ubi: UBI device description object
1244 * @vol_id: the volume id to flush for
1245 * @lnum: the logical eraseblock number to flush for
1244 * 1246 *
1245 * This function returns zero in case of success and a negative error code in 1247 * This function executes all pending works for a particular volume id /
1246 * case of failure. 1248 * logical eraseblock number pair. If either value is set to %UBI_ALL, then it
1249 * acts as a wildcard for all of the corresponding volume numbers or logical
1250 * eraseblock numbers. It returns zero in case of success and a negative error
1251 * code in case of failure.
1247 */ 1252 */
1248int ubi_wl_flush(struct ubi_device *ubi) 1253int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum)
1249{ 1254{
1250 int err; 1255 int err = 0;
1256 int found = 1;
1251 1257
1252 /* 1258 /*
1253 * Erase while the pending works queue is not empty, but not more than 1259 * Erase while the pending works queue is not empty, but not more than
1254 * the number of currently pending works. 1260 * the number of currently pending works.
1255 */ 1261 */
1256 dbg_wl("flush (%d pending works)", ubi->works_count); 1262 dbg_wl("flush pending work for LEB %d:%d (%d pending works)",
1257 while (ubi->works_count) { 1263 vol_id, lnum, ubi->works_count);
1258 err = do_work(ubi);
1259 if (err)
1260 return err;
1261 }
1262 1264
1263 /*
1264 * Make sure all the works which have been done in parallel are
1265 * finished.
1266 */
1267 down_write(&ubi->work_sem); 1265 down_write(&ubi->work_sem);
1268 up_write(&ubi->work_sem); 1266 while (found) {
1267 struct ubi_work *wrk;
1268 found = 0;
1269 1269
1270 /* 1270 spin_lock(&ubi->wl_lock);
1271 * And in case last was the WL worker and it canceled the LEB 1271 list_for_each_entry(wrk, &ubi->works, list) {
1272 * movement, flush again. 1272 if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
1273 */ 1273 (lnum == UBI_ALL || wrk->lnum == lnum)) {
1274 while (ubi->works_count) { 1274 list_del(&wrk->list);
1275 dbg_wl("flush more (%d pending works)", ubi->works_count); 1275 ubi->works_count -= 1;
1276 err = do_work(ubi); 1276 ubi_assert(ubi->works_count >= 0);
1277 if (err) 1277 spin_unlock(&ubi->wl_lock);
1278 return err; 1278
1279 err = wrk->func(ubi, wrk, 0);
1280 if (err)
1281 goto out;
1282 spin_lock(&ubi->wl_lock);
1283 found = 1;
1284 break;
1285 }
1286 }
1287 spin_unlock(&ubi->wl_lock);
1279 } 1288 }
1280 1289
1281 return 0; 1290out:
1291 up_write(&ubi->work_sem);
1292 return err;
1282} 1293}
1283 1294
1284/** 1295/**
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index f636f5df883f..c3918a0684fe 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -219,6 +219,7 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
219int ubi_leb_map(struct ubi_volume_desc *desc, int lnum); 219int ubi_leb_map(struct ubi_volume_desc *desc, int lnum);
220int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); 220int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum);
221int ubi_sync(int ubi_num); 221int ubi_sync(int ubi_num);
222int ubi_flush(int ubi_num, int vol_id, int lnum);
222 223
223/* 224/*
224 * This function is the same as the 'ubi_leb_read()' function, but it does not 225 * This function is the same as the 'ubi_leb_read()' function, but it does not