From e96d4605b024495d42279ae8e899969b29f7ce5f Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 28 Mar 2023 17:41:02 +0200 Subject: mtd: spi-nor: Prepare the introduction of a new locking mechanism This commit alone just introduces two new "prepare and lock" pairs of helpers which do the exact same thing as before. They will soon be improved in a followup commit which actually brings the logic, but I figured out it was more readable to do it this way. One new pair is suffixed _pe which stands for "program and erase" and hence is being called by spi_nor_write() and spi_nor_erase(). The other pair is suffixed _rd which stands for "read" and hence is being called by spi_nor_read(). One note however, these extra helpers will need to know the operation range, so they come with two new parameters to define it. Otherwise there is no functional change. Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/r/20230328154105.448540-6-miquel.raynal@bootlin.com Signed-off-by: Tudor Ambarus --- drivers/mtd/spi-nor/core.c | 59 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 6 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index e80677d36a8c..daed09950ee1 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1086,6 +1086,7 @@ static void spi_nor_unprep(struct spi_nor *nor) nor->controller_ops->unprepare(nor); } +/* Generic helpers for internal locking and serialization */ int spi_nor_prep_and_lock(struct spi_nor *nor) { int ret; @@ -1106,6 +1107,48 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor) spi_nor_unprep(nor); } +/* Internal locking helpers for program and erase operations */ +static int spi_nor_prep_and_lock_pe(struct spi_nor *nor, loff_t start, size_t len) +{ + int ret; + + ret = spi_nor_prep(nor); + if (ret) + return ret; + + mutex_lock(&nor->lock); + + return 0; +} + +static void spi_nor_unlock_and_unprep_pe(struct spi_nor *nor, loff_t start, size_t len) +{ + mutex_unlock(&nor->lock); + + spi_nor_unprep(nor); +} + +/* Internal locking helpers for read operations */ +static int spi_nor_prep_and_lock_rd(struct spi_nor *nor, loff_t start, size_t len) +{ + int ret; + + ret = spi_nor_prep(nor); + if (ret) + return ret; + + mutex_lock(&nor->lock); + + return 0; +} + +static void spi_nor_unlock_and_unprep_rd(struct spi_nor *nor, loff_t start, size_t len) +{ + mutex_unlock(&nor->lock); + + spi_nor_unprep(nor); +} + static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr) { if (!nor->params->convert_addr) @@ -1459,7 +1502,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) addr = instr->addr; len = instr->len; - ret = spi_nor_prep_and_lock(nor); + ret = spi_nor_prep_and_lock_pe(nor, instr->addr, instr->len); if (ret) return ret; @@ -1522,7 +1565,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) ret = spi_nor_write_disable(nor); erase_err: - spi_nor_unlock_and_unprep(nor); + spi_nor_unlock_and_unprep_pe(nor, instr->addr, instr->len); return ret; } @@ -1715,11 +1758,13 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); + loff_t from_lock = from; + size_t len_lock = len; ssize_t ret; dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); - ret = spi_nor_prep_and_lock(nor); + ret = spi_nor_prep_and_lock_rd(nor, from_lock, len_lock); if (ret) return ret; @@ -1746,7 +1791,8 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, ret = 0; read_err: - spi_nor_unlock_and_unprep(nor); + spi_nor_unlock_and_unprep_rd(nor, from_lock, len_lock); + return ret; } @@ -1765,7 +1811,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); - ret = spi_nor_prep_and_lock(nor); + ret = spi_nor_prep_and_lock_pe(nor, to, len); if (ret) return ret; @@ -1807,7 +1853,8 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, } write_err: - spi_nor_unlock_and_unprep(nor); + spi_nor_unlock_and_unprep_pe(nor, to, len); + return ret; } -- cgit v1.2.3