From nobody Tue Feb 10 08:31:35 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (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 16BB7329E4F for ; Thu, 8 Jan 2026 16:59:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767891567; cv=none; b=apFR4zcXgJ5sMyBAw3GiX1oehKuiPKws8HRqXDdz+8GFxgUpJFnxLZOBry+OdmbOfWmV2qU1vHTUXrzNLSoa2gqe9DbzvnoOSzzkOP3WD/U46edJQfpqzvxJmX7/dZ8ZI2rbIXwaQaSqb/JD36qLte9V02RAI5k+BmsH4LR4SUU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767891567; c=relaxed/simple; bh=ml5YxbTBgMFTzn3cVlCcnkDfoHhrfOjsIhbYyWKZ60Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=R+m3Nzfwbg9eNbEkq3ihEoFeT5fo5WouX1YkYFQI/R236n/VpWvgUd74auL6KWcqbEsjHERlQ8e3kmtgyqvAmnaHtylIyYQu09pbMbH97BjLmlZ8Mo49/R4uCYRxiL0HvM9Eu6w2ENuXjHTOuFEdVXbahIwCnD9Hh824Cha1HSk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Pe8ITo45; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Pe8ITo45" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id BE8864E42000; Thu, 8 Jan 2026 16:59:24 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 93BCC6072B; Thu, 8 Jan 2026 16:59:24 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 5488E103C885C; Thu, 8 Jan 2026 17:59:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1767891563; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=5c8b+vAxWRpFsI1z94Obh+lca7KIQv9tXkU1B1za+2E=; b=Pe8ITo4526+onyk7T6qdJKDt5JDKJ+mksmehdsbLjqG5WOEhSfSCKZKK2iUDcaeG/bTmZa ZXT33rR1DkwQ5TU0kJBl4j7/VoKH4o7dMpGpke+njzsDK4Da7LrTXnZCb5ld46oVYMwZxW be3fA30FI4SXs7wk3tJKh+vjGennIVYZ2rs8IToVGSeuCfmpZK6OUBqTtqUQfY6KAGWxce NUKceGz2yz7AqkUYlSsnlPVuQaGaA2iaIva1DJP2exw7N9WYkFwcEyvWgfJ7ZjHEM3aPxO EkNmZTZFmeZ44hT9qDW90f4tJEtFOYk5awWn0qGqsGkXGifirQgOAVHfbnxQ1w== From: Miquel Raynal Date: Thu, 08 Jan 2026 17:57:50 +0100 Subject: [PATCH v2 17/27] mtd: spi-nor: debugfs: Add locking support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260108-winbond-v6-18-rc1-spi-nor-swp-v2-17-c462ef806130@bootlin.com> References: <20260108-winbond-v6-18-rc1-spi-nor-swp-v2-0-c462ef806130@bootlin.com> In-Reply-To: <20260108-winbond-v6-18-rc1-spi-nor-swp-v2-0-c462ef806130@bootlin.com> To: Tudor Ambarus , Pratyush Yadav , Michael Walle , Richard Weinberger , Vignesh Raghavendra , Jonathan Corbet Cc: Sean Anderson , Thomas Petazzoni , Steam Lin , linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 The ioctl output may be counter intuitive in some cases. Asking for a "locked status" over a region that is only partially locked will return "unlocked" whereas in practice maybe the biggest part is actually locked. Knowing what is the real software locking state through debugfs would be very convenient for development/debugging purposes, hence this proposal for adding an extra block at the end of the file: a "locked sectors" array which lists every section, if it is locked or not, showing both the address ranges and the sizes in numbers of blocks. Here is an example of output, what is after the "sector map" is new. $ cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef a0 20 00 00 00 size 64.0 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_16BIT_SR | HAS_S= R_TB_BIT6 | HAS_4BIT_BP | SOFT_RESET | NO_WP opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 8D extension none protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (64.0 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-03ffffff | [ 3] | no locked sectors region (in hex) | status | #blocks ------------------+----------+-------- 00000000-03ffffff | unlocked | 1024 Signed-off-by: Miquel Raynal --- Here are below more examples of output with various situations. The full output of the "params" content has been manually removed to only show what has been added and how it behaves. $ flash_lock -l /dev/mtd0 0x3f00000 16 $ cat /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #blocks ------------------+----------+-------- 00000000-03efffff | unlocked | 1008 03f00000-03ffffff | locked | 16 $ $ flash_lock -u /dev/mtd0 0x3f00000 8 $ cat /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #blocks ------------------+----------+-------- 00000000-03f7ffff | unlocked | 1016 03f80000-03ffffff | locked | 8 $ $ flash_lock -u /dev/mtd0 $ cat /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #blocks ------------------+----------+-------- 00000000-03ffffff | unlocked | 1024 $ $ flash_lock -l /dev/mtd0 $ cat /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #blocks ------------------+----------+-------- 00000000-03ffffff | locked | 1024 $ $ flash_lock -u /dev/mtd0 0x20000 1022 $ cat /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #blocks ------------------+----------+-------- 00000000-0001ffff | locked | 2 00020000-03ffffff | unlocked | 1022 --- drivers/mtd/spi-nor/core.h | 4 ++++ drivers/mtd/spi-nor/debugfs.c | 22 ++++++++++++++++++++++ drivers/mtd/spi-nor/swp.c | 11 +++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 091eb934abe4..99ed6c54b90f 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -707,6 +707,10 @@ static inline bool spi_nor_needs_sfdp(const struct spi= _nor *nor) return !nor->info->size; } =20 +u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor); +void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_t= *ofs, u64 *len); +bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len, const = u8 *sr); + #ifdef CONFIG_DEBUG_FS void spi_nor_debugfs_register(struct spi_nor *nor); void spi_nor_debugfs_shutdown(void); diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index d0191eb9f879..821fbc9587dc 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -77,10 +77,12 @@ static void spi_nor_print_flags(struct seq_file *s, uns= igned long flags, static int spi_nor_params_show(struct seq_file *s, void *data) { struct spi_nor *nor =3D s->private; + unsigned int min_prot_len =3D spi_nor_get_min_prot_length_sr(nor); struct spi_nor_flash_parameter *params =3D nor->params; struct spi_nor_erase_map *erase_map =3D ¶ms->erase_map; struct spi_nor_erase_region *region =3D erase_map->regions; const struct flash_info *info =3D nor->info; + loff_t lock_start, lock_length; char buf[16], *str; unsigned int i; =20 @@ -159,6 +161,26 @@ static int spi_nor_params_show(struct seq_file *s, voi= d *data) region[i].overlaid ? "yes" : "no"); } =20 + seq_puts(s, "\nlocked sectors\n"); + seq_puts(s, " region (in hex) | status | #blocks\n"); + seq_puts(s, " ------------------+----------+--------\n"); + + spi_nor_get_locked_range_sr(nor, nor->dfs_sr_cache, &lock_start, &lock_le= ngth); + if (!lock_length || lock_length =3D=3D params->size) { + seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, params->size - 1, + lock_length ? " locked" : "unlocked", params->size / min_prot_len); + } else if (!lock_start) { + seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, lock_length - 1, + " locked", lock_length / min_prot_len); + seq_printf(s, " %08llx-%08llx | %s | %llu\n", lock_length, params->size = - 1, + "unlocked", (params->size - lock_length) / min_prot_len); + } else { + seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, lock_start - 1, + "unlocked", lock_start / min_prot_len); + seq_printf(s, " %08llx-%08llx | %s | %llu\n", lock_start, params->size -= 1, + " locked", lock_length / min_prot_len); + } + return 0; } DEFINE_SHOW_ATTRIBUTE(spi_nor_params); diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c index 7a6c2b8ef921..8de8459e8e90 100644 --- a/drivers/mtd/spi-nor/swp.c +++ b/drivers/mtd/spi-nor/swp.c @@ -32,7 +32,7 @@ static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor) return SR_TB_BIT5; } =20 -static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor) +u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor) { unsigned int bp_slots, bp_slots_needed; /* @@ -53,8 +53,8 @@ static u64 spi_nor_get_min_prot_length_sr(struct spi_nor = *nor) return sector_size; } =20 -static void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr,= loff_t *ofs, - u64 *len) +void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_t= *ofs, + u64 *len) { u64 min_prot_len; u8 bp_mask =3D spi_nor_get_sr_bp_mask(nor); @@ -112,7 +112,7 @@ static bool spi_nor_check_lock_status_sr(struct spi_nor= *nor, loff_t ofs, return (ofs >=3D lock_offs_max) || (offs_max <=3D lock_offs); } =20 -static bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len,= const u8 *sr) +bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len, const = u8 *sr) { return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true); } @@ -410,6 +410,9 @@ static int spi_nor_sr_is_locked(struct spi_nor *nor, lo= ff_t ofs, u64 len) * -is_locked(): Checks if the region is *fully* locked, returns false oth= erwise. * This feeback may be misleading because users may get an "= unlocked" * status even though a subpart of the region is effectively= locked. + * + * If in doubt during development, check-out the debugfs output which trie= s to + * be more user friendly. */ static const struct spi_nor_locking_ops spi_nor_sr_locking_ops =3D { .lock =3D spi_nor_sr_lock, --=20 2.51.1