]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mtd/ubi/scan.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / mtd / ubi / scan.c
index 29c41eeb09fe2c82523d877d020af5238d1c8f77..96d410e106ab1cb72cf9f6bda211e756eaa8c98d 100644 (file)
 
 #include <linux/err.h>
 #include <linux/crc32.h>
+#include <asm/div64.h>
 #include "ubi.h"
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-static int paranoid_check_si(const struct ubi_device *ubi,
-                            struct ubi_scan_info *si);
+static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
 #else
 #define paranoid_check_si(ubi, si) 0
 #endif
@@ -92,27 +92,6 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
        return 0;
 }
 
-/**
- * commit_to_mean_value - commit intermediate results to the final mean erase
- * counter value.
- * @si: scanning information
- *
- * This is a helper function which calculates partial mean erase counter mean
- * value and adds it to the resulting mean value. As we can work only in
- * integer arithmetic and we want to calculate the mean value of erase counter
- * accurately, we first sum erase counter values in @si->ec_sum variable and
- * count these components in @si->ec_count. If this temporary @si->ec_sum is
- * going to overflow, we calculate the partial mean value
- * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec.
- */
-static void commit_to_mean_value(struct ubi_scan_info *si)
-{
-       si->ec_sum /= si->ec_count;
-       if (si->ec_sum % si->ec_count >= si->ec_count / 2)
-               si->mean_ec += 1;
-       si->mean_ec += si->ec_sum;
-}
-
 /**
  * validate_vid_hdr - check that volume identifier header is correct and
  * consistent.
@@ -259,14 +238,13 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
  *     o bit 2 is cleared: the older LEB is not corrupted;
  *     o bit 2 is set: the older LEB is corrupted.
  */
-static int compare_lebs(const struct ubi_device *ubi,
-                       const struct ubi_scan_leb *seb, int pnum,
-                       const struct ubi_vid_hdr *vid_hdr)
+static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
+                       int pnum, const struct ubi_vid_hdr *vid_hdr)
 {
        void *buf;
        int len, err, second_is_newer, bitflips = 0, corrupted = 0;
        uint32_t data_crc, crc;
-       struct ubi_vid_hdr *vidh = NULL;
+       struct ubi_vid_hdr *vh = NULL;
        unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
 
        if (seb->sqnum == 0 && sqnum2 == 0) {
@@ -288,9 +266,14 @@ static int compare_lebs(const struct ubi_device *ubi,
                 * FIXME: but this is anyway obsolete and will be removed at
                 * some point.
                 */
-
                dbg_bld("using old crappy leb_ver stuff");
 
+               if (v1 == v2) {
+                       ubi_err("PEB %d and PEB %d have the same version %lld",
+                               seb->pnum, pnum, v1);
+                       return -EINVAL;
+               }
+
                abs = v1 - v2;
                if (abs < 0)
                        abs = -abs;
@@ -323,11 +306,11 @@ static int compare_lebs(const struct ubi_device *ubi,
        } else {
                pnum = seb->pnum;
 
-               vidh = ubi_zalloc_vid_hdr(ubi);
-               if (!vidh)
+               vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
+               if (!vh)
                        return -ENOMEM;
 
-               err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
+               err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
                if (err) {
                        if (err == UBI_IO_BITFLIPS)
                                bitflips = 1;
@@ -341,7 +324,7 @@ static int compare_lebs(const struct ubi_device *ubi,
                        }
                }
 
-               if (!vidh->copy_flag) {
+               if (!vh->copy_flag) {
                        /* It is not a copy, so it is newer */
                        dbg_bld("first PEB %d is newer, copy_flag is unset",
                                pnum);
@@ -349,7 +332,7 @@ static int compare_lebs(const struct ubi_device *ubi,
                        goto out_free_vidh;
                }
 
-               vid_hdr = vidh;
+               vid_hdr = vh;
        }
 
        /* Read the data of the copy and check the CRC */
@@ -379,7 +362,7 @@ static int compare_lebs(const struct ubi_device *ubi,
        }
 
        vfree(buf);
-       ubi_free_vid_hdr(ubi, vidh);
+       ubi_free_vid_hdr(ubi, vh);
 
        if (second_is_newer)
                dbg_bld("second PEB %d is newer, copy_flag is set", pnum);
@@ -391,8 +374,7 @@ static int compare_lebs(const struct ubi_device *ubi,
 out_free_buf:
        vfree(buf);
 out_free_vidh:
-       ubi_free_vid_hdr(ubi, vidh);
-       ubi_assert(err < 0);
+       ubi_free_vid_hdr(ubi, vh);
        return err;
 }
 
@@ -413,7 +395,7 @@ out_free_vidh:
  * to be picked, while the older one has to be dropped. This function returns
  * zero in case of success and a negative error code in case of failure.
  */
-int ubi_scan_add_used(const struct ubi_device *ubi, struct ubi_scan_info *si,
+int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                      int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
                      int bitflips)
 {
@@ -667,16 +649,12 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
  * function returns zero in case of success and a negative error code in case
  * of failure.
  */
-int ubi_scan_erase_peb(const struct ubi_device *ubi,
-                      const struct ubi_scan_info *si, int pnum, int ec)
+int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
+                      int pnum, int ec)
 {
        int err;
        struct ubi_ec_hdr *ec_hdr;
 
-       ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
-       if (!ec_hdr)
-               return -ENOMEM;
-
        if ((long long)ec >= UBI_MAX_ERASECOUNTER) {
                /*
                 * Erase counter overflow. Upgrade UBI and use 64-bit
@@ -686,6 +664,10 @@ int ubi_scan_erase_peb(const struct ubi_device *ubi,
                return -EINVAL;
        }
 
+       ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+       if (!ec_hdr)
+               return -ENOMEM;
+
        ec_hdr->ec = cpu_to_be64(ec);
 
        err = ubi_io_sync_erase(ubi, pnum, 0);
@@ -712,7 +694,7 @@ out_free:
  * This function returns scanning physical eraseblock information in case of
  * success and an error code in case of failure.
  */
-struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
+struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
                                           struct ubi_scan_info *si)
 {
        int err = 0, i;
@@ -771,7 +753,7 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(const struct ubi_device *ubi,
  */
 static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum)
 {
-       long long ec;
+       long long uninitialized_var(ec);
        int err, bitflips = 0, vol_id, ec_corr = 0;
 
        dbg_bld("scan PEB %d", pnum);
@@ -856,7 +838,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
        }
 
        vol_id = be32_to_cpu(vidh->vol_id);
-       if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOL_ID) {
+       if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) {
                int lnum = be32_to_cpu(vidh->lnum);
 
                /* Unsupported internal volume */
@@ -899,15 +881,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum
 
 adjust_mean_ec:
        if (!ec_corr) {
-               if (si->ec_sum + ec < ec) {
-                       commit_to_mean_value(si);
-                       si->ec_sum = 0;
-                       si->ec_count = 0;
-               } else {
-                       si->ec_sum += ec;
-                       si->ec_count += 1;
-               }
-
+               si->ec_sum += ec;
+               si->ec_count += 1;
                if (ec > si->max_ec)
                        si->max_ec = ec;
                if (ec < si->min_ec)
@@ -948,7 +923,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
        if (!ech)
                goto out_si;
 
-       vidh = ubi_zalloc_vid_hdr(ubi);
+       vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
        if (!vidh)
                goto out_ech;
 
@@ -963,9 +938,11 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
 
        dbg_msg("scanning is finished");
 
-       /* Finish mean erase counter calculations */
-       if (si->ec_count)
-               commit_to_mean_value(si);
+       /* Calculate mean erase counter */
+       if (si->ec_count) {
+               do_div(si->ec_sum, si->ec_count);
+               si->mean_ec = si->ec_sum;
+       }
 
        if (si->is_empty)
                ubi_msg("empty MTD device detected");
@@ -1110,8 +1087,7 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
  * This function returns zero if the scanning information is all right, %1 if
  * not and a negative error code if an error occurred.
  */
-static int paranoid_check_si(const struct ubi_device *ubi,
-                            struct ubi_scan_info *si)
+static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
 {
        int pnum, err, vols_found = 0;
        struct rb_node *rb1, *rb2;