diff options
author | Stefan Agner <stefan@agner.ch> | 2016-09-16 13:17:38 -0700 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2017-03-15 18:35:47 +0100 |
commit | 6819e8267b359913b95ccc822ac267454f39a460 (patch) | |
tree | 13ccc08839313536152b2c46fc9d3665c9e31db4 /drivers/mtd | |
parent | 440ef98ad687b210dca17e5c5141b24738f04922 (diff) | |
parent | 3b60b86aec06fbae1142ccc4e55b39b529ae2a25 (diff) |
Merge tag 'v4.1.32' into toradex_vf_4.1-next
Linux 4.1.32
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 13 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 43 | ||||
-rw-r--r-- | drivers/mtd/ubi/fastmap.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 25 |
6 files changed, 64 insertions, 22 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c6cf775ee431..0831af9a582c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2442,7 +2442,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, int cached = writelen > bytes && page != blockmask; uint8_t *wbuf = buf; int use_bufpoi; - int part_pagewr = (column || writelen < (mtd->writesize - 1)); + int part_pagewr = (column || writelen < mtd->writesize); if (part_pagewr) use_bufpoi = 1; diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index b7f824d5ee88..9fd4f7838080 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -887,7 +887,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, for (i = 0; i < UBI_MAX_DEVICES; i++) { ubi = ubi_devices[i]; if (ubi && mtd->index == ubi->mtd->index) { - ubi_err(ubi, "mtd%d is already attached to ubi%d", + pr_err("ubi: mtd%d is already attached to ubi%d", mtd->index, i); return -EEXIST; } @@ -902,7 +902,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, * no sense to attach emulated MTD devices, so we prohibit this. */ if (mtd->type == MTD_UBIVOLUME) { - ubi_err(ubi, "refuse attaching mtd%d - it is already emulated on top of UBI", + pr_err("ubi: refuse attaching mtd%d - it is already emulated on top of UBI", mtd->index); return -EINVAL; } @@ -913,7 +913,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, if (!ubi_devices[ubi_num]) break; if (ubi_num == UBI_MAX_DEVICES) { - ubi_err(ubi, "only %d UBI devices may be created", + pr_err("ubi: only %d UBI devices may be created", UBI_MAX_DEVICES); return -ENFILE; } @@ -923,7 +923,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, /* Make sure ubi_num is not busy */ if (ubi_devices[ubi_num]) { - ubi_err(ubi, "already exists"); + pr_err("ubi: ubi%i already exists", ubi_num); return -EEXIST; } } @@ -1005,6 +1005,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, goto out_detach; } + /* Make device "available" before it becomes accessible via sysfs */ + ubi_devices[ubi_num] = ubi; + err = uif_init(ubi, &ref); if (err) goto out_detach; @@ -1049,7 +1052,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, wake_up_process(ubi->bgt_thread); spin_unlock(&ubi->wl_lock); - ubi_devices[ubi_num] = ubi; ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL); return ubi_num; @@ -1060,6 +1062,7 @@ out_uif: ubi_assert(ref); uif_close(ubi); out_detach: + ubi_devices[ubi_num] = NULL; ubi_wl_close(ubi); ubi_free_internal_volumes(ubi); vfree(ubi->vtbl); diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 51bca035cd83..f109aeed9883 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -426,8 +426,25 @@ retry: pnum, vol_id, lnum); err = -EBADMSG; } else { - err = -EINVAL; - ubi_ro_mode(ubi); + /* + * Ending up here in the non-Fastmap case + * is a clear bug as the VID header had to + * be present at scan time to have it referenced. + * With fastmap the story is more complicated. + * Fastmap has the mapping info without the need + * of a full scan. So the LEB could have been + * unmapped, Fastmap cannot know this and keeps + * the LEB referenced. + * This is valid and works as the layer above UBI + * has to do bookkeeping about used/referenced + * LEBs in any case. + */ + if (ubi->fast_attach) { + err = -EBADMSG; + } else { + err = -EINVAL; + ubi_ro_mode(ubi); + } } } goto out_free; @@ -558,6 +575,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0; struct ubi_volume *vol = ubi->volumes[idx]; struct ubi_vid_hdr *vid_hdr; + uint32_t crc; vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); if (!vid_hdr) @@ -582,14 +600,8 @@ retry: goto out_put; } - vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); - err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); - if (err) { - up_read(&ubi->fm_eba_sem); - goto write_error; - } + ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC); - data_size = offset + len; mutex_lock(&ubi->buf_mutex); memset(ubi->peb_buf + offset, 0xFF, len); @@ -604,6 +616,19 @@ retry: memcpy(ubi->peb_buf + offset, buf, len); + data_size = offset + len; + crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size); + vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi)); + vid_hdr->copy_flag = 1; + vid_hdr->data_size = cpu_to_be32(data_size); + vid_hdr->data_crc = cpu_to_be32(crc); + err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); + if (err) { + mutex_unlock(&ubi->buf_mutex); + up_read(&ubi->fm_eba_sem); + goto write_error; + } + err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size); if (err) { mutex_unlock(&ubi->buf_mutex); diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 02a6de2f53ee..9f505b0dd292 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1051,6 +1051,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ubi_msg(ubi, "fastmap WL pool size: %d", ubi->fm_wl_pool.max_size); ubi->fm_disabled = 0; + ubi->fast_attach = 1; ubi_free_vid_hdr(ubi, vh); kfree(ech); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index c998212fc680..292a286ba489 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -462,6 +462,7 @@ struct ubi_debug_info { * @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes * @fm_work: fastmap work queue * @fm_work_scheduled: non-zero if fastmap work was scheduled + * @fast_attach: non-zero if UBI was attached by fastmap * * @used: RB-tree of used physical eraseblocks * @erroneous: RB-tree of erroneous used physical eraseblocks @@ -570,6 +571,7 @@ struct ubi_device { size_t fm_size; struct work_struct fm_work; int fm_work_scheduled; + int fast_attach; /* Wear-leveling sub-system's stuff */ struct rb_root used; diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index ff4d97848d1c..812ecf2d253a 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -536,13 +536,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) spin_unlock(&ubi->volumes_lock); } - /* Change volume table record */ - vtbl_rec = ubi->vtbl[vol_id]; - vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); - err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); - if (err) - goto out_acc; - if (pebs < 0) { for (i = 0; i < -pebs; i++) { err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i); @@ -560,6 +553,24 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) spin_unlock(&ubi->volumes_lock); } + /* + * When we shrink a volume we have to flush all pending (erase) work. + * Otherwise it can happen that upon next attach UBI finds a LEB with + * lnum > highest_lnum and refuses to attach. + */ + if (pebs < 0) { + err = ubi_wl_flush(ubi, vol_id, UBI_ALL); + if (err) + goto out_acc; + } + + /* Change volume table record */ + vtbl_rec = ubi->vtbl[vol_id]; + vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); + err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); + if (err) + goto out_acc; + vol->reserved_pebs = reserved_pebs; if (vol->vol_type == UBI_DYNAMIC_VOLUME) { vol->used_ebs = reserved_pebs; |