diff options
-rw-r--r-- | drivers/mtd/ubi/cdev.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/kapi.c | 29 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/upd.c | 4 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 61 | ||||
-rw-r--r-- | include/linux/mtd/ubi.h | 1 |
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 | } |
556 | EXPORT_SYMBOL_GPL(ubi_leb_erase); | 556 | EXPORT_SYMBOL_GPL(ubi_leb_erase); |
557 | 557 | ||
@@ -704,6 +704,33 @@ int ubi_sync(int ubi_num) | |||
704 | } | 704 | } |
705 | EXPORT_SYMBOL_GPL(ubi_sync); | 705 | EXPORT_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 | */ | ||
719 | int 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 | } | ||
732 | EXPORT_SYMBOL_GPL(ubi_flush); | ||
733 | |||
707 | BLOCKING_NOTIFIER_HEAD(ubi_notifiers); | 734 | BLOCKING_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); | |||
669 | int ubi_wl_get_peb(struct ubi_device *ubi); | 669 | int ubi_wl_get_peb(struct ubi_device *ubi); |
670 | int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, | 670 | int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, |
671 | int pnum, int torture); | 671 | int pnum, int torture); |
672 | int ubi_wl_flush(struct ubi_device *ubi); | 672 | int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum); |
673 | int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); | 673 | int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); |
674 | int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai); | 674 | int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai); |
675 | void ubi_wl_close(struct ubi_device *ubi); | 675 | void 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 | */ |
1248 | int ubi_wl_flush(struct ubi_device *ubi) | 1253 | int 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; | 1290 | out: |
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); | |||
219 | int ubi_leb_map(struct ubi_volume_desc *desc, int lnum); | 219 | int ubi_leb_map(struct ubi_volume_desc *desc, int lnum); |
220 | int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); | 220 | int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); |
221 | int ubi_sync(int ubi_num); | 221 | int ubi_sync(int ubi_num); |
222 | int 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 |