From nobody Fri Jul 24 05:22:28 2026 Received: from canpmsgout02.his.huawei.com (canpmsgout02.his.huawei.com [113.46.200.217]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AA0426A0B9 for ; Thu, 23 Jul 2026 02:11:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.217 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784772719; cv=none; b=a7y3Aqcin+EQGLNW+oOrT2nq4cHqpwWjSiJ9zeTMaL92iqZAqnWPmNdSvBQ8YmYlChmkWfNpL4vtX4tCIi4wY5K/mnOXIN173Edsx4XnZu5+hjyNoUxhqbkBMB4UNgR5QYjtouRK84EAxIT7E2tr13o7pcOPNBOxo26wmdnGY8o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784772719; c=relaxed/simple; bh=1JriCVdBA+mwh0hw8Pfu6P6zF79lTv0ZaQn4J3QjhWU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Mosy7arnrUfZfQEpYt3m6wlruAyaMnUTb8ok7PuNNP0abo74lYA0sryJI4GjMutkYAuiKJ7GORiu1FR2xZ7A8wu1IGPdA3KIhru4dGDfdY1+I3GYbwD4lP0SYhH1xWIfqTPzxoCG9mU8HBkwngxBI9D74Or5THW7/6c7JTXdab4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=DCbElVir; arc=none smtp.client-ip=113.46.200.217 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="DCbElVir" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=aYzr/QN7359G6aEH8C6fQiSsse3OttAwNAwOTYdQiIM=; b=DCbElVirdxLeX9orDR9zhZr6j3gJlNI2mKEpN8IP3clA6nUMJLEjM+uWh3vPIrnBzuS7T0Rau e6BrLtMjWTnWB52Td1I0XVohsWD8AdTMXlNDE6+qWBj707WDkcH9HwpycShq+JSywS+q3QWXVjn zJhAM0RJ4ZJqZ6kv4VZQWh4= Received: from mail.maildlp.com (unknown [172.19.162.197]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4h5DsC1rQbzcZyH; Thu, 23 Jul 2026 10:02:23 +0800 (CST) Received: from dggpemr200001.china.huawei.com (unknown [7.185.36.96]) by mail.maildlp.com (Postfix) with ESMTPS id 4EAEC4057D; Thu, 23 Jul 2026 10:11:53 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr200001.china.huawei.com (7.185.36.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 23 Jul 2026 10:11:52 +0800 From: Ran Hongyun To: , , , , CC: , , , , Subject: [PATCH 1/2] UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC Date: Thu, 23 Jul 2026 10:02:32 +0800 Message-ID: <20260723020233.3079997-2-ranhongyun1@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260723020233.3079997-1-ranhongyun1@huawei.com> References: <20260723020233.3079997-1-ranhongyun1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To dggpemr200001.china.huawei.com (7.185.36.96) Content-Type: text/plain; charset="utf-8" Fix two issues introduced before: - The parameter format string was missing the enable_fm and need_resv_pool tokens introduced in an earlier commit. - The bad-block reservation note was misplaced after Example 5 instead of after Example 3. It was misplaced due to an earlier patch. Fixes: 83ff59a06663 ("UBI: support ubi_num on mtd.ubi command line") Signed-off-by: Ran Hongyun Reviewed-by: Zhihao Cheng --- drivers/mtd/ubi/build.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 674ad87809df..8e5f178168cb 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -1574,7 +1574,7 @@ static int ubi_mtd_param_parse(const char *val, const= struct kernel_param *kp) } =20 module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400); -MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=3D[,[,max_beb_per1024[,ubi_num]]].\n" +MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=3D[,[,max_beb_per1024[,ubi_num[,enable_fm[,need_resv= _pool]]]]].\n" "Multiple \"mtd\" parameters may be specified.\n" "MTD devices may be specified by their number, name, or path to th= e MTD character device node.\n" "Optional \"vid_hdr_offs\" parameter specifies UBI VID header posi= tion to be used by UBI. (default value if 0)\n" @@ -1587,9 +1587,9 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Paramet= er format: mtd=3D; Thu, 23 Jul 2026 02:11:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784772720; cv=none; b=AtzkJBziv8kA05g3WNxMbmhTgvi2769QvDdC0rlboH9aM27u9xduf4CkqGaxJc611jqraSPhplD6lfp3u8sJ9c2r2wWUKRHNNQ7Iqd2KEVjjUykACB+0wOJ5TY/bCQ60fCt4+cruRyPQJkUkIm5VmbyocKHQCmmJ0Q7D0PWiJaM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784772720; c=relaxed/simple; bh=bgNeeqjKmX/xaAc7NyTSopN+nlqtJw6kTMIhZXEWOAo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iQSju0MIFceoYyGi41KKuMAcKX2cHcoBntXEwQn8ktMbFxWPlhMzfyaNQ3jhjvQsa0M3M1etmCOIgJT+fVC8F3xMM6oddH3I8Ux1rVNDFmt/tQq86R2TmUNrDhFtKuWewNT0Qs5KUUvL7xueWhuHj/W7P2BnbGmQDdggMIBGIhQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=HsKKhQwk; arc=none smtp.client-ip=113.46.200.216 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="HsKKhQwk" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=JqVTkYvB8QABU18J5BcqodZ9DlEBZ5e37d6moIjZeDE=; b=HsKKhQwkbo1YctVJ0rA+vghUcH7L0q+hf13HfkM3bd1oRDqU4lEbbiLin2HIBGLmCLRAXvaR4 mp8GnYdeLj/St+zyis3/DwVTDeCe5ajmDmIRXd8zLbF6cMSxtQUHULXSicNx/8hsCRCHtF1I0qE 2OISGM6LOpPrVJH4Vc0mwcc= Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4h5DsN3Gclz1T4GP; Thu, 23 Jul 2026 10:02:32 +0800 (CST) Received: from dggpemr200001.china.huawei.com (unknown [7.185.36.96]) by mail.maildlp.com (Postfix) with ESMTPS id 0BF112025F; Thu, 23 Jul 2026 10:11:54 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr200001.china.huawei.com (7.185.36.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 23 Jul 2026 10:11:53 +0800 From: Ran Hongyun To: , , , , CC: , , , , Subject: [PATCH 2/2] UBI: support per-device wear-leveling threshold Date: Thu, 23 Jul 2026 10:02:33 +0800 Message-ID: <20260723020233.3079997-3-ranhongyun1@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260723020233.3079997-1-ranhongyun1@huawei.com> References: <20260723020233.3079997-1-ranhongyun1@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500002.china.huawei.com (7.221.188.17) To dggpemr200001.china.huawei.com (7.185.36.96) Content-Type: text/plain; charset="utf-8" The UBI wear-leveling threshold (CONFIG_MTD_UBI_WL_THRESHOLD) is currently a compile-time constant shared by all UBI devices. When a single kernel image must support multiple NAND flashes with different erase lifetimes, one global threshold cannot suit all devices. Add a per-device configurable wl_threshold parameter: - UAPI: add __s32 wl_threshold to struct ubi_attach_req, carved from the existing padding. - Module parameter: ubi.mtd gains a new optional token "wl_threshold": ubi.mtd=3D0,0,0,0,0,0,256 ubi.mtd=3D1,0,0,0,0,0,4096 0 means "use the kernel default", the accepted range is 2-65536. Signed-off-by: Ran Hongyun Reviewed-by: Zhihao Cheng --- drivers/mtd/ubi/build.c | 43 ++++++++++++++++++++++++++++++------ drivers/mtd/ubi/cdev.c | 2 +- drivers/mtd/ubi/fastmap-wl.c | 8 +++---- drivers/mtd/ubi/ubi.h | 21 +++++++++++++++++- drivers/mtd/ubi/wl.c | 39 ++++++++------------------------ include/uapi/mtd/ubi-user.h | 10 ++++++++- 6 files changed, 79 insertions(+), 44 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 8e5f178168cb..ed0216f70220 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -36,7 +36,7 @@ #define MTD_PARAM_LEN_MAX 64 =20 /* Maximum number of comma-separated items in the 'mtd=3D' parameter */ -#define MTD_PARAM_MAX_COUNT 6 +#define MTD_PARAM_MAX_COUNT 7 =20 /* Maximum value for the number of bad PEBs per 1024 PEBs */ #define MAX_MTD_UBI_BEB_LIMIT 768 @@ -56,6 +56,7 @@ * @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs * @enable_fm: enable fastmap when value is non-zero * @need_resv_pool: reserve pool->max_size pebs when value is none-zero + * @wl_threshold: wear-leveling threshold, 0 means use CONFIG_MTD_UBI_WL_T= HRESHOLD */ struct mtd_dev_param { char name[MTD_PARAM_LEN_MAX]; @@ -64,6 +65,7 @@ struct mtd_dev_param { int max_beb_per1024; int enable_fm; int need_resv_pool; + int wl_threshold; }; =20 /* Numbers of elements set in the @mtd_dev_param array */ @@ -832,6 +834,8 @@ static int autoresize(struct ubi_device *ubi, int vol_i= d) * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs * @disable_fm: whether disable fastmap * @need_resv_pool: whether reserve pebs to fill fm_pool + * @wl_threshold: wear-leveling threshold for this UBI device; 0 means use + * %CONFIG_MTD_UBI_WL_THRESHOLD; accepted range is 2-65536 * * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num n= umber * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, = in @@ -848,7 +852,7 @@ static int autoresize(struct ubi_device *ubi, int vol_i= d) */ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset, int max_beb_per1024, bool disable_fm, - bool need_resv_pool) + bool need_resv_pool, int wl_threshold) { struct ubi_device *ubi; int i, err; @@ -859,6 +863,15 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_n= um, if (!max_beb_per1024) max_beb_per1024 =3D CONFIG_MTD_UBI_BEB_LIMIT; =20 + if (!wl_threshold) + wl_threshold =3D CONFIG_MTD_UBI_WL_THRESHOLD; + + if (wl_threshold < 2 || wl_threshold > 65536) { + pr_err("ubi: bad wear-leveling threshold %d\n", + wl_threshold); + return -EINVAL; + } + /* * Check if we already have the same MTD device attached. * @@ -944,6 +957,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_nu= m, ubi->ubi_num =3D ubi_num; ubi->vid_hdr_offset =3D vid_hdr_offset; ubi->autoresize_vol_id =3D -1; + ubi->wl_threshold =3D wl_threshold; + ubi->wl_free_max_diff =3D wl_threshold * 2; =20 #ifdef CONFIG_MTD_UBI_FASTMAP ubi->fm_pool.used =3D ubi->fm_pool.size =3D 0; @@ -1044,7 +1059,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_= num, ubi->vol_count - UBI_INT_VOL_COUNT, UBI_INT_VOL_COUNT, ubi->vtbl_slots); ubi_msg(ubi, "max/mean erase counter: %d/%d, WL threshold: %d, image sequ= ence number: %u", - ubi->max_ec, ubi->mean_ec, CONFIG_MTD_UBI_WL_THRESHOLD, + ubi->max_ec, ubi->mean_ec, ubi->wl_threshold, ubi->image_seq); ubi_msg(ubi, "available PEBs: %d, total reserved PEBs: %d, PEBs reserved = for bad PEB handling: %d", ubi->avail_pebs, ubi->rsvd_pebs, ubi->beb_rsvd_pebs); @@ -1247,7 +1262,7 @@ static void ubi_notify_add(struct mtd_info *mtd) =20 /* called while holding mtd_table_mutex */ mutex_lock_nested(&ubi_devices_mutex, SINGLE_DEPTH_NESTING); - err =3D ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false, false); + err =3D ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false, false, 0); mutex_unlock(&ubi_devices_mutex); if (err < 0) __put_mtd_device(mtd); @@ -1289,7 +1304,8 @@ static int __init ubi_init_attach(void) err =3D ubi_attach_mtd_dev(mtd, p->ubi_num, p->vid_hdr_offs, p->max_beb_per1024, p->enable_fm =3D=3D 0, - p->need_resv_pool !=3D 0); + p->need_resv_pool !=3D 0, + p->wl_threshold); mutex_unlock(&ubi_devices_mutex); if (err < 0) { pr_err("UBI error: cannot attach mtd%d\n", @@ -1569,12 +1585,24 @@ static int ubi_mtd_param_parse(const char *val, con= st struct kernel_param *kp) } else p->need_resv_pool =3D 0; =20 + token =3D tokens[6]; + if (token) { + int err =3D kstrtoint(token, 10, &p->wl_threshold); + + if (err) { + pr_err("UBI error: bad value for wl_threshold parameter: %s\n", + token); + return -EINVAL; + } + } else + p->wl_threshold =3D 0; + mtd_devs +=3D 1; return 0; } =20 module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400); -MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=3D[,[,max_beb_per1024[,ubi_num[,enable_fm[,need_resv= _pool]]]]].\n" +MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=3D[,[,max_beb_per1024[,ubi_num[,enable_fm[,need_resv= _pool[,wl_threshold]]]]]].\n" "Multiple \"mtd\" parameters may be specified.\n" "MTD devices may be specified by their number, name, or path to th= e MTD character device node.\n" "Optional \"vid_hdr_offs\" parameter specifies UBI VID header posi= tion to be used by UBI. (default value if 0)\n" @@ -1589,7 +1617,8 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Paramet= er format: mtd=3Dfree, WL_FREE_MAX_DIFF, + e =3D find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, !can_fill_pools(ubi, left_free)); self_check_in_wl_tree(ubi, e, &ubi->free); rb_erase(&e->u.rb, &ubi->free); @@ -392,18 +392,18 @@ static bool need_wear_leveling(struct ubi_device *ubi) if (!e) { if (!ubi->free.rb_node) return false; - e =3D find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0); + e =3D find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, 0); ec =3D e->ec; } else { ec =3D e->ec; if (ubi->free.rb_node) { - e =3D find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0); + e =3D find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, 0); ec =3D max(ec, e->ec); } } e =3D rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb); =20 - return ec - e->ec >=3D UBI_WL_THRESHOLD; + return ec - e->ec >=3D ubi->wl_threshold; } =20 /* get_peb_for_wl - returns a PEB to be used internally by the WL sub-syst= em. diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index af466cd83ae0..62026931d05e 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -516,6 +516,22 @@ struct ubi_debug_info { * @bgt_thread: background thread description object * @thread_enabled: if the background thread is enabled * @bgt_name: background thread name + * @wl_threshold: Maximum difference between two erase counters. If this + * threshold is exceeded, the WL sub-system starts moving + * data from used physical eraseblocks with low erase + * counter to free physical eraseblocks with high erase counter. + * @wl_free_max_diff: When a physical eraseblock is moved, the WL sub-syst= em + * has to pick the target physical eraseblock to move to. + * The simplest way would be just to pick the one with the + * highest erase counter. But in certain workloads this + * could lead to an unlimited wear of one or few physical + * eraseblock. Indeed, imagine a situation when the picked + * physical eraseblock is constantly erased after the + * data is written to it. So, we have a constant which + * limits the highest erase counter of the free physical + * eraseblock to pick. Namely, the WL sub-system does not + * pick eraseblocks with erase counter greater than the + * lowest erase counter plus @wl_free_max_diff. * * @flash_size: underlying MTD device size (in bytes) * @peb_count: count of physical eraseblocks on the MTD device @@ -623,6 +639,8 @@ struct ubi_device { struct task_struct *bgt_thread; int thread_enabled; char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2]; + int wl_threshold; + int wl_free_max_diff; =20 /* I/O sub-system's stuff */ long long flash_size; @@ -938,7 +956,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pn= um, /* build.c */ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset, int max_beb_per1024, - bool disable_fm, bool need_resv_pool); + bool disable_fm, bool need_resv_pool, + int wl_threshold); int ubi_detach_mtd_dev(int ubi_num, int anyway); struct ubi_device *ubi_get_device(int ubi_num); void ubi_put_device(struct ubi_device *ubi); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index e3705db8e570..4e18044a20c0 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -95,27 +95,6 @@ /* Number of physical eraseblocks reserved for wear-leveling purposes */ #define WL_RESERVED_PEBS 1 =20 -/* - * Maximum difference between two erase counters. If this threshold is - * exceeded, the WL sub-system starts moving data from used physical - * eraseblocks with low erase counter to free physical eraseblocks with hi= gh - * erase counter. - */ -#define UBI_WL_THRESHOLD CONFIG_MTD_UBI_WL_THRESHOLD - -/* - * When a physical eraseblock is moved, the WL sub-system has to pick the = target - * physical eraseblock to move to. The simplest way would be just to pick = the - * one with the highest erase counter. But in certain workloads this could= lead - * to an unlimited wear of one or few physical eraseblock. Indeed, imagine= a - * situation when the picked physical eraseblock is constantly erased afte= r the - * data is written to it. So, we have a constant which limits the highest = erase - * counter of the free physical eraseblock to pick. Namely, the WL sub-sys= tem - * does not pick eraseblocks with erase counter greater than the lowest er= ase - * counter plus %WL_FREE_MAX_DIFF. - */ -#define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD) - /* * Maximum number of consecutive background thread failures which is enoug= h to * switch to read-only mode. @@ -358,7 +337,7 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_de= vice *ubi, * * This function looks for a wear leveling entry with medium erase counter, * but not greater or equivalent than the lowest erase counter plus - * %WL_FREE_MAX_DIFF/2. + * @ubi->wl_free_max_diff/2. */ static struct ubi_wl_entry *find_mean_wl_entry(struct ubi_device *ubi, struct rb_root *root) @@ -368,7 +347,7 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct u= bi_device *ubi, first =3D rb_entry(rb_first(root), struct ubi_wl_entry, u.rb); last =3D rb_entry(rb_last(root), struct ubi_wl_entry, u.rb); =20 - if (last->ec - first->ec < WL_FREE_MAX_DIFF) { + if (last->ec - first->ec < ubi->wl_free_max_diff) { e =3D rb_entry(root->rb_node, struct ubi_wl_entry, u.rb); =20 /* @@ -379,7 +358,7 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct u= bi_device *ubi, */ e =3D may_reserve_for_fm(ubi, e, root); } else - e =3D find_wl_entry(ubi, root, WL_FREE_MAX_DIFF/2, 0); + e =3D find_wl_entry(ubi, root, ubi->wl_free_max_diff/2, 0); =20 return e; } @@ -706,7 +685,7 @@ static int wear_leveling_worker(struct ubi_device *ubi,= struct ubi_work *wrk, #ifdef CONFIG_MTD_UBI_FASTMAP e1 =3D find_anchor_wl_entry(&ubi->used); if (e1 && ubi->fm_anchor && - (ubi->fm_anchor->ec - e1->ec >=3D UBI_WL_THRESHOLD)) { + (ubi->fm_anchor->ec - e1->ec >=3D ubi->wl_threshold)) { ubi->fm_do_produce_anchor =3D 1; /* * fm_anchor is no longer considered a good anchor. @@ -743,7 +722,7 @@ static int wear_leveling_worker(struct ubi_device *ubi,= struct ubi_work *wrk, if (!e2) goto out_cancel; =20 - if (!(e2->ec - e1->ec >=3D UBI_WL_THRESHOLD)) { + if (!(e2->ec - e1->ec >=3D ubi->wl_threshold)) { dbg_wl("no WL needed: min used EC %d, max free EC %d", e1->ec, e2->ec); =20 @@ -1056,12 +1035,12 @@ static int ensure_wear_leveling(struct ubi_device *= ubi, int nested) * We schedule wear-leveling only if the difference between the * lowest erase counter of used physical eraseblocks and a high * erase counter of free physical eraseblocks is greater than - * %UBI_WL_THRESHOLD. + * @ubi->wl_threshold. */ e1 =3D rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb); - e2 =3D find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0); + e2 =3D find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, 0); =20 - if (!(e2->ec - e1->ec >=3D UBI_WL_THRESHOLD)) + if (!(e2->ec - e1->ec >=3D ubi->wl_threshold)) goto out_unlock; #endif dbg_wl("schedule wear-leveling"); @@ -2090,7 +2069,7 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi= _device *ubi) { struct ubi_wl_entry *e; =20 - e =3D find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0); + e =3D find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, 0); self_check_in_wl_tree(ubi, e, &ubi->free); ubi->free_count--; ubi_assert(ubi->free_count >=3D 0); diff --git a/include/uapi/mtd/ubi-user.h b/include/uapi/mtd/ubi-user.h index aa872a41ffb9..3538e11b5175 100644 --- a/include/uapi/mtd/ubi-user.h +++ b/include/uapi/mtd/ubi-user.h @@ -289,6 +289,13 @@ enum { * If @disable_fm is not zero, ubi doesn't create new fastmap even the mod= ule * param 'fm_autoconvert' is set, and existed old fastmap will be destroyed * after doing full scanning. + * + * The @wl_threshold defines the maximum difference between the highest an= d the + * lowest erase counter value of eraseblocks of this UBI device. When this + * threshold is exceeded, UBI starts performing wear leveling by means of + * moving data from eraseblock with low erase counter to eraseblocks with = high + * erase counter. If @wl_threshold is zero, the default kernel value of + * %CONFIG_MTD_UBI_WL_THRESHOLD is used. The accepted range is 2-65536. */ struct ubi_attach_req { __s32 ubi_num; @@ -297,7 +304,8 @@ struct ubi_attach_req { __s16 max_beb_per1024; __s8 disable_fm; __s8 need_resv_pool; - __s8 padding[8]; + __s32 wl_threshold; + __s8 padding[4]; }; =20 /* --=20 2.52.0