Re: [PATCH RFC 0/3] mtd: spi-nor: allow multiple erase sizes on uniform flashes

From: Michael Walle

Date: Wed Jul 22 2026 - 03:41:54 EST


Hi,

On Mon Jul 20, 2026 at 5:12 PM CEST, Mateusz Litwin via B4 Relay wrote:
> Most SPI NOR flashes advertise several erase sizes (e.g. 4 KiB, 32 KiB and
> 64 KiB) even when the erase map is uniform across the whole device. The
> spi-nor driver currently collapses such flashes to a single erase size and
> uses only that size for every erase request.
>
> This is a problem on platforms that need a small exposed erasesize for
> partition alignment (for example u-boot-env, RouterBoot soft_config, or
> boot header partitions) while still wanting fast bulk erases. Today the
> usual workaround is to enable MTD_SPI_NOR_USE_4K_SECTORS, which forces 4 KiB
> erases for the entire device and hurts erase performance on large regions.
>
> This series introduces MTD_SPI_NOR_MULTI_ERASE_SIZE. When enabled, uniform
> flashes keep multiple erase sizes in the driver erase map and pick the
> largest suitable erase size for each step of an erase operation, similar to
> what non-uniform flashes already do. Userspace still sees a single
> mtd->erasesize (4 KiB when MTD_SPI_NOR_USE_4K_SECTORS is also enabled), but
> large aligned portions of an erase request can use 32 KiB or 64 KiB erase
> commands internally.
>
> The series also converts all erase-type opcodes to their 4-byte-address
> variants on uniform flashes, so multi-size erases work correctly on devices
> larger than 16 MiB.
>
> This is an RFC series. Feedback is especially welcome on whether to merge
> patch 1 alone, patches 1+2, or the full series including the patch 3 PoC.
>
> The series is stacked so maintainers can choose how much to take:
>
> - Patch 1 adds the Kconfig option, keeps multiple erase types in the
> uniform region mask, and converts all erase-type opcodes for 4-byte
> addressing. On its own it routes multi-size uniform erases through
> spi_nor_erase_multi_sectors().
> - Patch 2 replaces that routing with a dedicated uniform erase flow
> (spi_nor_erase_uniform()), reducing CPU and memory overhead.
> - Patch 3 is a proof-of-concept optimization on top of patch 2: it
> caches the largest uniform erase type per request to skip redundant
> spi_nor_find_best_erase_type() calls in bulk-aligned regions.
>
> Patch 1 follows an OpenWrt pending patch already used in production:
>
> https://github.com/openwrt/openwrt/blob/main/target/linux/generic/pending-6.12/402-mtd-spi-nor-write-support-for-minor-aligned-partitions.patch
>
> MTD_SPI_NOR_MULTI_ERASE_SIZE defaults to N, so existing configurations are
> unaffected.

No, not a new Kconfig option. Integrate it into the core, adapt the
current erase handling.

Also, was this assisted by AI tooling?

> Tested: backported to a 6.6-based tree on Micron MT25QU02G with
> MTD_SPI_NOR_MULTI_ERASE_SIZE enabled and MTD_SPI_NOR_USE_4K_SECTORS

Why didn't you test this on the latest kernel?

> disabled (mtd->erasesize reports 64 KiB). librsu erases the flash with

What is librsu?

-michael

> the MEMERASE ioctl on the MTD character device, issuing erase requests
> smaller than mtd->erasesize (e.g. a 32 KiB boot header region).
> mtd_erase() does not enforce erasesize alignment, so these requests reach
> the driver, where the previous uniform path rejected them; they now
> succeed through spi_nor_is_uniform_erasable() and the multi-size erase
> path. Verified writes and erases on the 32 KiB region.
>
> A few implementation details are worth discussing:
>
> 1. The previous uniform erase path only required the length to be a
> multiple of mtd->erasesize. With MTD_SPI_NOR_MULTI_ERASE_SIZE enabled,
> spi_nor_is_uniform_erasable() instead checks the address and length
> against the smallest supported uniform erase size. Requests aligned to
> mtd->erasesize still pass (it is a multiple of that size), while
> callers may now issue erases smaller than mtd->erasesize, as the tested
> librsu path does. Misaligned requests are rejected rather than
> relying on undefined behavior; please report any regressions.
>
> 2. Patch 3 addresses per-step spi_nor_find_best_erase_type() overhead.
> As a PoC it may be dropped, revised, or split out depending on
> maintainer feedback.
>
> 3. Patch 3 calculates the largest erase size on every request. This could
> be done once at init. The same applies to the smallest erase size used
> for request validation. Where to store that data is open for
> discussion if such a change is needed.
>
> 4. spansion_nor_late_init() overrides nor->erase_opcode (and mtd->erasesize)
> for flashes larger than 16 MiB. With MTD_SPI_NOR_MULTI_ERASE_SIZE enabled,
> spi_nor_erase_uniform() sets nor->erase_opcode before each erase, so the
> late_init value is not used on the erase path. If the SFDP table masks
> unsupported erase types in 4-byte-address mode, this is not an issue;
> otherwise late_init() or erase-type masking may need changes for
> Cypress/Spansion parts.
>
> 5. Some flashes do not support every erase type with 4-byte-address opcodes.
> Unsupported types are masked by clearing erase_type[].size, but the
> corresponding erase_mask bit is not cleared. Erases work correctly, but
> debugfs can show a set bit in the sector-map erase mask for a type that is
> not listed under "erase commands". Fixing that is probably best done in
> a separate patch.
>
> Signed-off-by: Mateusz Litwin <mateusz.litwin@xxxxxxxxx>
> ---
> Mateusz Litwin (3):
> mtd: spi-nor: allow multiple erase sizes on uniform flash
> mtd: spi-nor: add dedicated multi-size uniform erase path
> mtd: spi-nor: skip erase type search in uniform bulk erase
>
> drivers/mtd/spi-nor/Kconfig | 25 +++++
> drivers/mtd/spi-nor/core.c | 247 +++++++++++++++++++++++++++++++++-----------
> 2 files changed, 213 insertions(+), 59 deletions(-)
> ---
> base-commit: df415c5e1de0f1aeefacb4e6252ff98d38c04437
> change-id: 20260720-spi_nor_multisize_erase-d644cfd4a5fb
>
> Best regards,