Linux-mtd Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] UBI: fix ubi.mtd MODULE_PARM_DESC issues and add per-device wear-leveling threshold
@ 2026-07-23  2:02 Ran Hongyun
  2026-07-23  2:02 ` [PATCH 1/2] UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC Ran Hongyun
  2026-07-23  2:02 ` [PATCH 2/2] UBI: support per-device wear-leveling threshold Ran Hongyun
  0 siblings, 2 replies; 9+ messages in thread
From: Ran Hongyun @ 2026-07-23  2:02 UTC (permalink / raw)
  To: richard, miquel.raynal, vigneshr, vapier, artem.bityutskiy
  Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

This series adds a per-device wear-leveling threshold for UBI devices,
with a preparatory fix to the MODULE_PARM_DESC.

Patch 1 fixes two pre-existing issues in the ubi.mtd MODULE_PARM_DESC:
the parameter format string was missing the enable_fm and need_resv_pool
tokens, and the bad-block reservation note was misplaced after Example 5
instead of after Example 3.

Patch 2 extends struct ubi_attach_req with a __s32 wl_threshold field, 
plumbs it through the ioctl and module parameter paths, and replaces 
the compile-time macros UBI_WL_THRESHOLD and WL_FREE_MAX_DIFF with p
er-device fields across wl.c and fastmap-wl.c. 0 means "use the kernel 
default", the accepted range is 2-65536.

Ran Hongyun (2):
  UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC
  UBI: support per-device wear-leveling threshold

 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(-)

-- 
2.52.0


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/2] UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC
  2026-07-23  2:02 [PATCH 0/2] UBI: fix ubi.mtd MODULE_PARM_DESC issues and add per-device wear-leveling threshold Ran Hongyun
@ 2026-07-23  2:02 ` Ran Hongyun
  2026-07-23  2:40   ` Zhihao Cheng
  2026-07-23  2:02 ` [PATCH 2/2] UBI: support per-device wear-leveling threshold Ran Hongyun
  1 sibling, 1 reply; 9+ messages in thread
From: Ran Hongyun @ 2026-07-23  2:02 UTC (permalink / raw)
  To: richard, miquel.raynal, vigneshr, vapier, artem.bityutskiy
  Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

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 <ranhongyun1@huawei.com>
---
 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)
 }
 
 module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400);
-MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num]]].\n"
+MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,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 the MTD character device node.\n"
 		      "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n"
@@ -1587,9 +1587,9 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa
 		      "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n"
 		      "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n"
 		      "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n"
+		      "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).\n"
 		      "Example 4: mtd=/dev/mtd1,0,0,5 - attach MTD device /dev/mtd1 to UBI 5 and using default values for the other fields.\n"
-		      "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n"
-		      "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).");
+		      "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n");
 #ifdef CONFIG_MTD_UBI_FASTMAP
 module_param(fm_autoconvert, bool, 0644);
 MODULE_PARM_DESC(fm_autoconvert, "Set this parameter to enable fastmap automatically on images without a fastmap.");
-- 
2.52.0


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] UBI: support per-device wear-leveling threshold
  2026-07-23  2:02 [PATCH 0/2] UBI: fix ubi.mtd MODULE_PARM_DESC issues and add per-device wear-leveling threshold Ran Hongyun
  2026-07-23  2:02 ` [PATCH 1/2] UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC Ran Hongyun
