@@ -828,6 +828,75 @@ static int rename_volumes(struct ubi_device *ubi,
return err;
}
+static int ubi_get_info(struct ubi_device *ubi, void __user *argp)
+{
+ struct ubi_ecinfo_res info;
+ struct ubi_wl_entry *wl;
+ int peb;
+ int ec_count = 0;
+ int ec_count_fastmap = 0;
+ uint64_t ec_sum = 0;
+ uint64_t ec_sum_fastmap = 0;
+ int max_ec = 0;
+ int max_ec_data = 0;
+#ifdef CONFIG_MTD_UBI_FASTMAP
+ const bool fastmap = true;
+#else
+ const bool fastmap = false;
+#endif
+ memset(&info, 0, sizeof(info));
+
+ for (peb = 0; peb < ubi->peb_count; peb++) {
+ int err;
+
+ /*
+ * We have looped through the fastmap blocks, lets store fastmap data if
+ * fastmap is enabled.
+ */
+ if (fastmap && peb == UBI_FM_MAX_START) {
+ ec_sum_fastmap = ec_sum;
+ ec_count_fastmap = ec_count;
+ info.mean_ec_fastmap = div_u64(ec_sum_fastmap, ec_count_fastmap);
+ info.max_ec_fastmap = max_ec;
+ }
+
+ err = ubi_io_is_bad(ubi, peb);
+ if (err)
+ continue;
+
+ spin_lock(&ubi->wl_lock);
+
+ wl = ubi->lookuptbl[peb];
+ if (wl) {
+ ec_sum += wl->ec;
+ ec_count++;
+
+ if (max_ec < wl->ec)
+ max_ec = wl->ec;
+ if (fastmap && (peb >= UBI_FM_MAX_START) && (max_ec_data < wl->ec))
+ max_ec_data = wl->ec;
+ }
+
+ spin_unlock(&ubi->wl_lock);
+ }
+
+ if (ec_count > 0) {
+ info.max_ec = max_ec;
+ info.mean_ec = div_u64(ec_sum, ec_count);
+
+ if (fastmap && (ec_count > ec_count_fastmap)) {
+ info.mean_ec_data = div_u64(ec_sum - ec_sum_fastmap,
+ ec_count - ec_count_fastmap);
+ info.max_ec_data = max_ec_data;
+ }
+ }
+
+ if (copy_to_user(argp, &info, sizeof(info)))
+ return -EFAULT;
+
+ return 0;
+}
+
static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -991,6 +1060,12 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
break;
}
+ case UBI_IOCECNFO:
+ {
+ err = ubi_get_info(ubi, argp);
+ break;
+ }
+
default:
err = -ENOTTY;
break;
Currently, only "max_ec" can be read from sysfs, which provides a limited view of the flash device’s wear. In certain cases, such as bugs in the wear-leveling algorithm, specific blocks can be worn down more than others, resulting in uneven wear distribution. Providing mean erase counter values give a better understanding of the overall flash wear. There exists more detailed info in debugfs, but this information is only available for debug builds. This patch calculates the mean and max values only when they are requested. This calculation typically takes 2.7 ms for an UBI device with 4091 blocks running on a single core Cortex-A9 at 792 MHz. Signed-off-by: Rickard Andersson <rickard.andersson@axis.com> --- drivers/mtd/ubi/cdev.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+)