All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Santhosh Kumar K" <s-k6@ti.com>
Cc: "Pratyush Yadav" <pratyush@kernel.org>,
	devicetree@vger.kernel.org,
	"Takahiro Kuwano" <takahiro.kuwano@infineon.com>,
	conor+dt@kernel.org, "Vignesh Raghavendra" <vigneshr@ti.com>,
	robh@kernel.org, "Richard Weinberger" <richard@nod.at>,
	"Miquel Raynal" <miquel.raynal@bootlin.com>,
	"Michael Walle" <mwalle@kernel.org>
Subject: Re: [PATCH v6 15/17] mtd: spinand: negotiate optimal controller operating point before dirmap creation
Date: Thu, 23 Jul 2026 12:02:23 +0000	[thread overview]
Message-ID: <20260723120247.8E1BD1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260723110219.3180747-16-s-k6@ti.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Ranked controller optimization downgrades the read variant on tuning failure but fails to update or disable continuous read, leading to potential controller lockups and data corruption.
- [High] The SPI NAND chip is unconditionally restored to ODTR mode upon system resume, even if controller optimization dynamically fell back to SSDR mode at probe time, breaking statically configured dirmaps.
- [High] SPI controller PHY tuning state is lost across suspend/resume cycles.
- [Medium] `spinand->max_write_op` is not reset between iterations in `spinand_try_ranked_variant()`, leaking `max_freq` modifications across tuning attempts.
--

--- Patch [15]: [PATCH v6 15/17] mtd: spinand: negotiate optimal controller operating point before dirmap creation ---
commit dc7c5dff1e36808c28c6f5690c48c5cbe8f6d925
Author: Santhosh Kumar K <s-k6@ti.com>
Subject: mtd: spinand: negotiate optimal controller operating point before dirmap creation

This commit moves dirmap creation after negotiating the optimal controller
operating point, so the validated frequency is embedded in the descriptors.
It introduces a ranked fallback mechanism to try variants in performance
order if the initial optimization fails.

> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index f839438a44ff2..e082e6233c7c1 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
[ ... ]
> @@ -2050,6 +2055,175 @@ static void spinand_cleanup(struct spinand_device *spinand)
> +static bool spinand_try_ranked_variant(struct spinand_device *spinand,
> +				       struct spi_mem *mem,
> +				       enum spinand_bus_interface iface,
> +				       u32 *tried_mask)
> +{
> +	const struct spinand_op_variants *variants = spinand->all_read_variants;
> +	const struct spi_mem_op *best;
> +	int ret;
> +
> +	if (!variants)
> +		return false;
> +
> +	while ((best = spinand_op_find_best_variant(spinand, variants, iface,
> +						    *tried_mask))) {
> +		*tried_mask |= BIT(best - variants->ops);
> +		spinand->max_read_op = *best;
> +		spinand->max_read_op.max_freq = 0;

[Severity: Medium]
Should spinand->max_write_op.max_freq also be reset to 0 here?

If the controller driver modifies the write op's max_freq during a failed
tuning attempt, the non-zero max_freq leaks into the next loop iteration. This
could limit the frequency negotiation artificially, causing subsequent valid
fallback variants to fail tuning or operate at suboptimal speeds.

> +		ret = spi_mem_execute_tuning(mem, &spinand->max_read_op,
> +					     &spinand->max_write_op);
> +		if (ret && ret != -EOPNOTSUPP)
> +			dev_dbg(&mem->spi->dev, "%s optimization failed: %d\n",
> +				iface == ODTR ? "ODTR" : "SSDR", ret);
> +		if (!ret && spinand->max_read_op.max_freq) {
> +			if (iface == ODTR)
> +				spinand->odtr_op_templates.read_cache = best;
> +			else
> +				spinand->ssdr_op_templates.read_cache = best;

[Severity: High]
Is it necessary to update or disable cont_read_cache to match the new
controller capabilities?

If spinand_optimize_controller() falls back to a slower ranked variant, it
only updates read_cache here, leaving cont_read_cache and cont_read_possible
unchanged. When spinand_create_dirmap() constructs the secondary read dirmap,
it will use the unmodified, incompatible cont_read_cache but incorrectly assign
it the max_freq of this slower fallback variant. 

When the kernel executes a continuous read, will it send an unsupported command
at an incompatible PHY frequency, potentially crashing the controller or
silently corrupting data?

> +			return true;
> +		}
> +	}
> +	return false;
> +}
[ ... ]
> +static void spinand_optimize_controller(struct spinand_device *spinand,
> +					struct spi_mem *mem)
> +{
[ ... ]
> +	/*
> +	 * Pass 2: switch to SSDR and try all SSDR variants in performance
> +	 * order. configure_chip is guaranteed non-NULL here: reaching ODTR
> +	 * mode requires it.
> +	 */
> +	if (WARN_ON(!spinand->configure_chip))
> +		goto use_odtr_fallback;
> +
> +	if (spinand->configure_chip(spinand, SSDR))
> +		goto use_odtr_fallback;
> +
> +	spinand->op_templates = &spinand->ssdr_op_templates;
> +	spinand->bus_iface = SSDR;

[Severity: High]
Does falling back to SSDR mode here require clearing the ODTR templates?

If ODTR tuning fails during probe, the device is switched to SSDR and dirmaps
are created using SSDR templates. However, because odtr_op_templates are not
cleared, when the system resumes from suspend, spinand_mtd_resume() calls
spinand_init_flash() -> spinand_configure_chip(). 

The configure chip logic will see that the ODTR templates exist and
unconditionally force the chip back into ODTR mode. Will subsequent I/O
operations then send SSDR-formatted SPI commands to a chip expecting ODTR
commands, resulting in data corruption?

> +	spinand->max_write_op = *spinand->ssdr_op_templates.write_cache;
> +	spinand->max_write_op.max_freq = 0;
[ ... ]
> @@ -2072,6 +2246,20 @@ static int spinand_probe(struct spi_mem *mem)
>  	if (ret)
>  		return ret;
>  
> +	/*
> +	 * Negotiate the best controller operating point before creating dirmaps
> +	 * so the validated frequency is available at dirmap construction time.
> +	 */
> +	spinand_optimize_controller(spinand, mem);

[Severity: High]
Will the PHY tuning state negotiated here get restored across suspend/resume
cycles?

During probe, spinand_optimize_controller() calibrates the controller PHY delay
registers via spi_mem_execute_tuning() and embeds the validated max_freq into
the dirmaps. During suspend, the SPI controller loses power.

On resume, neither the SPI core, spinand_mtd_resume(), nor the controller
driver appear to restore the PHY tuning registers or re-invoke
spi_mem_execute_tuning(). Could the dirmaps continue executing I/O at the high
max_freq with uncalibrated PHY timings, resulting in I/O errors or data
corruption?

> +	ret = spinand_create_dirmaps(spinand);
> +	if (ret) {
> +		dev_err(&mem->spi->dev,
> +			"Failed to create direct mappings for read/write operations (err = %d)\n",
> +			ret);
> +		goto err_spinand_cleanup;
> +	}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260723110219.3180747-1-s-k6@ti.com?part=15

  reply	other threads:[~2026-07-23 12:02 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-23 11:02 [PATCH v6 00/17] spi: cadence-quadspi: add PHY tuning support Santhosh Kumar K
2026-07-23 11:02 ` Santhosh Kumar K
2026-07-23 11:02 ` [PATCH v6 01/17] spi: dt-bindings: add spi-max-post-config-frequency-hz property Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:02 ` [PATCH v6 02/17] spi: dt-bindings: add spi-phy-pattern-partition property Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:02 ` [PATCH v6 03/17] spi: parse spi-max-post-config-frequency-hz into post_config_max_speed_hz Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:02 ` [PATCH v6 04/17] spi: spi-mem: teach spi_mem_adjust_op_freq() about post-config ops Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:34   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 05/17] spi: spi-mem: add execute_tuning callback and spi_mem_execute_tuning() Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:30   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 06/17] spi: cadence-quadspi: move cqspi_readdata_capture earlier Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:02 ` [PATCH v6 07/17] spi: cadence-quadspi: add DQS support to read data capture Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:28   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 08/17] spi: cadence-quadspi: add PHY tuning support Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:33   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 09/17] spi: cadence-quadspi: skip DDR PHY tuning for 2-byte-address ops (i2383) Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:48   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 10/17] spi: cadence-quadspi: refactor direct read path for PHY support Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:41   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 11/17] spi: cadence-quadspi: enable PHY for direct reads Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:48   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 12/17] spi: cadence-quadspi: enable PHY for indirect writes Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:44   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 13/17] spi: cadence-quadspi: reprogram CS timing on every chip-select switch Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:49   ` sashiko-bot
2026-07-23 11:02 ` [PATCH v6 14/17] mtd: spinand: extract variant ranking logic into spinand_op_find_best_variant() Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:02 ` [PATCH v6 15/17] mtd: spinand: negotiate optimal controller operating point before dirmap creation Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 12:02   ` sashiko-bot [this message]
2026-07-23 11:02 ` [PATCH v6 16/17] mtd: spi-nor: extract read op template construction into helper Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K
2026-07-23 11:02 ` [PATCH v6 17/17] mtd: spi-nor: run controller optimization before dirmap creation Santhosh Kumar K
2026-07-23 11:02   ` Santhosh Kumar K

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260723120247.8E1BD1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=miquel.raynal@bootlin.com \
    --cc=mwalle@kernel.org \
    --cc=pratyush@kernel.org \
    --cc=richard@nod.at \
    --cc=robh@kernel.org \
    --cc=s-k6@ti.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=takahiro.kuwano@infineon.com \
    --cc=vigneshr@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.