@ 2026-07-23  2:02 ` Ran Hongyun
  2026-07-23  3:01   ` Zhihao Cheng
                     ` (2 more replies)
  1 sibling, 3 replies; 9+ messages in thread
From: Ran Hongyun @ 2026-07-23  2:02 UTC (permalink / raw)
  To: richard, miquel.raynal, vigneshr, vapier, artem.bityutskiy
  Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

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=0,0,0,0,0,0,256  ubi.mtd=1,0,0,0,0,0,4096

0 means "use the kernel default", the accepted range is
2-65536.

Signed-off-by: Ran Hongyun <ranhongyun1@huawei.com>
---
 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
 
 /* Maximum number of comma-separated items in the 'mtd=' parameter */
-#define MTD_PARAM_MAX_COUNT 6
+#define MTD_PARAM_MAX_COUNT 7
 
 /* 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_THRESHOLD
  */
 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;
 };
 
 /* Numbers of elements set in the @mtd_dev_param array */
@@ -832,6 +834,8 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
  * @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 number
  * 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_id)
  */
 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_num,
 	if (!max_beb_per1024)
 		max_beb_per1024 = CONFIG_MTD_UBI_BEB_LIMIT;
 
+	if (!wl_threshold)
+		wl_threshold = 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_num,
 	ubi->ubi_num = ubi_num;
 	ubi->vid_hdr_offset = vid_hdr_offset;
 	ubi->autoresize_vol_id = -1;
+	ubi->wl_threshold = wl_threshold;
+	ubi->wl_free_max_diff = wl_threshold * 2;
 
 #ifdef CONFIG_MTD_UBI_FASTMAP
 	ubi->fm_pool.used = ubi->fm_pool.size = 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 sequence 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)
 
 	/* called while holding mtd_table_mutex */
 	mutex_lock_nested(&ubi_devices_mutex, SINGLE_DEPTH_NESTING);
-	err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false, false);
+	err = 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 = ubi_attach_mtd_dev(mtd, p->ubi_num,
 					 p->vid_hdr_offs, p->max_beb_per1024,
 					 p->enable_fm == 0,
-					 p->need_resv_pool != 0);
+					 p->need_resv_pool != 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, const struct kernel_param *kp)
 	} else
 		p->need_resv_pool = 0;
 
+	token = tokens[6];
+	if (token) {
+		int err = 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 = 0;
+
 	mtd_devs += 1;
 	return 0;
 }
 
 module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400);
-MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num[,enable_fm[,need_resv_pool]]]]].\n"
+MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,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 the MTD character device node.\n"
 		      "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n"
@@ -1589,7 +1617,8 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa
 		      "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n"
 		      "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).\n"
 		      "Example 4: mtd=/dev/mtd1,0,0,5 - attach MTD device /dev/mtd1 to UBI 5 and using default values for the other fields.\n"
-		      "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n");
+		      "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n"
+		      "Example 6: mtd=/dev/mtd0,0,0,0,0,0,256 mtd=/dev/mtd1,0,0,0,0,0,4096 - attach MTD device /dev/mtd0 with wear-leveling threshold 256, and MTD device /dev/mtd1 with threshold 4096.\n");
 #ifdef CONFIG_MTD_UBI_FASTMAP
 module_param(fm_autoconvert, bool, 0644);
 MODULE_PARM_DESC(fm_autoconvert, "Set this parameter to enable fastmap automatically on images without a fastmap.");
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index fd39030dbf89..54acd8394d67 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -1112,7 +1112,7 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
 		mutex_lock(&ubi_devices_mutex);
 		err = ubi_attach_mtd_dev(mtd, req.ubi_num, req.vid_hdr_offset,
 					 req.max_beb_per1024, !!req.disable_fm,
-					 !!req.need_resv_pool);
+					 !!req.need_resv_pool, req.wl_threshold);
 		mutex_unlock(&ubi_devices_mutex);
 		if (err < 0)
 			put_mtd_device(mtd);
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
index a0f750411f9d..e24bb6b18e90 100644
--- a/drivers/mtd/ubi/fastmap-wl.c
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -238,7 +238,7 @@ void ubi_refill_pools_and_lock(struct ubi_device *ubi)
 			if (left_free <= 0)
 				break;
 
-			e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF,
+			e = 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 = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
+		e = find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, 0);
 		ec = e->ec;
 	} else {
 		ec = e->ec;
 		if (ubi->free.rb_node) {
-			e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
+			e = find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, 0);
 			ec = max(ec, e->ec);
 		}
 	}
 	e = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb);
 
-	return ec - e->ec >= UBI_WL_THRESHOLD;
+	return ec - e->ec >= ubi->wl_threshold;
 }
 
 /* get_peb_for_wl - returns a PEB to be used internally by the WL sub-system.
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-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 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;
 
 	/* 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 pnum,
 /* 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
 
-/*
- * 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.
- */
-#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 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.
- */
-#define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD)
-
 /*
  * Maximum number of consecutive background thread failures which is enough to
  * switch to read-only mode.
@@ -358,7 +337,7 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *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 ubi_device *ubi,
 	first = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
 	last = rb_entry(rb_last(root), struct ubi_wl_entry, u.rb);
 
-	if (last->ec - first->ec < WL_FREE_MAX_DIFF) {
+	if (last->ec - first->ec < ubi->wl_free_max_diff) {
 		e = rb_entry(root->rb_node, struct ubi_wl_entry, u.rb);
 
 		/*
@@ -379,7 +358,7 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct ubi_device *ubi,
 		 */
 		e = may_reserve_for_fm(ubi, e, root);
 	} else
-		e = find_wl_entry(ubi, root, WL_FREE_MAX_DIFF/2, 0);
+		e = find_wl_entry(ubi, root, ubi->wl_free_max_diff/2, 0);
 
 	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 = find_anchor_wl_entry(&ubi->used);
 	if (e1 && ubi->fm_anchor &&
-	    (ubi->fm_anchor->ec - e1->ec >= UBI_WL_THRESHOLD)) {
+	    (ubi->fm_anchor->ec - e1->ec >= ubi->wl_threshold)) {
 		ubi->fm_do_produce_anchor = 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;
 
-		if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD)) {
+		if (!(e2->ec - e1->ec >= ubi->wl_threshold)) {
 			dbg_wl("no WL needed: min used EC %d, max free EC %d",
 			       e1->ec, e2->ec);
 
@@ -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 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb);
-		e2 = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
+		e2 = find_wl_entry(ubi, &ubi->free, ubi->wl_free_max_diff, 0);
 
-		if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD))
+		if (!(e2->ec - e1->ec >= 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;
 
-	e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF, 0);
+	e = 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 >= 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 module
  * 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 and 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];
 };
 
 /*
-- 
2.52.0


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC
  2026-07-23  2:02 ` [PATCH 1/2] UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC Ran Hongyun
