[PATCH] mtd: spi-nor: use _lock_and_prep() in _read_sfdp()

Cyrille Pitchen cyrille.pitchen at wedev4u.fr
Fri Dec 22 04:49:39 PST 2017


Hi Yogesh,

Le 22/12/2017 à 09:35, Yogesh Gaur a écrit :
> spi_nor_read_sfdp() calls nor->read() to read the SFDP data.
> But first needs to call nor->prepare() to prepare the READ command before
> calling nor->read().
>

Currently, I don't agree with this: spi_nor_read_sfdp() is called only from
spi_nor_scan(). Before the SFDP patch, spi_nor_scan() has already been
calling for years nor->read_reg() and nor->write_reg() without calling
spi_nor_lock_and_prep() first.

Indeed, still being in spi_nor_scan(), the SPI NOR memory should have not
been registered yet to the above MTD layer. So there should be no need to
lock nor->lock at this point.

Then, about calling nor->prepare(), IMHO, it's look a little bit odd that
neither nor->read_reg() nor nor->write_reg() require nor->prepare() to be
called first whereas nor->read() does need it.

You didn't describe what issue or bug you actually noticed so now I assume
it deals with the fsl-quadspi.c driver. So let's have a look at its
implementation of nor->prepare() / fsl_qspi_prep():

+static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+	struct fsl_qspi *q = nor->priv;
+	int ret;
+
+	mutex_lock(&q->lock);

It was not needed before by fsl_qspi_read_reg() or fls_qspi_write_reg(),
why would it be needed now by fls_qspi_read()?

Then I guess, this is not the issue.

Anyway, if actually needed or safer, the mutex can be locked just after
mutex_init() and before for_each_available_child_of_node() in
fsl_qspi_probe().

+
+	ret = fsl_qspi_clk_prep_enable(q);

Already called from fls_qpsi_probe() before calling spi_nor_scan():
should not be the issue neither.

+	if (ret)
+		goto err_mutex;
+
+	fsl_qspi_set_base_addr(q, nor);

Also called from fsl_qspi_probe() right before calling spi_nor_scan():

		/* set the chip address for READID */
		fsl_qspi_set_base_addr(q, nor);

		ret = spi_nor_scan(nor, NULL, &hwcaps);
		if (ret)
			goto mutex_failed;

		ret = mtd_device_register(mtd, NULL, 0);
		if (ret)
			goto mutex_failed;

		/* Set the correct NOR size now. */
		if (q->nor_size == 0) {
			q->nor_size = mtd->size;

			/* Map the SPI NOR to accessiable address */
			fsl_qspi_set_map_addr(q);
		}

q->nor_size is only updated after spi_nor_scan() hence I don't see why
calling nor->prepare() hence fsl_qpsi_set_base_addr() one more time now
during spi_nor_scan() would actually change anything.

Please note that all I said was based on the assumption that you are trying
to fix an issue in the fsl-quadspi.c driver (based on your email address:
@nxp.com) as the nxp-spifi.c driver doesn't provide any implementation for
the optional nor->prepare().

Then could you please describe a little bit more details about the actual
issue? What does this patch fix? Which drivers are involved? 

Indeed, you would like to have a precise understanding of the issue and
also avoid modifying spi-nor.c rather than the single fsl-quadspi.c driver
or whatever driver is concerned since calling nor->preprare() from
spi_nor_scan() has never been done before and may have unwanted side effects
on other SPI flash controller drivers.

Actually, this is the reason why spi_nor_read_sfdp() directly calls
nor->read() instead of spi_nor_read().

Best regards,

Cyrille

+	return 0;
+
+err_mutex:
+	mutex_unlock(&q->lock);
+	return ret;
+}

 
> Patch adds call to spi_nor_lock_and_prep() to prepare the READ command
> and add subsequent call to spi_nor_unlock_and_unprep() to release lock
> and call nor->unprepare().
> 
> Signed-off-by: Yogesh Gaur <yogeshnarayan.gaur at nxp.com>
> ---
>  drivers/mtd/spi-nor/spi-nor.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 2203d6ef..9fb85ae 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -1807,6 +1807,10 @@ static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
>  	nor->addr_width = 3;
>  	nor->read_dummy = 8;
>  
> +	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_READ);
> +	if (ret)
> +		goto lock_err;
> +
>  	while (len) {
>  		ret = nor->read(nor, addr, len, (u8 *)buf);
>  		if (!ret || ret > len) {
> @@ -1822,6 +1826,8 @@ static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
>  	}
>  	ret = 0;
>  
> +	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
> +lock_err:
>  read_err:
>  	nor->read_opcode = read_opcode;
>  	nor->addr_width = addr_width;
> 




More information about the linux-mtd mailing list