[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1658508510-15400-2-git-send-email-zhouyanjie@wanyeetech.com>
Date: Sat, 23 Jul 2022 00:48:28 +0800
From: 周琰杰 (Zhou Yanjie)
<zhouyanjie@...yeetech.com>
To: tudor.ambarus@...rochip.com, p.yadav@...com, michael@...le.cc,
miquel.raynal@...tlin.com, richard@....at, vigneshr@...com,
broonie@...nel.org, robh+dt@...nel.org,
krzysztof.kozlowski+dt@...aro.org
Cc: linux-mtd@...ts.infradead.org, linux-spi@...r.kernel.org,
linux-mips@...r.kernel.org, linux-kernel@...r.kernel.org,
devicetree@...r.kernel.org, aidanmacdonald.0x0@...il.com,
tmn505@...il.com, paul@...pouillou.net, dongsheng.qiu@...enic.com,
aric.pzqi@...enic.com, rick.tyliu@...enic.com,
jinghui.liu@...enic.com, sernia.zhou@...mail.com,
reimu@...omaker.com
Subject: [PATCH 1/3] mtd: spi-nor: Use the spi-mem poll status APIs.
With advanced controllers (such as Ingenic SFC), it is possible to poll
the status register of the device. This could be done to offload the CPU
during a erase or write operation. Make use of spi-mem poll status APIs
to handle this feature.
Previously, when erasing large area (e.g. 32MiB), in non-offload case,
CPU load could reach ~90% and would generate ~3.92 million interrupts,
now it decrease to ~15% CPU load and 0.15 million interrupts.
This should also fix the high CPU usage for system which don't have a
dedicated poll status block logic (decrease to ~80% CPU load and ~1.61
million interrupts.).
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@...yeetech.com>
---
drivers/mtd/spi-nor/core.c | 42 ++++++++++++++++++++++++++++++++----------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 502967c..6a31132 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -617,19 +617,41 @@ static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor,
unsigned long deadline;
int timeout = 0, ret;
- deadline = jiffies + timeout_jiffies;
+ if (nor->spimem && !nor->params->ready) {
+ struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),
+ SPI_MEM_OP_NO_ADDR,
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 0));
- while (!timeout) {
- if (time_after_eq(jiffies, deadline))
- timeout = 1;
+ if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
+ op.addr.nbytes = nor->params->rdsr_addr_nbytes;
+ op.dummy.nbytes = nor->params->rdsr_dummy;
+ /*
+ * We don't want to read only one byte in DTR mode. So,
+ * read 2 and then discard the second byte.
+ */
+ op.data.nbytes = 2;
+ }
- ret = spi_nor_ready(nor);
- if (ret < 0)
- return ret;
- if (ret)
- return 0;
+ spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
+ return spi_mem_poll_status(nor->spimem, &op, SR_WIP, 0, 0, 10,
+ jiffies_to_msecs(timeout_jiffies));
+ } else {
+ deadline = jiffies + timeout_jiffies;
- cond_resched();
+ while (!timeout) {
+ if (time_after_eq(jiffies, deadline))
+ timeout = 1;
+
+ ret = spi_nor_ready(nor);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ return 0;
+
+ cond_resched();
+ }
}
dev_dbg(nor->dev, "flash operation timed out\n");
--
2.7.4
Powered by blists - more mailing lists