summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/fastmap-wl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/fastmap-wl.c')
-rw-r--r--drivers/mtd/ubi/fastmap-wl.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
index 2a9cc9413c42..9bdb6525f128 100644
--- a/drivers/mtd/ubi/fastmap-wl.c
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -346,14 +346,27 @@ out:
* WL sub-system.
*
* @ubi: UBI device description object
+ * @need_fill: whether to fill wear-leveling pool when no PEBs are found
*/
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
+ bool need_fill)
{
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
int pnum;
- if (pool->used == pool->size)
+ if (pool->used == pool->size) {
+ if (need_fill && !ubi->fm_work_scheduled) {
+ /*
+ * We cannot update the fastmap here because this
+ * function is called in atomic context.
+ * Let's fail here and refill/update it as soon as
+ * possible.
+ */
+ ubi->fm_work_scheduled = 1;
+ schedule_work(&ubi->fm_work);
+ }
return NULL;
+ }
pnum = pool->pebs[pool->used];
return ubi->lookuptbl[pnum];
@@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
if (!ubi->used.rb_node)
return false;
- e = next_peb_for_wl(ubi);
+ e = next_peb_for_wl(ubi, false);
if (!e) {
if (!ubi->free.rb_node)
return false;