@ 2026-07-23  2:40   ` Zhihao Cheng
  0 siblings, 0 replies; 9+ messages in thread
From: Zhihao Cheng @ 2026-07-23  2:40 UTC (permalink / raw)
  To: Ran Hongyun, richard, miquel.raynal, vigneshr, vapier,
	artem.bityutskiy
  Cc: linux-mtd, linux-kernel, yangerkun, yi.zhang

在 2026/7/23 10:02, Ran Hongyun 写道:
> 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 <ranhongyun1@huawei.com>
> ---
>   drivers/mtd/ubi/build.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
> 

Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
> 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)
>   }
>   
>   module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400);
> -MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num]]].\n"
> +MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,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 the MTD character device node.\n"
>   		      "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n"
> @@ -1587,9 +1587,9 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa
>   		      "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n"
>   		      "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n"
>   		      "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n"
> +		      "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).\n"
>   		      "Example 4: mtd=/dev/mtd1,0,0,5 - attach MTD device /dev/mtd1 to UBI 5 and using default values for the other fields.\n"
> -		      "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n"
> -		      "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).");
> +		      "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n");
>   #ifdef CONFIG_MTD_UBI_FASTMAP
>   module_param(fm_autoconvert, bool, 0644);
>   MODULE_PARM_DESC(fm_autoconvert, "Set this parameter to enable fastmap automatically on images without a fastmap.");
> 


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] UBI: support per-device wear-leveling threshold
  2026-07-23  2:02 ` [PATCH 2/2] UBI: support per-device wear-leveling threshold Ran Hongyun
@ 2026-07-23  3:01   ` Zhihao Cheng
  2026-07-23  6:06   ` Ran Hongyun
  2026-07-23  8:16   ` Ran Hongyun
  2 siblings, 0 replies; 9+ messages in thread
From: Zhihao Cheng @ 2026-07-23  3:01 UTC (permalink / raw)
  To: Ran Hongyun, richard, miquel.raynal, vigneshr, vapier,
	artem.bityutskiy
  Cc: linux-mtd, linux-kernel, yangerkun, yi.zhang

在 2026/7/23 10:02, Ran Hongyun 写道:
> 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=0,0,0,0,0,0,256  ubi.mtd=1,0,0,0,0,0,4096
> 
> 0 means "use the kernel default", the accepted range is
> 2-65536.
> 
> Signed-off-by: Ran Hongyun <ranhongyun1@huawei.com>
> ---
>   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(-)
> 

Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] UBI: support per-device wear-leveling threshold
  2026-07-23  2:02 ` [PATCH 2/2] UBI: support per-device wear-leveling threshold Ran Hongyun
  2026-07-23  3:01   ` Zhihao Cheng
@ 2026-07-23  6:06   ` Ran Hongyun
  2026-07-23  7:19     ` Richard Weinberger
  2026-07-23  8:16   ` Ran Hongyun
  2 siblings, 1 reply; 9+ messages in thread
From: Ran Hongyun @ 2026-07-23  6:06 UTC (permalink / raw)
  To: ranhongyun1
  Cc: artem.bityutskiy, chengzhihao1, linux-kernel, linux-mtd,
	miquel.raynal, richard, vapier, vigneshr, yangerkun, yi.zhang

Reply to the issues raised by sashiko: The struct size is unchanged,
and all existing userspace programs zero-initialize the struct
ubi_attach_req, so wl_threshold reads as zero and falls back to 
CONFIG_MTD_UBI_WL_THRESHOLD. No backward compatibility issue.

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] UBI: support per-device wear-leveling threshold
  2026-07-23  6:06   ` Ran Hongyun
@ 2026-07-23  7:19     ` Richard Weinberger
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Weinberger @ 2026-07-23  7:19 UTC (permalink / raw)
  To: Ran Hongyun
  Cc: Artem Bityutskiy, chengzhihao1, linux-kernel, linux-mtd,
	Miquel Raynal, vapier, Vignesh Raghavendra, yangerkun, yi zhang

