diff options
| author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-04-19 13:44:31 -0400 |
|---|---|---|
| committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-04-19 13:49:41 -0400 |
| commit | 4bc1dca4b0eb4dfbf100895bfc1256f21e3c901a (patch) | |
| tree | 4ccfc207a0b55cfad4247f49bd1bce03d5034560 | |
| parent | cbd8a9d2cd6f576ca41022599341bbd8be1b0b27 (diff) | |
UBI: fix mean EC calculation
(a + b) / (c + d) != a / c + b / d. The old code errornously
assumed this incorrect formuld. Instead, just sum all erase
counters in a 64-bit variable and divide to the number of EBs
at the end.
Thanks to Adrian Hunter for pointing this out.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
| -rw-r--r-- | drivers/mtd/ubi/scan.c | 41 | ||||
| -rw-r--r-- | drivers/mtd/ubi/scan.h | 2 |
2 files changed, 9 insertions, 34 deletions
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 05aa3e7daba1..96d410e106ab 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | #include <linux/err.h> | 43 | #include <linux/err.h> |
| 44 | #include <linux/crc32.h> | 44 | #include <linux/crc32.h> |
| 45 | #include <asm/div64.h> | ||
| 45 | #include "ubi.h" | 46 | #include "ubi.h" |
| 46 | 47 | ||
| 47 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 48 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| @@ -92,27 +93,6 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, | |||
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | /** | 95 | /** |
| 95 | * commit_to_mean_value - commit intermediate results to the final mean erase | ||
| 96 | * counter value. | ||
| 97 | * @si: scanning information | ||
| 98 | * | ||
| 99 | * This is a helper function which calculates partial mean erase counter mean | ||
| 100 | * value and adds it to the resulting mean value. As we can work only in | ||
| 101 | * integer arithmetic and we want to calculate the mean value of erase counter | ||
| 102 | * accurately, we first sum erase counter values in @si->ec_sum variable and | ||
| 103 | * count these components in @si->ec_count. If this temporary @si->ec_sum is | ||
| 104 | * going to overflow, we calculate the partial mean value | ||
| 105 | * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec. | ||
| 106 | */ | ||
| 107 | static void commit_to_mean_value(struct ubi_scan_info *si) | ||
| 108 | { | ||
| 109 | si->ec_sum /= si->ec_count; | ||
| 110 | if (si->ec_sum % si->ec_count >= si->ec_count / 2) | ||
| 111 | si->mean_ec += 1; | ||
| 112 | si->mean_ec += si->ec_sum; | ||
| 113 | } | ||
| 114 | |||
| 115 | /** | ||
| 116 | * validate_vid_hdr - check that volume identifier header is correct and | 96 | * validate_vid_hdr - check that volume identifier header is correct and |
| 117 | * consistent. | 97 | * consistent. |
| 118 | * @vid_hdr: the volume identifier header to check | 98 | * @vid_hdr: the volume identifier header to check |
| @@ -901,15 +881,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum | |||
| 901 | 881 | ||
| 902 | adjust_mean_ec: | 882 | adjust_mean_ec: |
| 903 | if (!ec_corr) { | 883 | if (!ec_corr) { |
| 904 | if (si->ec_sum + ec < ec) { | 884 | si->ec_sum += ec; |
| 905 | commit_to_mean_value(si); | 885 | si->ec_count += 1; |
| 906 | si->ec_sum = 0; | ||
| 907 | si->ec_count = 0; | ||
| 908 | } else { | ||
| 909 | si->ec_sum += ec; | ||
| 910 | si->ec_count += 1; | ||
| 911 | } | ||
| 912 | |||
| 913 | if (ec > si->max_ec) | 886 | if (ec > si->max_ec) |
| 914 | si->max_ec = ec; | 887 | si->max_ec = ec; |
| 915 | if (ec < si->min_ec) | 888 | if (ec < si->min_ec) |
| @@ -965,9 +938,11 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) | |||
| 965 | 938 | ||
| 966 | dbg_msg("scanning is finished"); | 939 | dbg_msg("scanning is finished"); |
| 967 | 940 | ||
| 968 | /* Finish mean erase counter calculations */ | 941 | /* Calculate mean erase counter */ |
| 969 | if (si->ec_count) | 942 | if (si->ec_count) { |
| 970 | commit_to_mean_value(si); | 943 | do_div(si->ec_sum, si->ec_count); |
| 944 | si->mean_ec = si->ec_sum; | ||
| 945 | } | ||
| 971 | 946 | ||
| 972 | if (si->is_empty) | 947 | if (si->is_empty) |
| 973 | ubi_msg("empty MTD device detected"); | 948 | ubi_msg("empty MTD device detected"); |
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 46d444af471a..966b9b682a42 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h | |||
| @@ -124,7 +124,7 @@ struct ubi_scan_info { | |||
| 124 | int max_ec; | 124 | int max_ec; |
| 125 | unsigned long long max_sqnum; | 125 | unsigned long long max_sqnum; |
| 126 | int mean_ec; | 126 | int mean_ec; |
| 127 | int ec_sum; | 127 | uint64_t ec_sum; |
| 128 | int ec_count; | 128 | int ec_count; |
| 129 | }; | 129 | }; |
| 130 | 130 | ||
