Loading drivers/mtd/ubi/attach.c +32 −105 Original line number Diff line number Diff line /* * Copyright (c) International Business Machines Corp., 2006 * Copyright (c) 2014, Linux Foundation. All rights reserved. * Linux Foundation chooses to take subject only to the GPLv2 * license terms, and distributes only under these terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -90,21 +87,8 @@ #include <linux/crc32.h> #include <linux/math64.h> #include <linux/random.h> #include <linux/time.h> #include "ubi.h" #define set_aeb_default_values(aeb, ai) \ do { \ if (aeb->ec == UBI_UNKNOWN) { \ aeb->ec = ai->mean_ec; \ if (ai->mean_last_erase_time) \ aeb->last_erase_time = \ ai->mean_last_erase_time; \ else \ aeb->last_erase_time = UBI_DT_THRESHOLD / 2; \ } \ } while (0) static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai); /* Temporary variables used during scanning */ Loading @@ -118,9 +102,6 @@ static struct ubi_vid_hdr *vidh; * @vol_id: the last used volume id for the PEB * @lnum: the last used LEB number for the PEB * @ec: erase counter of the physical eraseblock * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * @to_head: if not zero, add to the head of the list * @list: the list to add to * Loading @@ -136,8 +117,7 @@ static struct ubi_vid_hdr *vidh; * failure. */ static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, int lnum, int ec, long last_erase_time, long rc, int to_head, struct list_head *list) int lnum, int ec, int to_head, struct list_head *list) { struct ubi_ainf_peb *aeb; Loading @@ -159,9 +139,6 @@ static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, aeb->vol_id = vol_id; aeb->lnum = lnum; aeb->ec = ec; aeb->rc = rc; aeb->last_erase_time = last_erase_time; if (to_head) list_add(&aeb->u.list, list); else Loading @@ -174,17 +151,13 @@ static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, * @ai: attaching information * @pnum: physical eraseblock number to add * @ec: erase counter of the physical eraseblock * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * * This function allocates a 'struct ubi_ainf_peb' object for a corrupted * physical eraseblock @pnum and adds it to the 'corr' list. The corruption * was presumably not caused by a power cut. Returns zero in case of success * and a negative error code in case of failure. */ static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec, long rc, long last_erase_time) static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec) { struct ubi_ainf_peb *aeb; Loading @@ -197,8 +170,6 @@ static int add_corrupted(struct ubi_attach_info *ai, int pnum, ai->corr_peb_count += 1; aeb->pnum = pnum; aeb->ec = ec; aeb->rc = rc; aeb->last_erase_time = last_erase_time; list_add(&aeb->u.list, &ai->corr); return 0; } Loading Loading @@ -465,9 +436,6 @@ out_free_vidh: * @ai: attaching information * @pnum: the physical eraseblock number * @ec: erase counter * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * @vid_hdr: the volume identifier header * @bitflips: if bit-flips were detected when this physical eraseblock was read * Loading @@ -479,8 +447,7 @@ out_free_vidh: * zero in case of success and a negative error code in case of failure. */ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, int ec, long last_erase_time, long rc, const struct ubi_vid_hdr *vid_hdr, int bitflips) int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips) { int err, vol_id, lnum; unsigned long long sqnum; Loading Loading @@ -567,16 +534,12 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, return err; err = add_to_list(ai, aeb->pnum, aeb->vol_id, aeb->lnum, aeb->ec, aeb->last_erase_time, aeb->rc, cmp_res & 4, aeb->lnum, aeb->ec, cmp_res & 4, &ai->erase); if (err) return err; aeb->ec = ec; aeb->last_erase_time = last_erase_time; aeb->rc = rc; aeb->pnum = pnum; aeb->vol_id = vol_id; aeb->lnum = lnum; Loading @@ -595,8 +558,7 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, * previously. */ return add_to_list(ai, pnum, vol_id, lnum, ec, last_erase_time, rc, cmp_res & 4, &ai->erase); cmp_res & 4, &ai->erase); } } Loading @@ -614,8 +576,6 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, return -ENOMEM; aeb->ec = ec; aeb->last_erase_time = last_erase_time; aeb->rc = rc; aeb->pnum = pnum; aeb->vol_id = vol_id; aeb->lnum = lnum; Loading Loading @@ -692,8 +652,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) * @ai: attaching information * @pnum: physical eraseblock number to erase; * @ec: erase counter value to write (%UBI_UNKNOWN if it is unknown) * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * * This function erases physical eraseblock 'pnum', and writes the erase * counter header to it. This function should only be used on UBI device Loading @@ -702,8 +660,7 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) * case of failure. */ static int early_erase_peb(struct ubi_device *ubi, const struct ubi_attach_info *ai, int pnum, int ec, long last_erase_time) const struct ubi_attach_info *ai, int pnum, int ec) { int err; struct ubi_ec_hdr *ec_hdr; Loading @@ -723,7 +680,7 @@ static int early_erase_peb(struct ubi_device *ubi, return -ENOMEM; ec_hdr->ec = cpu_to_be64(ec); ec_hdr->last_erase_time = cpu_to_be64(last_erase_time); err = ubi_io_sync_erase(ubi, pnum, 0); if (err < 0) goto out_free; Loading Loading @@ -754,7 +711,6 @@ struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, { int err = 0; struct ubi_ainf_peb *aeb, *tmp_aeb; struct timeval tv; if (!list_empty(&ai->free)) { aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list); Loading @@ -769,20 +725,15 @@ struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, * so forth. We don't want to take care about bad eraseblocks here - * they'll be handled later. */ do_gettimeofday(&tv); list_for_each_entry_safe(aeb, tmp_aeb, &ai->erase, u.list) { if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; /* The last erase time resolution is in days */ err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1, tv.tv_sec / NUM_SEC_IN_DAY); err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1); if (err) continue; aeb->ec += 1; aeb->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; aeb->rc = 0; list_del(&aeb->u.list); dbg_bld("return PEB %d, EC %d", aeb->pnum, aeb->ec); return aeb; Loading Loading @@ -869,8 +820,6 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, int *vid, unsigned long long *sqnum) { long long uninitialized_var(ec); long long uninitialized_var(rc); long long uninitialized_var(last_erase_time); int err, bitflips = 0, vol_id = -1, ec_err = 0; dbg_bld("scan PEB %d", pnum); Loading @@ -896,13 +845,11 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, case UBI_IO_FF: ai->empty_peb_count += 1; return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, 0, &ai->erase); UBI_UNKNOWN, 0, &ai->erase); case UBI_IO_FF_BITFLIPS: ai->empty_peb_count += 1; return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, 1, &ai->erase); UBI_UNKNOWN, 1, &ai->erase); case UBI_IO_BAD_HDR_EBADMSG: case UBI_IO_BAD_HDR: /* Loading @@ -912,8 +859,6 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, */ ec_err = err; ec = UBI_UNKNOWN; last_erase_time = UBI_UNKNOWN; rc = UBI_UNKNOWN; bitflips = 1; break; default: Loading @@ -933,16 +878,6 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, } ec = be64_to_cpu(ech->ec); last_erase_time = be64_to_cpu(ech->last_erase_time); /* * Default value for read counter should be 0. If this is a * free or erased peb, the counter has no meaning. * If this peb is used, later code will schedule the peb for * scrubbing. We can afford erasing all used blocks in this * case as this is a rear case, and not doing so might have * destructive implication on the system. */ rc = 0; if (ec > UBI_MAX_ERASECOUNTER) { /* * Erase counter overflow. The EC headers have 64 bits Loading Loading @@ -1027,32 +962,29 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, else if (!err) /* This corruption is caused by a power cut */ err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, rc, 1, &ai->erase); UBI_UNKNOWN, ec, 1, &ai->erase); else /* This is an unexpected corruption */ err = add_corrupted(ai, pnum, ec, rc, last_erase_time); err = add_corrupted(ai, pnum, ec); if (err) return err; goto adjust_mean_av_stat; goto adjust_mean_ec; case UBI_IO_FF_BITFLIPS: err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, rc, 1, &ai->erase); ec, 1, &ai->erase); if (err) return err; goto adjust_mean_av_stat; goto adjust_mean_ec; case UBI_IO_FF: if (ec_err || bitflips) err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, rc, 1, &ai->erase); UBI_UNKNOWN, ec, 1, &ai->erase); else err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, 0, 0, &ai->free); UBI_UNKNOWN, ec, 0, &ai->free); if (err) return err; goto adjust_mean_av_stat; goto adjust_mean_ec; default: ubi_err(ubi->ubi_num, "'ubi_io_read_vid_hdr()' returned unknown code %d", err); Loading @@ -1078,8 +1010,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, vol_id, lnum); } err = add_to_list(ai, pnum, vol_id, lnum, ec, last_erase_time, rc, 1, &ai->erase); ec, 1, &ai->erase); if (err) return err; return 0; Loading @@ -1098,8 +1029,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, "volume %d:%d found", vol_id, lnum); err = add_to_list(ai, pnum, vol_id, lnum, ec, last_erase_time, rc, 0, &ai->alien); ec, 0, &ai->alien); if (err) return err; return 0; Loading @@ -1114,13 +1044,11 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, if (ec_err) ubi_warn(ubi->ubi_num, "valid VID header but corrupted EC header at PEB %d", pnum); err = ubi_add_to_av(ubi, ai, pnum, ec, last_erase_time, UBI_DEF_RD_THRESHOLD, vidh, bitflips); err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips); if (err) return err; adjust_mean_av_stat: adjust_mean_ec: if (!ec_err) { ai->ec_sum += ec; ai->ec_count += 1; Loading @@ -1128,8 +1056,6 @@ adjust_mean_av_stat: ai->max_ec = ec; if (ec < ai->min_ec) ai->min_ec = ec; ai->last_erase_time_sum += last_erase_time; ai->last_erase_time_count++; } return 0; Loading Loading @@ -1339,10 +1265,6 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, if (ai->ec_count) ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count); if (ai->last_erase_time_count) ai->mean_last_erase_time = div_u64(ai->last_erase_time_sum, ai->last_erase_time_count); err = late_analysis(ubi, ai); if (err) goto out_vidh; Loading @@ -1353,17 +1275,22 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, */ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) set_aeb_default_values(aeb, ai); if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; } list_for_each_entry(aeb, &ai->free, u.list) set_aeb_default_values(aeb, ai); list_for_each_entry(aeb, &ai->free, u.list) { if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; } list_for_each_entry(aeb, &ai->corr, u.list) set_aeb_default_values(aeb, ai); if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; list_for_each_entry(aeb, &ai->erase, u.list) set_aeb_default_values(aeb, ai); if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; err = self_check_ai(ubi, ai); if (err) Loading drivers/mtd/ubi/debug.c +0 −12 Original line number Diff line number Diff line /* * Copyright (c) International Business Machines Corp., 2006 * Copyright (c) 2014, Linux Foundation. All rights reserved. * Linux Foundation chooses to take subject only to the GPLv2 * license terms, and distributes only under these terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -51,15 +48,6 @@ void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len) err, len, pnum, offset, read); goto out; } if (ubi->lookuptbl) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } else ubi_err(ubi->ubi_num, "Can't update RC. No lookuptbl"); ubi_msg(ubi->ubi_num, "dumping %d bytes of data from PEB %d, offset %d", len, pnum, offset); Loading drivers/mtd/ubi/fastmap.c +15 −103 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi) sizeof(struct ubi_fm_scan_pool) + \ (ubi->peb_count * sizeof(struct ubi_fm_ec)) + \ (sizeof(struct ubi_fm_eba) + \ (ubi->peb_count * sizeof(__be32)) + \ (ubi->peb_count * sizeof(__be32))) + \ sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES; return roundup(size, ubi->leb_size); Loading Loading @@ -73,16 +72,12 @@ out: * @list: the target list * @pnum: PEB number of the new attach erase block * @ec: erease counter of the new LEB * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * @scrub: scrub this PEB after attaching * * Returns 0 on success, < 0 indicates an internal error. */ static int add_aeb(struct ubi_attach_info *ai, struct list_head *list, int pnum, int ec, unsigned long last_erase_time, int rc, int scrub) int pnum, int ec, int scrub) { struct ubi_ainf_peb *aeb; Loading @@ -92,8 +87,6 @@ static int add_aeb(struct ubi_attach_info *ai, struct list_head *list, aeb->pnum = pnum; aeb->ec = ec; aeb->rc = rc; aeb->last_erase_time = last_erase_time; aeb->lnum = -1; aeb->scrub = scrub; aeb->copy_flag = aeb->sqnum = 0; Loading @@ -107,9 +100,6 @@ static int add_aeb(struct ubi_attach_info *ai, struct list_head *list, if (ai->min_ec > aeb->ec) ai->min_ec = aeb->ec; ai->last_erase_time_sum += aeb->last_erase_time; ai->last_erase_time_count++; list_add_tail(&aeb->u.list, list); return 0; Loading Loading @@ -257,8 +247,6 @@ static int update_vol(struct ubi_device *ubi, struct ubi_attach_info *ai, return -ENOMEM; victim->ec = aeb->ec; victim->last_erase_time = aeb->last_erase_time; victim->rc = aeb->rc; victim->pnum = aeb->pnum; list_add_tail(&victim->u.list, &ai->erase); Loading @@ -270,8 +258,6 @@ static int update_vol(struct ubi_device *ubi, struct ubi_attach_info *ai, av->vol_id, aeb->lnum, new_aeb->pnum); aeb->ec = new_aeb->ec; aeb->last_erase_time = new_aeb->last_erase_time; aeb->rc = new_aeb->rc; aeb->pnum = new_aeb->pnum; aeb->copy_flag = new_vh->copy_flag; aeb->scrub = new_aeb->scrub; Loading @@ -286,7 +272,7 @@ static int update_vol(struct ubi_device *ubi, struct ubi_attach_info *ai, return 0; } /* This LEB is new, last_erase_time's add it to the volume */ /* This LEB is new, let's add it to the volume */ if (av->highest_lnum <= be32_to_cpu(new_vh->lnum)) { av->highest_lnum = be32_to_cpu(new_vh->lnum); Loading Loading @@ -459,16 +445,12 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); if (err == UBI_IO_FF || err == UBI_IO_FF_BITFLIPS) { unsigned long long ec = be64_to_cpu(ech->ec); unsigned long long last_erase_time = be64_to_cpu(ech->last_erase_time); unmap_peb(ai, pnum); dbg_bld("Adding PEB to free: %i", pnum); if (err == UBI_IO_FF_BITFLIPS) add_aeb(ai, free, pnum, ec, last_erase_time, 0, 1); add_aeb(ai, free, pnum, ec, 1); else add_aeb(ai, free, pnum, ec, last_erase_time, 0, 0); add_aeb(ai, free, pnum, ec, 0); continue; } else if (err == 0 || err == UBI_IO_BITFLIPS) { dbg_bld("Found non empty PEB:%i in pool", pnum); Loading Loading @@ -496,9 +478,6 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, } new_aeb->ec = be64_to_cpu(ech->ec); new_aeb->last_erase_time = be64_to_cpu(ech->last_erase_time); new_aeb->rc = UBI_DEF_RD_THRESHOLD; new_aeb->pnum = pnum; new_aeb->lnum = be32_to_cpu(vh->lnum); new_aeb->sqnum = be64_to_cpu(vh->sqnum); Loading Loading @@ -673,9 +652,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 0); be32_to_cpu(fmec->ec), 0); } /* read EC values from used list */ Loading @@ -686,9 +663,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &used, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 0); be32_to_cpu(fmec->ec), 0); } /* read EC values from scrub list */ Loading @@ -699,9 +674,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &used, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 1); be32_to_cpu(fmec->ec), 1); } /* read EC values from erase list */ Loading @@ -712,14 +685,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 1); be32_to_cpu(fmec->ec), 1); } ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count); ai->mean_last_erase_time = div_u64(ai->last_erase_time_sum, ai->last_erase_time_count); ai->bad_peb_count = be32_to_cpu(fmhdr->bad_peb_count); /* Iterate over all volumes and read their EBA table */ Loading Loading @@ -751,8 +720,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, fm_eba = (struct ubi_fm_eba *)(fm_raw + fm_pos); fm_pos += sizeof(*fm_eba); fm_pos += 2 * (sizeof(__be32) * be32_to_cpu(fm_eba->reserved_pebs)); fm_pos += (sizeof(__be32) * be32_to_cpu(fm_eba->reserved_pebs)); if (fm_pos >= fm_size) goto fail_bad; Loading Loading @@ -796,9 +764,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, aeb->lnum = j; aeb->pnum = be32_to_cpu(fm_eba->peb_data[j].pnum); aeb->ec = UBI_UNKNOWN; aeb->rc = be32_to_cpu(fm_eba->peb_data[j].rc); aeb->last_erase_time = UBI_UNKNOWN; aeb->ec = -1; aeb->scrub = aeb->copy_flag = aeb->sqnum = 0; list_add_tail(&aeb->u.list, &eba_orphans); continue; Loading Loading @@ -845,9 +811,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, tmp_aeb->scrub = 1; tmp_aeb->ec = be64_to_cpu(ech->ec); tmp_aeb->last_erase_time = be64_to_cpu(ech->last_erase_time); tmp_aeb->rc = UBI_DEF_RD_THRESHOLD; assign_aeb_to_av(ai, tmp_aeb, av); } Loading Loading @@ -1112,8 +1075,6 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, e->pnum = be32_to_cpu(fmsb2->block_loc[i]); e->ec = be32_to_cpu(fmsb2->block_ec[i]); e->last_erase_time = be64_to_cpu(fmsb2->block_let[i]); e->rc = be32_to_cpu(fmsb2->block_rc[i]); fm->e[i] = e; } Loading Loading @@ -1233,8 +1194,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); free_peb_count++; fm_pos += sizeof(*fec); ubi_assert(fm_pos <= ubi->fm_size); Loading @@ -1247,8 +1207,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); used_peb_count++; fm_pos += sizeof(*fec); ubi_assert(fm_pos <= ubi->fm_size); Loading @@ -1274,8 +1233,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); scrub_peb_count++; fm_pos += sizeof(*fec); Loading @@ -1293,9 +1250,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); erase_peb_count++; fm_pos += sizeof(*fec); Loading Loading @@ -1331,15 +1285,8 @@ static int ubi_write_fastmap(struct ubi_device *ubi, 2 * (sizeof(__be32) * vol->reserved_pebs); ubi_assert(fm_pos <= ubi->fm_size); for (j = 0; j < vol->reserved_pebs; j++) { for (j = 0; j < vol->reserved_pebs; j++) feba->peb_data[j].pnum = cpu_to_be32(vol->eba_tbl[j]); feba->peb_data[j].rc = cpu_to_be32(UBI_UNKNOWN); if (vol->eba_tbl[j] >= 0 && ubi->lookuptbl[vol->eba_tbl[j]]) feba->peb_data[j].rc = cpu_to_be32( ubi->lookuptbl[vol->eba_tbl[j]]->rc); } feba->reserved_pebs = cpu_to_be32(j); feba->magic = cpu_to_be32(UBI_FM_EBA_MAGIC); Loading @@ -1363,8 +1310,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi, for (i = 0; i < new_fm->used_blocks; i++) { fmsb->block_loc[i] = cpu_to_be32(new_fm->e[i]->pnum); fmsb->block_ec[i] = cpu_to_be32(new_fm->e[i]->ec); fmsb->block_let[i] = cpu_to_be64(new_fm->e[i]->last_erase_time); fmsb->block_rc[i] = cpu_to_be32(new_fm->e[i]->rc); } fmsb->data_crc = 0; Loading Loading @@ -1420,7 +1365,6 @@ static int erase_block(struct ubi_device *ubi, int pnum) int ret; struct ubi_ec_hdr *ec_hdr; long long ec; struct timeval tv; ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); if (!ec_hdr) Loading @@ -1446,9 +1390,6 @@ static int erase_block(struct ubi_device *ubi, int pnum) } ec_hdr->ec = cpu_to_be64(ec); do_gettimeofday(&tv); /* The last erase time resolution is in days */ ec_hdr->last_erase_time = cpu_to_be64(tv.tv_sec / NUM_SEC_IN_DAY); ret = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr); if (ret < 0) goto out; Loading @@ -1471,17 +1412,10 @@ static int invalidate_fastmap(struct ubi_device *ubi, { int ret; struct ubi_vid_hdr *vh; struct timeval tv; ret = erase_block(ubi, fm->e[0]->pnum); if (ret < 0) return ret; fm->e[0]->ec = ret; do_gettimeofday(&tv); /* The last erase time resolution is in days */ fm->e[0]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; fm->e[0]->rc = 0; vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID); if (!vh) Loading @@ -1508,9 +1442,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) int ret, i; struct ubi_fastmap_layout *new_fm, *old_fm; struct ubi_wl_entry *tmp_e; struct timeval tv; do_gettimeofday(&tv); mutex_lock(&ubi->fm_mutex); Loading Loading @@ -1586,19 +1517,10 @@ int ubi_update_fastmap(struct ubi_device *ubi) } new_fm->e[i]->pnum = old_fm->e[i]->pnum; new_fm->e[i]->ec = old_fm->e[i]->ec = ret; /* The last erase time resolution is in days */ new_fm->e[i]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; old_fm->e[i]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; new_fm->e[i]->rc = old_fm->e[i]->rc = 0; new_fm->e[i]->ec = old_fm->e[i]->ec; } else { new_fm->e[i]->pnum = tmp_e->pnum; new_fm->e[i]->ec = tmp_e->ec; new_fm->e[i]->rc = tmp_e->rc; new_fm->e[i]->last_erase_time = tmp_e->last_erase_time; if (old_fm) ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, Loading Loading @@ -1626,13 +1548,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) } new_fm->e[0]->pnum = old_fm->e[0]->pnum; new_fm->e[0]->ec = old_fm->e[0]->ec = ret; /* The last erase time resolution is in days */ new_fm->e[0]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; old_fm->e[0]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; new_fm->e[0]->rc = old_fm->e[0]->rc = 0; new_fm->e[0]->ec = ret; } else { /* we've got a new anchor PEB, return the old one */ ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0, Loading @@ -1640,8 +1556,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) new_fm->e[0]->pnum = tmp_e->pnum; new_fm->e[0]->ec = tmp_e->ec; new_fm->e[0]->last_erase_time = tmp_e->last_erase_time; new_fm->e[0]->rc = tmp_e->rc; } } else { if (!tmp_e) { Loading @@ -1657,8 +1571,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) new_fm->e[0]->pnum = tmp_e->pnum; new_fm->e[0]->ec = tmp_e->ec; new_fm->e[0]->last_erase_time = tmp_e->last_erase_time; new_fm->e[0]->rc = tmp_e->rc; } down_write(&ubi->work_sem); Loading drivers/mtd/ubi/io.c +0 −32 Original line number Diff line number Diff line /* * Copyright (c) International Business Machines Corp., 2006 * Copyright (c) Nokia Corporation, 2006, 2007 * Copyright (c) 2014, Linux Foundation. All rights reserved. * Linux Foundation chooses to take subject only to the GPLv2 * license terms, and distributes only under these terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -212,15 +209,6 @@ retry: } } else { ubi_assert(len == read); if (ubi->lookuptbl && ubi->lookuptbl[pnum]) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } if (ubi_dbg_is_bitflip(ubi)) { dbg_gen("bit-flip (emulated)"); Loading Loading @@ -1380,16 +1368,6 @@ static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum, if (err && !mtd_is_bitflip(err)) goto out_free; if (ubi->lookuptbl && ubi->lookuptbl[pnum]) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } else ubi_err(ubi->ubi_num, "Can't update RC. No lookuptbl"); for (i = 0; i < len; i++) { uint8_t c = ((uint8_t *)buf)[i]; uint8_t c1 = ((uint8_t *)buf1)[i]; Loading Loading @@ -1459,16 +1437,6 @@ int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) err, len, pnum, offset, read); goto error; } if (ubi->lookuptbl && ubi->lookuptbl[pnum]) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } else ubi_err(ubi->ubi_num, "Can't update RC. No lookuptbl"); err = ubi_check_pattern(buf, 0xFF, len); if (err == 0) { Loading drivers/mtd/ubi/ubi.h +1 −23 Original line number Diff line number Diff line Loading @@ -96,16 +96,6 @@ */ #define UBI_RD_THRESHOLD 100000 /* * This is the default read counter to be assigned to blocks lacking * read counter value on attach. The value was choosen as mean between * just_erased_block (rc = 0) and needs_scrubbibg_block * (rc = UBI_RD_THRESHOLD). On the one hand we don't want to miss * blocks that needs scrubbing but on the other, we dont want to * abuse scrubbing. */ #define UBI_DEF_RD_THRESHOLD (UBI_RD_THRESHOLD / 2) /* * This parameter defines the maximun interval (in days) between two * erasures of an eraseblock. When this interval is reached, UBI starts Loading @@ -114,9 +104,6 @@ */ #define UBI_DT_THRESHOLD 120 /* Used when calculaing the lats erase timestamp of a PEB */ #define NUM_SEC_IN_DAY (60*60*24) /* * The UBI debugfs directory name pattern and maximum name length (3 for "ubi" * + 2 for the number plus 1 for the trailing zero byte. Loading Loading @@ -736,11 +723,6 @@ struct ubi_ainf_volume { * @ec_count: a temporary variable used when calculating @mean_ec * @failed_fm: set to true if fm faound invalid during attach * @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects * @mean_last_erase_time: mean late erase timestamp value * @last_erase_time_sum: temporary variable, used to calculate * @mean_last_erase_time * @last_erase_time_count: temporary variable, used to calculate * @mean_last_erase_time * * This data structure contains the result of attaching an MTD device and may * be used by other UBI sub-systems to build final UBI data structures, further Loading Loading @@ -768,9 +750,6 @@ struct ubi_attach_info { int ec_count; int failed_fm; struct kmem_cache *aeb_slab_cache; long long mean_last_erase_time; long long last_erase_time_sum; int last_erase_time_count; }; /** Loading Loading @@ -811,8 +790,7 @@ extern struct blocking_notifier_head ubi_notifiers; /* attach.c */ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, int ec, long last_erase_time, long rc, const struct ubi_vid_hdr *vid_hdr, int bitflips); int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips); struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, int vol_id); void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); Loading Loading
drivers/mtd/ubi/attach.c +32 −105 Original line number Diff line number Diff line /* * Copyright (c) International Business Machines Corp., 2006 * Copyright (c) 2014, Linux Foundation. All rights reserved. * Linux Foundation chooses to take subject only to the GPLv2 * license terms, and distributes only under these terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -90,21 +87,8 @@ #include <linux/crc32.h> #include <linux/math64.h> #include <linux/random.h> #include <linux/time.h> #include "ubi.h" #define set_aeb_default_values(aeb, ai) \ do { \ if (aeb->ec == UBI_UNKNOWN) { \ aeb->ec = ai->mean_ec; \ if (ai->mean_last_erase_time) \ aeb->last_erase_time = \ ai->mean_last_erase_time; \ else \ aeb->last_erase_time = UBI_DT_THRESHOLD / 2; \ } \ } while (0) static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai); /* Temporary variables used during scanning */ Loading @@ -118,9 +102,6 @@ static struct ubi_vid_hdr *vidh; * @vol_id: the last used volume id for the PEB * @lnum: the last used LEB number for the PEB * @ec: erase counter of the physical eraseblock * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * @to_head: if not zero, add to the head of the list * @list: the list to add to * Loading @@ -136,8 +117,7 @@ static struct ubi_vid_hdr *vidh; * failure. */ static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, int lnum, int ec, long last_erase_time, long rc, int to_head, struct list_head *list) int lnum, int ec, int to_head, struct list_head *list) { struct ubi_ainf_peb *aeb; Loading @@ -159,9 +139,6 @@ static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, aeb->vol_id = vol_id; aeb->lnum = lnum; aeb->ec = ec; aeb->rc = rc; aeb->last_erase_time = last_erase_time; if (to_head) list_add(&aeb->u.list, list); else Loading @@ -174,17 +151,13 @@ static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, * @ai: attaching information * @pnum: physical eraseblock number to add * @ec: erase counter of the physical eraseblock * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * * This function allocates a 'struct ubi_ainf_peb' object for a corrupted * physical eraseblock @pnum and adds it to the 'corr' list. The corruption * was presumably not caused by a power cut. Returns zero in case of success * and a negative error code in case of failure. */ static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec, long rc, long last_erase_time) static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec) { struct ubi_ainf_peb *aeb; Loading @@ -197,8 +170,6 @@ static int add_corrupted(struct ubi_attach_info *ai, int pnum, ai->corr_peb_count += 1; aeb->pnum = pnum; aeb->ec = ec; aeb->rc = rc; aeb->last_erase_time = last_erase_time; list_add(&aeb->u.list, &ai->corr); return 0; } Loading Loading @@ -465,9 +436,6 @@ out_free_vidh: * @ai: attaching information * @pnum: the physical eraseblock number * @ec: erase counter * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * @vid_hdr: the volume identifier header * @bitflips: if bit-flips were detected when this physical eraseblock was read * Loading @@ -479,8 +447,7 @@ out_free_vidh: * zero in case of success and a negative error code in case of failure. */ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, int ec, long last_erase_time, long rc, const struct ubi_vid_hdr *vid_hdr, int bitflips) int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips) { int err, vol_id, lnum; unsigned long long sqnum; Loading Loading @@ -567,16 +534,12 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, return err; err = add_to_list(ai, aeb->pnum, aeb->vol_id, aeb->lnum, aeb->ec, aeb->last_erase_time, aeb->rc, cmp_res & 4, aeb->lnum, aeb->ec, cmp_res & 4, &ai->erase); if (err) return err; aeb->ec = ec; aeb->last_erase_time = last_erase_time; aeb->rc = rc; aeb->pnum = pnum; aeb->vol_id = vol_id; aeb->lnum = lnum; Loading @@ -595,8 +558,7 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, * previously. */ return add_to_list(ai, pnum, vol_id, lnum, ec, last_erase_time, rc, cmp_res & 4, &ai->erase); cmp_res & 4, &ai->erase); } } Loading @@ -614,8 +576,6 @@ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, return -ENOMEM; aeb->ec = ec; aeb->last_erase_time = last_erase_time; aeb->rc = rc; aeb->pnum = pnum; aeb->vol_id = vol_id; aeb->lnum = lnum; Loading Loading @@ -692,8 +652,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) * @ai: attaching information * @pnum: physical eraseblock number to erase; * @ec: erase counter value to write (%UBI_UNKNOWN if it is unknown) * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * * This function erases physical eraseblock 'pnum', and writes the erase * counter header to it. This function should only be used on UBI device Loading @@ -702,8 +660,7 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) * case of failure. */ static int early_erase_peb(struct ubi_device *ubi, const struct ubi_attach_info *ai, int pnum, int ec, long last_erase_time) const struct ubi_attach_info *ai, int pnum, int ec) { int err; struct ubi_ec_hdr *ec_hdr; Loading @@ -723,7 +680,7 @@ static int early_erase_peb(struct ubi_device *ubi, return -ENOMEM; ec_hdr->ec = cpu_to_be64(ec); ec_hdr->last_erase_time = cpu_to_be64(last_erase_time); err = ubi_io_sync_erase(ubi, pnum, 0); if (err < 0) goto out_free; Loading Loading @@ -754,7 +711,6 @@ struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, { int err = 0; struct ubi_ainf_peb *aeb, *tmp_aeb; struct timeval tv; if (!list_empty(&ai->free)) { aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list); Loading @@ -769,20 +725,15 @@ struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, * so forth. We don't want to take care about bad eraseblocks here - * they'll be handled later. */ do_gettimeofday(&tv); list_for_each_entry_safe(aeb, tmp_aeb, &ai->erase, u.list) { if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; /* The last erase time resolution is in days */ err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1, tv.tv_sec / NUM_SEC_IN_DAY); err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1); if (err) continue; aeb->ec += 1; aeb->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; aeb->rc = 0; list_del(&aeb->u.list); dbg_bld("return PEB %d, EC %d", aeb->pnum, aeb->ec); return aeb; Loading Loading @@ -869,8 +820,6 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, int *vid, unsigned long long *sqnum) { long long uninitialized_var(ec); long long uninitialized_var(rc); long long uninitialized_var(last_erase_time); int err, bitflips = 0, vol_id = -1, ec_err = 0; dbg_bld("scan PEB %d", pnum); Loading @@ -896,13 +845,11 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, case UBI_IO_FF: ai->empty_peb_count += 1; return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, 0, &ai->erase); UBI_UNKNOWN, 0, &ai->erase); case UBI_IO_FF_BITFLIPS: ai->empty_peb_count += 1; return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, UBI_UNKNOWN, 1, &ai->erase); UBI_UNKNOWN, 1, &ai->erase); case UBI_IO_BAD_HDR_EBADMSG: case UBI_IO_BAD_HDR: /* Loading @@ -912,8 +859,6 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, */ ec_err = err; ec = UBI_UNKNOWN; last_erase_time = UBI_UNKNOWN; rc = UBI_UNKNOWN; bitflips = 1; break; default: Loading @@ -933,16 +878,6 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, } ec = be64_to_cpu(ech->ec); last_erase_time = be64_to_cpu(ech->last_erase_time); /* * Default value for read counter should be 0. If this is a * free or erased peb, the counter has no meaning. * If this peb is used, later code will schedule the peb for * scrubbing. We can afford erasing all used blocks in this * case as this is a rear case, and not doing so might have * destructive implication on the system. */ rc = 0; if (ec > UBI_MAX_ERASECOUNTER) { /* * Erase counter overflow. The EC headers have 64 bits Loading Loading @@ -1027,32 +962,29 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, else if (!err) /* This corruption is caused by a power cut */ err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, rc, 1, &ai->erase); UBI_UNKNOWN, ec, 1, &ai->erase); else /* This is an unexpected corruption */ err = add_corrupted(ai, pnum, ec, rc, last_erase_time); err = add_corrupted(ai, pnum, ec); if (err) return err; goto adjust_mean_av_stat; goto adjust_mean_ec; case UBI_IO_FF_BITFLIPS: err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, rc, 1, &ai->erase); ec, 1, &ai->erase); if (err) return err; goto adjust_mean_av_stat; goto adjust_mean_ec; case UBI_IO_FF: if (ec_err || bitflips) err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, rc, 1, &ai->erase); UBI_UNKNOWN, ec, 1, &ai->erase); else err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, ec, last_erase_time, 0, 0, &ai->free); UBI_UNKNOWN, ec, 0, &ai->free); if (err) return err; goto adjust_mean_av_stat; goto adjust_mean_ec; default: ubi_err(ubi->ubi_num, "'ubi_io_read_vid_hdr()' returned unknown code %d", err); Loading @@ -1078,8 +1010,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, vol_id, lnum); } err = add_to_list(ai, pnum, vol_id, lnum, ec, last_erase_time, rc, 1, &ai->erase); ec, 1, &ai->erase); if (err) return err; return 0; Loading @@ -1098,8 +1029,7 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, "volume %d:%d found", vol_id, lnum); err = add_to_list(ai, pnum, vol_id, lnum, ec, last_erase_time, rc, 0, &ai->alien); ec, 0, &ai->alien); if (err) return err; return 0; Loading @@ -1114,13 +1044,11 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, if (ec_err) ubi_warn(ubi->ubi_num, "valid VID header but corrupted EC header at PEB %d", pnum); err = ubi_add_to_av(ubi, ai, pnum, ec, last_erase_time, UBI_DEF_RD_THRESHOLD, vidh, bitflips); err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips); if (err) return err; adjust_mean_av_stat: adjust_mean_ec: if (!ec_err) { ai->ec_sum += ec; ai->ec_count += 1; Loading @@ -1128,8 +1056,6 @@ adjust_mean_av_stat: ai->max_ec = ec; if (ec < ai->min_ec) ai->min_ec = ec; ai->last_erase_time_sum += last_erase_time; ai->last_erase_time_count++; } return 0; Loading Loading @@ -1339,10 +1265,6 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, if (ai->ec_count) ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count); if (ai->last_erase_time_count) ai->mean_last_erase_time = div_u64(ai->last_erase_time_sum, ai->last_erase_time_count); err = late_analysis(ubi, ai); if (err) goto out_vidh; Loading @@ -1353,17 +1275,22 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai, */ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) set_aeb_default_values(aeb, ai); if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; } list_for_each_entry(aeb, &ai->free, u.list) set_aeb_default_values(aeb, ai); list_for_each_entry(aeb, &ai->free, u.list) { if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; } list_for_each_entry(aeb, &ai->corr, u.list) set_aeb_default_values(aeb, ai); if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; list_for_each_entry(aeb, &ai->erase, u.list) set_aeb_default_values(aeb, ai); if (aeb->ec == UBI_UNKNOWN) aeb->ec = ai->mean_ec; err = self_check_ai(ubi, ai); if (err) Loading
drivers/mtd/ubi/debug.c +0 −12 Original line number Diff line number Diff line /* * Copyright (c) International Business Machines Corp., 2006 * Copyright (c) 2014, Linux Foundation. All rights reserved. * Linux Foundation chooses to take subject only to the GPLv2 * license terms, and distributes only under these terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -51,15 +48,6 @@ void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len) err, len, pnum, offset, read); goto out; } if (ubi->lookuptbl) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } else ubi_err(ubi->ubi_num, "Can't update RC. No lookuptbl"); ubi_msg(ubi->ubi_num, "dumping %d bytes of data from PEB %d, offset %d", len, pnum, offset); Loading
drivers/mtd/ubi/fastmap.c +15 −103 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi) sizeof(struct ubi_fm_scan_pool) + \ (ubi->peb_count * sizeof(struct ubi_fm_ec)) + \ (sizeof(struct ubi_fm_eba) + \ (ubi->peb_count * sizeof(__be32)) + \ (ubi->peb_count * sizeof(__be32))) + \ sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES; return roundup(size, ubi->leb_size); Loading Loading @@ -73,16 +72,12 @@ out: * @list: the target list * @pnum: PEB number of the new attach erase block * @ec: erease counter of the new LEB * @last_erase_time: last erase time stamp (%UBI_UNKNOWN if it * is unknown) * @rc: read counter (%UBI_UNKNOWN if it is unknown) * @scrub: scrub this PEB after attaching * * Returns 0 on success, < 0 indicates an internal error. */ static int add_aeb(struct ubi_attach_info *ai, struct list_head *list, int pnum, int ec, unsigned long last_erase_time, int rc, int scrub) int pnum, int ec, int scrub) { struct ubi_ainf_peb *aeb; Loading @@ -92,8 +87,6 @@ static int add_aeb(struct ubi_attach_info *ai, struct list_head *list, aeb->pnum = pnum; aeb->ec = ec; aeb->rc = rc; aeb->last_erase_time = last_erase_time; aeb->lnum = -1; aeb->scrub = scrub; aeb->copy_flag = aeb->sqnum = 0; Loading @@ -107,9 +100,6 @@ static int add_aeb(struct ubi_attach_info *ai, struct list_head *list, if (ai->min_ec > aeb->ec) ai->min_ec = aeb->ec; ai->last_erase_time_sum += aeb->last_erase_time; ai->last_erase_time_count++; list_add_tail(&aeb->u.list, list); return 0; Loading Loading @@ -257,8 +247,6 @@ static int update_vol(struct ubi_device *ubi, struct ubi_attach_info *ai, return -ENOMEM; victim->ec = aeb->ec; victim->last_erase_time = aeb->last_erase_time; victim->rc = aeb->rc; victim->pnum = aeb->pnum; list_add_tail(&victim->u.list, &ai->erase); Loading @@ -270,8 +258,6 @@ static int update_vol(struct ubi_device *ubi, struct ubi_attach_info *ai, av->vol_id, aeb->lnum, new_aeb->pnum); aeb->ec = new_aeb->ec; aeb->last_erase_time = new_aeb->last_erase_time; aeb->rc = new_aeb->rc; aeb->pnum = new_aeb->pnum; aeb->copy_flag = new_vh->copy_flag; aeb->scrub = new_aeb->scrub; Loading @@ -286,7 +272,7 @@ static int update_vol(struct ubi_device *ubi, struct ubi_attach_info *ai, return 0; } /* This LEB is new, last_erase_time's add it to the volume */ /* This LEB is new, let's add it to the volume */ if (av->highest_lnum <= be32_to_cpu(new_vh->lnum)) { av->highest_lnum = be32_to_cpu(new_vh->lnum); Loading Loading @@ -459,16 +445,12 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); if (err == UBI_IO_FF || err == UBI_IO_FF_BITFLIPS) { unsigned long long ec = be64_to_cpu(ech->ec); unsigned long long last_erase_time = be64_to_cpu(ech->last_erase_time); unmap_peb(ai, pnum); dbg_bld("Adding PEB to free: %i", pnum); if (err == UBI_IO_FF_BITFLIPS) add_aeb(ai, free, pnum, ec, last_erase_time, 0, 1); add_aeb(ai, free, pnum, ec, 1); else add_aeb(ai, free, pnum, ec, last_erase_time, 0, 0); add_aeb(ai, free, pnum, ec, 0); continue; } else if (err == 0 || err == UBI_IO_BITFLIPS) { dbg_bld("Found non empty PEB:%i in pool", pnum); Loading Loading @@ -496,9 +478,6 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai, } new_aeb->ec = be64_to_cpu(ech->ec); new_aeb->last_erase_time = be64_to_cpu(ech->last_erase_time); new_aeb->rc = UBI_DEF_RD_THRESHOLD; new_aeb->pnum = pnum; new_aeb->lnum = be32_to_cpu(vh->lnum); new_aeb->sqnum = be64_to_cpu(vh->sqnum); Loading Loading @@ -673,9 +652,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 0); be32_to_cpu(fmec->ec), 0); } /* read EC values from used list */ Loading @@ -686,9 +663,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &used, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 0); be32_to_cpu(fmec->ec), 0); } /* read EC values from scrub list */ Loading @@ -699,9 +674,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &used, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 1); be32_to_cpu(fmec->ec), 1); } /* read EC values from erase list */ Loading @@ -712,14 +685,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, goto fail_bad; add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum), be32_to_cpu(fmec->ec), be64_to_cpu(fmec->last_erase_time), be32_to_cpu(fmec->rc), 1); be32_to_cpu(fmec->ec), 1); } ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count); ai->mean_last_erase_time = div_u64(ai->last_erase_time_sum, ai->last_erase_time_count); ai->bad_peb_count = be32_to_cpu(fmhdr->bad_peb_count); /* Iterate over all volumes and read their EBA table */ Loading Loading @@ -751,8 +720,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, fm_eba = (struct ubi_fm_eba *)(fm_raw + fm_pos); fm_pos += sizeof(*fm_eba); fm_pos += 2 * (sizeof(__be32) * be32_to_cpu(fm_eba->reserved_pebs)); fm_pos += (sizeof(__be32) * be32_to_cpu(fm_eba->reserved_pebs)); if (fm_pos >= fm_size) goto fail_bad; Loading Loading @@ -796,9 +764,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, aeb->lnum = j; aeb->pnum = be32_to_cpu(fm_eba->peb_data[j].pnum); aeb->ec = UBI_UNKNOWN; aeb->rc = be32_to_cpu(fm_eba->peb_data[j].rc); aeb->last_erase_time = UBI_UNKNOWN; aeb->ec = -1; aeb->scrub = aeb->copy_flag = aeb->sqnum = 0; list_add_tail(&aeb->u.list, &eba_orphans); continue; Loading Loading @@ -845,9 +811,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, tmp_aeb->scrub = 1; tmp_aeb->ec = be64_to_cpu(ech->ec); tmp_aeb->last_erase_time = be64_to_cpu(ech->last_erase_time); tmp_aeb->rc = UBI_DEF_RD_THRESHOLD; assign_aeb_to_av(ai, tmp_aeb, av); } Loading Loading @@ -1112,8 +1075,6 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, e->pnum = be32_to_cpu(fmsb2->block_loc[i]); e->ec = be32_to_cpu(fmsb2->block_ec[i]); e->last_erase_time = be64_to_cpu(fmsb2->block_let[i]); e->rc = be32_to_cpu(fmsb2->block_rc[i]); fm->e[i] = e; } Loading Loading @@ -1233,8 +1194,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); free_peb_count++; fm_pos += sizeof(*fec); ubi_assert(fm_pos <= ubi->fm_size); Loading @@ -1247,8 +1207,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); used_peb_count++; fm_pos += sizeof(*fec); ubi_assert(fm_pos <= ubi->fm_size); Loading @@ -1274,8 +1233,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); scrub_peb_count++; fm_pos += sizeof(*fec); Loading @@ -1293,9 +1250,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi, fec->pnum = cpu_to_be32(wl_e->pnum); fec->ec = cpu_to_be32(wl_e->ec); fec->last_erase_time = cpu_to_be64(wl_e->last_erase_time); fec->rc = cpu_to_be32(wl_e->rc); erase_peb_count++; fm_pos += sizeof(*fec); Loading Loading @@ -1331,15 +1285,8 @@ static int ubi_write_fastmap(struct ubi_device *ubi, 2 * (sizeof(__be32) * vol->reserved_pebs); ubi_assert(fm_pos <= ubi->fm_size); for (j = 0; j < vol->reserved_pebs; j++) { for (j = 0; j < vol->reserved_pebs; j++) feba->peb_data[j].pnum = cpu_to_be32(vol->eba_tbl[j]); feba->peb_data[j].rc = cpu_to_be32(UBI_UNKNOWN); if (vol->eba_tbl[j] >= 0 && ubi->lookuptbl[vol->eba_tbl[j]]) feba->peb_data[j].rc = cpu_to_be32( ubi->lookuptbl[vol->eba_tbl[j]]->rc); } feba->reserved_pebs = cpu_to_be32(j); feba->magic = cpu_to_be32(UBI_FM_EBA_MAGIC); Loading @@ -1363,8 +1310,6 @@ static int ubi_write_fastmap(struct ubi_device *ubi, for (i = 0; i < new_fm->used_blocks; i++) { fmsb->block_loc[i] = cpu_to_be32(new_fm->e[i]->pnum); fmsb->block_ec[i] = cpu_to_be32(new_fm->e[i]->ec); fmsb->block_let[i] = cpu_to_be64(new_fm->e[i]->last_erase_time); fmsb->block_rc[i] = cpu_to_be32(new_fm->e[i]->rc); } fmsb->data_crc = 0; Loading Loading @@ -1420,7 +1365,6 @@ static int erase_block(struct ubi_device *ubi, int pnum) int ret; struct ubi_ec_hdr *ec_hdr; long long ec; struct timeval tv; ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); if (!ec_hdr) Loading @@ -1446,9 +1390,6 @@ static int erase_block(struct ubi_device *ubi, int pnum) } ec_hdr->ec = cpu_to_be64(ec); do_gettimeofday(&tv); /* The last erase time resolution is in days */ ec_hdr->last_erase_time = cpu_to_be64(tv.tv_sec / NUM_SEC_IN_DAY); ret = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr); if (ret < 0) goto out; Loading @@ -1471,17 +1412,10 @@ static int invalidate_fastmap(struct ubi_device *ubi, { int ret; struct ubi_vid_hdr *vh; struct timeval tv; ret = erase_block(ubi, fm->e[0]->pnum); if (ret < 0) return ret; fm->e[0]->ec = ret; do_gettimeofday(&tv); /* The last erase time resolution is in days */ fm->e[0]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; fm->e[0]->rc = 0; vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID); if (!vh) Loading @@ -1508,9 +1442,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) int ret, i; struct ubi_fastmap_layout *new_fm, *old_fm; struct ubi_wl_entry *tmp_e; struct timeval tv; do_gettimeofday(&tv); mutex_lock(&ubi->fm_mutex); Loading Loading @@ -1586,19 +1517,10 @@ int ubi_update_fastmap(struct ubi_device *ubi) } new_fm->e[i]->pnum = old_fm->e[i]->pnum; new_fm->e[i]->ec = old_fm->e[i]->ec = ret; /* The last erase time resolution is in days */ new_fm->e[i]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; old_fm->e[i]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; new_fm->e[i]->rc = old_fm->e[i]->rc = 0; new_fm->e[i]->ec = old_fm->e[i]->ec; } else { new_fm->e[i]->pnum = tmp_e->pnum; new_fm->e[i]->ec = tmp_e->ec; new_fm->e[i]->rc = tmp_e->rc; new_fm->e[i]->last_erase_time = tmp_e->last_erase_time; if (old_fm) ubi_wl_put_fm_peb(ubi, old_fm->e[i], i, Loading Loading @@ -1626,13 +1548,7 @@ int ubi_update_fastmap(struct ubi_device *ubi) } new_fm->e[0]->pnum = old_fm->e[0]->pnum; new_fm->e[0]->ec = old_fm->e[0]->ec = ret; /* The last erase time resolution is in days */ new_fm->e[0]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; old_fm->e[0]->last_erase_time = tv.tv_sec / NUM_SEC_IN_DAY; new_fm->e[0]->rc = old_fm->e[0]->rc = 0; new_fm->e[0]->ec = ret; } else { /* we've got a new anchor PEB, return the old one */ ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0, Loading @@ -1640,8 +1556,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) new_fm->e[0]->pnum = tmp_e->pnum; new_fm->e[0]->ec = tmp_e->ec; new_fm->e[0]->last_erase_time = tmp_e->last_erase_time; new_fm->e[0]->rc = tmp_e->rc; } } else { if (!tmp_e) { Loading @@ -1657,8 +1571,6 @@ int ubi_update_fastmap(struct ubi_device *ubi) new_fm->e[0]->pnum = tmp_e->pnum; new_fm->e[0]->ec = tmp_e->ec; new_fm->e[0]->last_erase_time = tmp_e->last_erase_time; new_fm->e[0]->rc = tmp_e->rc; } down_write(&ubi->work_sem); Loading
drivers/mtd/ubi/io.c +0 −32 Original line number Diff line number Diff line /* * Copyright (c) International Business Machines Corp., 2006 * Copyright (c) Nokia Corporation, 2006, 2007 * Copyright (c) 2014, Linux Foundation. All rights reserved. * Linux Foundation chooses to take subject only to the GPLv2 * license terms, and distributes only under these terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading Loading @@ -212,15 +209,6 @@ retry: } } else { ubi_assert(len == read); if (ubi->lookuptbl && ubi->lookuptbl[pnum]) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } if (ubi_dbg_is_bitflip(ubi)) { dbg_gen("bit-flip (emulated)"); Loading Loading @@ -1380,16 +1368,6 @@ static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum, if (err && !mtd_is_bitflip(err)) goto out_free; if (ubi->lookuptbl && ubi->lookuptbl[pnum]) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } else ubi_err(ubi->ubi_num, "Can't update RC. No lookuptbl"); for (i = 0; i < len; i++) { uint8_t c = ((uint8_t *)buf)[i]; uint8_t c1 = ((uint8_t *)buf1)[i]; Loading Loading @@ -1459,16 +1437,6 @@ int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) err, len, pnum, offset, read); goto error; } if (ubi->lookuptbl && ubi->lookuptbl[pnum]) { if (ubi->lookuptbl[pnum]->rc < UBI_MAX_READCOUNTER) ubi->lookuptbl[pnum]->rc++; else ubi_err(ubi->ubi_num, "read counter overflow at PEB %d, RC %d", pnum, ubi->lookuptbl[pnum]->rc); } else ubi_err(ubi->ubi_num, "Can't update RC. No lookuptbl"); err = ubi_check_pattern(buf, 0xFF, len); if (err == 0) { Loading
drivers/mtd/ubi/ubi.h +1 −23 Original line number Diff line number Diff line Loading @@ -96,16 +96,6 @@ */ #define UBI_RD_THRESHOLD 100000 /* * This is the default read counter to be assigned to blocks lacking * read counter value on attach. The value was choosen as mean between * just_erased_block (rc = 0) and needs_scrubbibg_block * (rc = UBI_RD_THRESHOLD). On the one hand we don't want to miss * blocks that needs scrubbing but on the other, we dont want to * abuse scrubbing. */ #define UBI_DEF_RD_THRESHOLD (UBI_RD_THRESHOLD / 2) /* * This parameter defines the maximun interval (in days) between two * erasures of an eraseblock. When this interval is reached, UBI starts Loading @@ -114,9 +104,6 @@ */ #define UBI_DT_THRESHOLD 120 /* Used when calculaing the lats erase timestamp of a PEB */ #define NUM_SEC_IN_DAY (60*60*24) /* * The UBI debugfs directory name pattern and maximum name length (3 for "ubi" * + 2 for the number plus 1 for the trailing zero byte. Loading Loading @@ -736,11 +723,6 @@ struct ubi_ainf_volume { * @ec_count: a temporary variable used when calculating @mean_ec * @failed_fm: set to true if fm faound invalid during attach * @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects * @mean_last_erase_time: mean late erase timestamp value * @last_erase_time_sum: temporary variable, used to calculate * @mean_last_erase_time * @last_erase_time_count: temporary variable, used to calculate * @mean_last_erase_time * * This data structure contains the result of attaching an MTD device and may * be used by other UBI sub-systems to build final UBI data structures, further Loading Loading @@ -768,9 +750,6 @@ struct ubi_attach_info { int ec_count; int failed_fm; struct kmem_cache *aeb_slab_cache; long long mean_last_erase_time; long long last_erase_time_sum; int last_erase_time_count; }; /** Loading Loading @@ -811,8 +790,7 @@ extern struct blocking_notifier_head ubi_notifiers; /* attach.c */ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, int ec, long last_erase_time, long rc, const struct ubi_vid_hdr *vid_hdr, int bitflips); int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips); struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, int vol_id); void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); Loading