----- Ursprüngliche Mail -----
> Von: "Ran Hongyun" <ranhongyun1@huawei.com>
> An: ranhongyun1@huawei.com
> CC: "Artem Bityutskiy" <artem.bityutskiy@linux.intel.com>, "chengzhihao1" <chengzhihao1@huawei.com>, "linux-kernel"
> <linux-kernel@vger.kernel.org>, "linux-mtd" <linux-mtd@lists.infradead.org>, "Miquel Raynal"
> <miquel.raynal@bootlin.com>, "richard" <richard@nod.at>, vapier@gentoo.org, "Vignesh Raghavendra" <vigneshr@ti.com>,
> "yangerkun" <yangerkun@huawei.com>, "yi zhang" <yi.zhang@huawei.com>
> Gesendet: Donnerstag, 23. Juli 2026 08:06:43
> Betreff: Re: [PATCH 2/2] UBI: support per-device wear-leveling threshold

> Reply to the issues raised by sashiko: The struct size is unchanged,
> and all existing userspace programs zero-initialize the struct
> ubi_attach_req, so wl_threshold reads as zero and falls back to
> CONFIG_MTD_UBI_WL_THRESHOLD. No backward compatibility issue.

I don't see Sashiko's mail. Where was it sent to?

Thanks,
//richard

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] UBI: support per-device wear-leveling threshold
  2026-07-23  2:02 ` [PATCH 2/2] UBI: support per-device wear-leveling threshold Ran Hongyun
  2026-07-23  3:01   ` Zhihao Cheng
  2026-07-23  6:06   ` Ran Hongyun
@ 2026-07-23  8:16   ` Ran Hongyun
  2026-07-23  8:30     ` Richard Weinberger
  2 siblings, 1 reply; 9+ messages in thread
From: Ran Hongyun @ 2026-07-23  8:16 UTC (permalink / raw)
  To: ranhongyun1
  Cc: artem.bityutskiy, chengzhihao1, linux-kernel, linux-mtd,
	miquel.raynal, richard, vapier, vigneshr, yangerkun, yi.zhang

Here is the link to Sashiko's comments https://sashiko.dev/#/message/20260723020233.3079997-3-ranhongyun1%40huawei.com

Thanks,
Ran Hongyun

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] UBI: support per-device wear-leveling threshold
  2026-07-23  8:16   ` Ran Hongyun
@ 2026-07-23  8:30     ` Richard Weinberger
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Weinberger @ 2026-07-23  8:30 UTC (permalink / raw)
  To: Ran Hongyun
  Cc: Artem Bityutskiy, chengzhihao1, linux-kernel, linux-mtd,
	Miquel Raynal, vapier, Vignesh Raghavendra, yangerkun, yi zhang

----- Ursprüngliche Mail -----
> Von: "Ran Hongyun" <ranhongyun1@huawei.com>
> An: "Ran Hongyun" <ranhongyun1@huawei.com>
> CC: "Artem Bityutskiy" <artem.bityutskiy@linux.intel.com>, "chengzhihao1" <chengzhihao1@huawei.com>, "linux-kernel"
> <linux-kernel@vger.kernel.org>, "linux-mtd" <linux-mtd@lists.infradead.org>, "Miquel Raynal"
> <miquel.raynal@bootlin.com>, "richard" <richard@nod.at>, "vapier" <vapier@gentoo.org>, "Vignesh Raghavendra"
> <vigneshr@ti.com>, "yangerkun" <yangerkun@huawei.com>, "yi zhang" <yi.zhang@huawei.com>
> Gesendet: Donnerstag, 23. Juli 2026 10:16:39
> Betreff: Re: [PATCH 2/2] UBI: support per-device wear-leveling threshold

> Here is the link to Sashiko's comments
> https://sashiko.dev/#/message/20260723020233.3079997-3-ranhongyun1%40huawei.com

I saw that but I expected it to send a mail :-)

Thanks,
//richard

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-07-23  8:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23  2:02 [PATCH 0/2] UBI: fix ubi.mtd MODULE_PARM_DESC issues and add per-device wear-leveling threshold Ran Hongyun
2026-07-23  2:02 ` [PATCH 1/2] UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC Ran Hongyun
2026-07-23  2:40   ` Zhihao Cheng
2026-07-23  2:02 ` [PATCH 2/2] UBI: support per-device wear-leveling threshold Ran Hongyun
2026-07-23  3:01   ` Zhihao Cheng
2026-07-23  6:06   ` Ran Hongyun
2026-07-23  7:19     ` Richard Weinberger
2026-07-23  8:16   ` Ran Hongyun
2026-07-23  8:30     ` Richard Weinberger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox