diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2023-03-28 17:41:04 +0200 |
---|---|---|
committer | Tudor Ambarus <tudor.ambarus@linaro.org> | 2023-03-29 13:46:07 +0300 |
commit | 74df43b3f626a3594a4de50556048852bf2753f7 (patch) | |
tree | 9137528bcfb991d43649b97b97f8fd95021bc0d8 /include/linux/mtd | |
parent | 4eddee70140b3ae183398b246a609756546c51f1 (diff) | |
download | linux-74df43b3f626a3594a4de50556048852bf2753f7.tar.gz linux-74df43b3f626a3594a4de50556048852bf2753f7.tar.bz2 linux-74df43b3f626a3594a4de50556048852bf2753f7.zip |
mtd: spi-nor: Enhance locking to support reads while writes
On devices featuring several banks, the Read While Write (RWW) feature
is here to improve the overall performance when performing parallel
reads and writes at different locations (different banks). The following
constraints have to be taken into account:
1#: A single operation can be performed in a given bank.
2#: Only a single program or erase operation can happen on the entire
chip (common hardware limitation to limit costs)
3#: Reads must remain serialized even though reads crossing bank
boundaries are allowed.
4#: The I/O bus is unique and thus is the most constrained resource, all
spi-nor operations requiring access to the spi bus (through the spi
controller) must be serialized until the bus exchanges are over. So
we must ensure a single operation can be "sent" at a time.
5#: Any other operation that would not be either a read or a write or an
erase is considered requiring access to the full chip and cannot be
parallelized, we then need to ensure the full chip is in the idle
state when this occurs.
All these constraints can easily be managed with a proper locking model:
1#: Is enforced by a bitfield of the in-use banks, so that only a single
operation can happen in a specific bank at any time.
2#: Is handled by the ongoing_pe boolean which is set before any write
or erase, and is released only at the very end of the
operation. This way, no other destructive operation on the chip can
start during this time frame.
3#: An ongoing_rd boolean allows to track the ongoing reads, so that
only one can be performed at a time.
4#: An ongoing_io boolean is introduced in order to capture and serialize
bus accessed. This is the one being released "sooner" than before,
because we only need to protect the chip against other SPI accesses
during the I/O phase, which for the destructive operations is the
beginning of the operation (when we send the command cycles and
possibly the data), while the second part of the operation (the
erase delay or the programmation delay) is when we can do something
else in another bank.
5#: Is handled by the three booleans presented above, if any of them is
set, the chip is not yet ready for the operation and must wait.
All these internal variables are protected by the existing lock, so that
changes in this structure are atomic. The serialization is handled with
a wait queue.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/r/20230328154105.448540-8-miquel.raynal@bootlin.com
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Diffstat (limited to 'include/linux/mtd')
-rw-r--r-- | include/linux/mtd/spi-nor.h | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index a3f8cdca90c8..82547b4b3708 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -343,6 +343,12 @@ struct spi_nor_flash_parameter; * struct spi_nor - Structure for defining the SPI NOR layer * @mtd: an mtd_info structure * @lock: the lock for the read/write/erase/lock/unlock operations + * @rww: Read-While-Write (RWW) sync lock + * @rww.wait: wait queue for the RWW sync + * @rww.ongoing_io: the bus is busy + * @rww.ongoing_rd: a read is ongoing on the chip + * @rww.ongoing_pe: a program/erase is ongoing on the chip + * @rww.used_banks: bitmap of the banks in use * @dev: pointer to an SPI device or an SPI NOR controller device * @spimem: pointer to the SPI memory device * @bouncebuf: bounce buffer used when the buffer passed by the MTD @@ -376,6 +382,13 @@ struct spi_nor_flash_parameter; struct spi_nor { struct mtd_info mtd; struct mutex lock; + struct spi_nor_rww { + wait_queue_head_t wait; + bool ongoing_io; + bool ongoing_rd; + bool ongoing_pe; + unsigned int used_banks; + } rww; struct device *dev; struct spi_mem *spimem; u8 *bouncebuf; |