| Age | Commit message (Collapse) | Author |
|
|
|
fsl_qspi_select_mem() returns early when the chip select has not changed,
which happens before it reaches clk_set_rate(). Since the rate is now
taken from the spi-mem operation rather than from the SPI device, the
controller honours op->max_freq exactly once per chip select and ignores
it for every operation after that.
q->selected is only reset to -1 in fsl_qspi_default_setup(), i.e. at probe
and on resume, so on the common single chip select board the very first
operation latches a rate that all subsequent operations inherit, whatever
frequency they asked for.
This results in operations being issued with the wrong frequency.
Cache the operation frequency the clock was programmed for next to the
selected chip select, and redo the clock setup when either changes.
Fixes: 2438db5253eb ("spi: fsl-qspi: Support per spi-mem operation frequency switches")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Acked-by: Han Xu <han.xu@nxp.com>
Link: https://patch.msgid.link/20260917-fsl-qspi-freq-op-fix-v1-1-5fbe6b02f738@kontron.de
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Johan Alvarado <contact@c127.dev> says:
qcom_spi_ecc_init_ctx_pipelined() installs the ooblayout but never
publishes the ECC context it allocates, so qcom_spi_ooblayout_ecc() and
qcom_spi_ooblayout_free() run against a pointer that describes something
else - a zeroed struct on a first probe, the previous attempt's freed
context on a retry. On IPQ5018 the qcom,smem-part parser makes that retry
routine, and like half the boots on a Mercusys MR80X failed to mount the
rootfs.
Patch 1 is the fix and is unchanged from v1. Patch 2 removes what becomes
redundant once the context is published. It is a cleanup with no
functional change, so it carries no Fixes: tag and is not marked for
stable.
Patch 1 was applied to mtd/fixes as 93bc7c4d2f41 on 2026-09-04 and
dropped the same day, so nothing from this series is queued.
Link: https://patch.msgid.link/20260911184416.109790-1-contact@c127.dev
|
|
qcom_spi_ecc_init_ctx_pipelined() now publishes the ECC context to
snandc->qspi->ecc, so the assignment in
qcom_spi_ecc_prepare_io_req_pipelined() repeats what the pointer already
holds, and the zeroed struct qpic_ecc that qcom_spi_probe() allocates is
never read.
The pointer is non-NULL only between context creation and destruction,
and every reader runs inside that window. The ooblayout callbacks are
installed by init_ctx. The page read, write and program helpers run only
when prepare_io_req has set page_rw or oob_rw. qcom_spi_block_erase()
runs only while the mtd is registered, which happens after init_ctx and
ends before cleanup_ctx. The controller drives a single chip select, so
the per-controller pointer and the per-chip context cannot disagree.
Remove both. No functional change.
Suggested-by: Gabor Juhos <j4g8y7@gmail.com>
Signed-off-by: Johan Alvarado <contact@c127.dev>
Tested-by: Gabor Juhos <j4g8y7@gmail.com>
Link: https://patch.msgid.link/20260911184416.109790-3-contact@c127.dev
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
qcom_spi_ooblayout_ecc() and qcom_spi_ooblayout_free() read the ECC
configuration through snandc->qspi->ecc. qcom_spi_probe() points it at a
zeroed scratch struct and only qcom_spi_ecc_prepare_io_req_pipelined(),
which runs on page I/O, ever updates it. qcom_spi_ecc_init_ctx_pipelined()
installs the ooblayout but does not publish the context it just
allocated, and qcom_spi_ecc_cleanup_ctx_pipelined() frees that context
without clearing the pointer.
spinand_init() calls mtd_ooblayout_count_freebytes() right after the ECC
context is created and before any page I/O, so the ooblayout always runs
against a pointer that does not describe the current context:
- On a first probe it reads the zeroed struct from qcom_spi_probe(),
so steps, bytes and bbm_size are 0. The count then returns 0 rather
than an error, so the probe continues with mtd->oobavail set to 0.
- On a probe retry it reads the ecc_cfg the previous attempt freed.
A retry is easy to hit. On IPQ5018 with the qcom,smem-part parser the
partition parse returns -EPROBE_DEFER until SMEM has probed, so the
first spi-nand probe defers. It defers inside
mtd_device_parse_register(), after mtd_otp_nvmem_add() has already read
the factory OTP - that read goes through prepare_io_req and leaves
snandc->qspi->ecc pointing at the context that spinand_cleanup() then
frees. The second probe allocates a new context, never publishes it, and
computes the OOB layout from the freed one. Once the slab has been
reused, qecc->steps holds garbage and
oobregion->length = qecc->steps * 4;
goes negative. qcom_spi_ooblayout_free() only reports -ERANGE for
section 1 and later, so mtd_ooblayout_count_bytes() sums the regions and
returns that negative length as the byte count. The -512 below is
steps * 4 with steps == -128. It is a byte count that happens to
collide with -ERESTARTSYS, not an error the driver returned.
spinand_init() takes it as an error, and because it is not
-EPROBE_DEFER the driver core never retries and the NAND never appears:
spi-nand spi0.0: ESMT SPI NAND was found.
spi-nand spi0.0: probe with driver spi-nand failed with error -512
UBI error: cannot open mtd rootfs, error -2
Waiting for root device /dev/ubiblock0_1...
On a Mercusys MR80X (IPQ5018, ESMT F50D1G41LB) about half of the boots
failed to mount the rootfs, the outcome depending on whether the freed
memory had been overwritten yet.
Publish the context when it is created and clear the pointer when it is
destroyed. Clearing leaves snandc->qspi->ecc NULL after cleanup, which
is safe: the mtd is unregistered before cleanup_ctx runs, so no
ooblayout callback can follow.
Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
Cc: stable@vger.kernel.org
Tested-by: Gabor Juhos <j4g8y7@gmail.com>
Signed-off-by: Johan Alvarado <contact@c127.dev>
Link: https://patch.msgid.link/20260911184416.109790-2-contact@c127.dev
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Francesco Valla <francesco@valla.it> says:
while developing a virtio-spi device, I noticed that the spi-virtio
driver in not honoring the indication on the maximum transfer frequency
supported by the device that this one indicates using the config space.
Patch 1 contains a fix for that.
While at it, I did a minor cleanup inside the function parsing the
config space, where a value was stored into the driver's private data
without a further usage, wasting (a very tiny amount of) memory.
This was tested against a (still unreleased) virtio device running on
a Cortex-M33, with remoteproc as virtio transport.
Link: https://patch.msgid.link/20260915-virtio-spi-fix2-v1-0-7a474cb1b13b@valla.it
|
|
The mode_func_supported field is read from the config space into the
driver's private data, but then never used outside of the function it is
read in. Drop the variable from the private data and parse it from the
stack instead.
Signed-off-by: Francesco Valla <francesco@valla.it>
Link: https://patch.msgid.link/20260915-virtio-spi-fix2-v1-2-7a474cb1b13b@valla.it
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The maximum transfer frequency is read from the virtio config space but
never propagated to the SPI framework logic. Fix this behavior and drop
the useless setting copy from the driver's private data.
Fixes: f98cabe3f6cf ("SPI: Add virtio SPI driver")
Signed-off-by: Francesco Valla <francesco@valla.it>
Link: https://patch.msgid.link/20260915-virtio-spi-fix2-v1-1-7a474cb1b13b@valla.it
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The driver has no ->shutdown, and platform_drv_shutdown() has no
fallback of its own. Unlike pci_device_shutdown(), which clears bus
mastering when kexec_in_progress, nothing on the platform bus disarms a
device that can still write to memory. The normal kexec path never
calls ->suspend either, so the quiesce in zynqmp_qspi_suspend() is not
reached.
A controller that is still executing a DMA read may therefore keep
writing to memory across a kexec. QSPIDMA_DST_ADDR still points at
memory owned by the kernel that called kexec, DST_SIZE is non-zero and
the flash is still clocked, so data can keep landing in RAM while the
new kernel is being relocated, and after it has started executing.
That destination is a physical address which means nothing to the new
kernel, so the writes can corrupt whatever now occupies it: kernel text
or data, page tables, or the initrd. Nothing reports an error and the
resulting behaviour is undefined.
This can be observed by reading GQSPI_EN (offset 0x114) and
QSPIDMA_DST_ADDR/SIZE/STS/CTRL (offsets 0x800 to 0x80c) early in the new
kernel, before the driver probes: without this patch GQSPI_EN reads 1
and QSPIDMA_DST_ADDR still points into the previous kernel's memory.
Add a ->shutdown that stops the controller the way zynqmp_qspi_suspend()
already does. spi_controller_suspend() stops the queue, waits for a
message that is already executing and makes any later transfer fail with
-ESHUTDOWN, so nothing can be cut short by the register write that
follows. It may sleep, which is fine here: device_shutdown() runs in
process context. Unlike ->suspend this cannot abort on error, because a
controller left mastering the bus is worse than a truncated transfer, so
a failure to drain is only logged.
GQSPI_EN_OFST is then cleared, as zynqmp_qspi_remove() and
zynqmp_qspi_suspend() already do. Skip that write only when
pm_runtime_get_if_in_use() returns 0, i.e. runtime suspended: the clocks
are gated, so the registers are unreachable and the controller cannot be
mastering the bus. A negative return is not the same thing - it is what
the CONFIG_PM=n stub always returns, and there probe() has enabled pclk
and refclk for good, so the controller is running and must be stopped.
Fixes: dfe11a11d523 ("spi: Add support for Zynq Ultrascale+ MPSoC GQSPI controller")
Cc: stable@vger.kernel.org
Signed-off-by: Itai Handler <itai.handler@gmail.com>
Link: https://patch.msgid.link/20260910174832.873352-1-itai.handler@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
virtio_spi_transfer_one() puts spi->bits_per_word into the request
header, so a transfer that sets its own word size reaches the backend
with the device default instead. The SPI core has already copied that
default into xfer->bits_per_word when the transfer leaves it at zero,
the same way it does for xfer->speed_hz, which this function already
uses.
Per-transfer word sizes are ordinary SPI usage. mipi_dbi, for one, sends
a 9-bit command and reads the reply as 8-bit data in the same message.
With a 16-bit device default, a one-byte transfer asking for 8 bits goes
out as a partial 16-bit word, which the backend may reject.
Fixes: f98cabe3f6cf ("SPI: Add virtio SPI driver")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Hao-Qun Huang <alvinhuang0603@gmail.com>
Link: https://patch.msgid.link/20260913032049.11209.alvinhuang0603@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The description of commit bfb34eced559 ("mtd: rawnand: qcom: avoid writing
to obsolete register") says this:
"QPIC_EBI2_ECC_BUF_CFG register got obsolete from QPIC V2.0 onwards.
Avoid writing this register if QPIC version is V2.0 or newer."
Although the referenced commit is related to the 'qcom-nandc' driver,
however the hardware supported by the current driver is also based on
QPIC v2.0 so we should avoid writing that register here as well.
Remove the register writing code to avoid undefined behaviour.
Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
Reviewed-by: Md Sadre Alam <md.alam@oss.qualcomm.com>
Link: https://patch.msgid.link/20260909-qpic-snand-avoid-ebi2-reg-write-v1-1-9b1b1466cc75@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Remove an unnecessary cast to '__le32 *' in the qcom_spi_io_op()
function. The 'reg_read_buf' member of the 'qcom_nand_controller'
structure is defined as '__le32 *' already, so the cast is not
needed.
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
Link: https://patch.msgid.link/20260908-qpic-snand-unnecessary-cast-v1-1-26df1cdd4bb6@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
spi_new_ancillary_device() returns the new struct spi_device, or an
ERR_PTR() on failure, but its kernel-doc says "0 on success; negative
errno on failure", which was never true. Describe the pointer.
Fixes: 0c79378c0199 ("spi: add ancillary device support")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
Link: https://patch.msgid.link/20260911230211.11755-1-kmehltretter@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The dev_data variable in the qcom_spi_probe() function is only used
to temporarily store a pointer of the device specific data before that
value gets assigned to 'snandc->props'. Remove the interim variable
and use 'snandc->props' directly instead in order to simplify the code.
No functional changes.
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
Link: https://patch.msgid.link/20260908-qpic-snand-drop-dev_data-var-v1-1-147d3fab6c48@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
rockchip_sfc_probe enables runtime PM and leaves the device active with
a usage count held by pm_runtime_get_noresume(). The remove callback
only disables the clocks and does not disable runtime PM, leaving the
device in an inconsistent state and leaking the runtime PM reference.
Add the missing runtime PM teardown in rockchip_sfc_remove to balance
the probe's enable and get_noresume calls.
Signed-off-by: jiawen <1298662399@qq.com>
Link: https://patch.msgid.link/tencent_DD16C0EEDFEF4ACAFAB5A23EC8235D462707@qq.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The driver ignored clk_prepare_enable() failures for sclk during
probe and for core/sclk during runtime resume. Propagate the errors
and, on resume, disable core if enabling sclk fails, so probe/resume
do not continue with clocks disabled or report success falsely.
Fixes: cef9991e04ae ("spi: Add Amlogic SPISG driver")
Signed-off-by: Li Youhong <liyouhong@kylinos.cn>
Link: https://patch.msgid.link/20260831094553.2247003-1-dayou5941@163.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Vishwaroop A <va@nvidia.com> says:
The current threaded IRQ implementation in spi-tegra210-quad suffers
from scheduler-induced latency on heavily loaded systems. The old
irq_thread() runs SCHED_FIFO but is pinned by the kernel to the IRQ
affinity mask (typically one CPU); when that CPU is saturated by RT
workloads (e.g. NCCL multicast) or by an SPI transaction coming from
a higher-priority context, the sleeping DMA/PIO wait inside the IRQ
thread cannot progress and wait_for_completion_timeout() in
transfer_one_message expires - even though the QSPI hardware
finished on time. This results in false timeout errors and WARN_ON
splats during normal operation.
This series addresses the problem in three steps:
1. Convert the threaded IRQ handler to a hard IRQ + high-priority
unbound workqueue model. The hard IRQ does the minimum: capture
FIFO status, mask and clear the controller IRQ, then schedule the
bottom half. The workqueue handler runs in process context (can
sleep for DMA completion) and runs on any CPU in the WQ_UNBOUND
pool, so the bottom half can migrate off the interrupt-taking CPU
that the previous threaded IRQ pinned to via
set_cpus_allowed_ptr(irq_affinity).
2. Cache QSPI_TRANS_STATUS in the ISR before clearing it. This lets
the timeout handler distinguish between a real hardware timeout
(QSPI_RDY not set) and a delayed workqueue (QSPI_RDY set),
preventing false timeout errors when hardware has already
completed. Pair the cache publication with
smp_store_release()/smp_load_acquire() so the timeout handler
observes a coherent set of cached fields on weakly-ordered
architectures. In v6 the timeout handler is additionally serialised
with the workqueue via cancel_work_sync() and only runs the manual
completion fallback on the last chunk of a transfer (see "Changes
since v5" below for the multi-chunk DMA race Mark identified).
3. Process small PIO transfers (those that complete the whole
spi_transfer in a single chunk) directly in hard IRQ context,
eliminating workqueue scheduling latency for TPM-style short reads.
Runtime PM lifetime note (unchanged from v4): the work handler only
touches QSPI MMIO when curr_xfer is non-NULL. While curr_xfer is set,
the transfer thread is blocked in wait_for_completion_timeout() with
the SPI core's runtime PM reference held, so the clocks are
guaranteed on. When the work handler runs late after the timeout path
has already processed the transfer, it sees curr_xfer == NULL and
returns without any MMIO. With this invariant no additional PM
reference handoff between the ISR and the work handler is needed.
Link: https://patch.msgid.link/20260813200027.2711863-1-va@nvidia.com
|
|
On heavily loaded systems, workqueue scheduling delays can exceed
transfer timeouts even for high-priority queues, causing false
timeouts for latency-sensitive devices like TPM despite hardware
completing in microseconds.
Process small PIO transfers (those that complete the whole spi_transfer
in a single chunk) directly in hard IRQ context instead of deferring to
the workqueue. This reduces completion latency from 1000ms+ to
microseconds and matches the pattern used by other SPI drivers.
To avoid touching the spi_transfer object from hard IRQ context (which
would race with the synchronous teardown path that clears curr_xfer on
timeout), tegra_qspi_start_cpu_based_transfer() caches the "this PIO
chunk completes the whole transfer" decision into a scalar
tqspi->is_last_pio_chunk *before* unmasking the IRQ. The hard-IRQ
fastpath consumes that scalar with READ_ONCE() and never dereferences
curr_xfer or any spi_transfer fields. Multi-chunk PIO transfers are
intentionally kept on the workqueue (only the final chunk sets the
flag) so the fastpath can never recurse into
tegra_qspi_start_cpu_based_transfer() from hard IRQ context, and DMA
transfers always go through the workqueue because their completion
path sleeps on the DMA engine.
The fastpath also gates on the per-IRQ tx_status / rx_status locals
being zero, because handle_cpu_based_xfer()'s error path calls
tegra_qspi_reset() -> device_reset(), which can sleep and must not run
from hard IRQ context.
is_curr_dma_xfer and is_last_pio_chunk are written from process
context (the transfer-start functions) and read lock-free from the
hard IRQ handler and the workqueue handler, so the writes use
WRITE_ONCE() and the reads use READ_ONCE() to prevent compiler tearing
and silence KCSAN data-race warnings.
Signed-off-by: Vishwaroop A <va@nvidia.com>
Link: https://patch.msgid.link/20260813200027.2711863-4-va@nvidia.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
On heavily loaded systems the workqueue bottom half can be delayed
long enough for wait_for_completion_timeout() to expire before the
ISR's queued work actually runs. Reading QSPI_TRANS_STATUS directly
from the controller in the timeout handler races with both the
workqueue handler and the controller itself, and can mis-classify a
transfer that genuinely timed out as having "completed".
Cache the controller status captured by the hard IRQ before it is
acked, and let the timeout handler consume that cache:
- tegra_qspi_isr() reads QSPI_FIFO_STATUS and QSPI_TRANS_STATUS,
derives tx_status / rx_status, publishes them via WRITE_ONCE(),
and then publishes the trans_status cache via
smp_store_release() *before* masking and acking the controller
IRQ. Publish-before-clear is required so that a timeout handler
that fell back to a live QSPI_TRANS_STATUS read (because it saw
the cache still zero on another CPU) also sees the hardware
RDY bit that has not been cleared yet.
- tegra_qspi_handle_timeout() consumes trans_status with a paired
smp_load_acquire() and a cache-live-cache retry pattern. If the
initial cache load returns zero, the handler reads the live
QSPI_TRANS_STATUS register; if that also returns zero it retries
the cache once more. That closes the interleaving where an ISR
publishes trans_status with release semantics and then W1Cs the
hardware between the timeout handler's cache load and its live
load, otherwise leaving the timeout handler with cache = 0 and
HW = 0 (a false timeout on a transfer that has in fact just
completed).
- tegra_qspi_setup_transfer_one() and both
tegra_qspi_start_{cpu,dma}_based_transfer() paths clear the cache
with smp_store_release() under the spinlock before unmasking the
IRQ for the new chunk, so a stale RDY bit from a previous chunk
of a multi-chunk transfer cannot fool the handler.
Serialise handle_timeout with the workqueue and the ISR
unconditionally. Every expired wait_for_completion_timeout() enters
the recovery state: publish recovery_in_progress under tqspi->lock,
mask the controller IRQ, synchronize_irq() to drain any in-flight
hard IRQ (including the small-PIO fastpath), and cancel_work_sync()
to drain the workqueue. This holds regardless of whether the
hardware finished, because a genuine hardware timeout still races the
caller's dma_stop() + device_reset() + curr_xfer clear against a
delayed ISR or worker that arrives immediately after the status
sample. Classifying the timeout as -ETIMEDOUT only *after*
serialisation gives the caller a stable state to clean up.
Snapshot the live FIFO error status *before* entering recovery when
the ISR cache is empty and the live QSPI_TRANS_STATUS shows RDY (the
lost-IRQ path). tegra_qspi_mask_clear_irq() W1Cs QSPI_TRANS_STATUS
and the QSPI_FIFO_STATUS error bits, so a lost-IRQ recovery that
called it first would erase the very error state the manual handler
downstream needs to see. Capturing the snapshot before the mask and
publishing it into tqspi->{status_reg,tx_status,rx_status} after the
drain keeps the manual final-chunk handler operating on fresh error
data rather than stale fields from an earlier ISR run.
cancel_work_sync() cancels a pending worker without executing it and
waits for a currently running one to finish. The recovery_in_progress
guard is checked inside tegra_qspi_isr() under the same tqspi->lock
as its queue_work() and small-PIO fastpath dispatch decisions, so no
new bottom-half work is enqueued once we publish the flag.
synchronize_irq() closes the window where an ISR observed
recovery_in_progress == false, released the lock, and is about to
call queue_work(): we wait for that ISR to finish before draining
the workqueue, so its queued work is caught by cancel_work_sync().
After the drain, re-check the cache once more (the drained worker
may have published a completion status the entry snapshot did not
observe). If try_wait_for_completion() reports the whole transfer
completed, return success.
Restrict the manual fallback that invokes handle_{cpu,dma}_based_xfer()
from process context to the last chunk of a transfer. On an
intermediate chunk of a multi-chunk DMA transfer the work handler
may have processed the current chunk and armed the next chunk
(unmasked the IRQ and kicked HW) before cancel_work_sync() returned;
running another handler here would let the caller's seq_xfer clear
curr_xfer and finalise the message while the DMA engine is still
moving the next chunk into the client buffer. Return -ETIMEDOUT in
that case and let the caller's existing dma_stop() + reset() path
clean up.
Before returning, re-mask the controller IRQ and synchronize_irq()
one more time. The drained bottom half may have unmasked the IRQ
when arming a subsequent chunk; without the re-mask a lingering
RDY IRQ that arrives after this function returns could invoke the
ISR and queue a worker after recovery_in_progress has been cleared,
racing the caller's cleanup of curr_xfer.
Signed-off-by: Vishwaroop A <va@nvidia.com>
Link: https://patch.msgid.link/20260813200027.2711863-3-va@nvidia.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Threaded IRQ handlers can be delayed by the scheduler on heavily loaded
systems, causing wait_for_completion_timeout() to expire before the
handler runs and producing false transfer timeouts. On GB200 with TPM
hwrng traffic running alongside a NCCL multicast workload this shows up
as a WARN in tegra_qspi_transfer_one_message() even though the hardware
has already signalled QSPI_RDY.
irq_thread() runs SCHED_FIFO but set_cpus_allowed_ptr()s to the IRQ
affinity mask (typically a single CPU). When that CPU is saturated by
non-preemptible kernel work on the same interrupt line (softirqs,
spinlock contention, network RX processing), the FIFO priority alone
does not help - there is nothing at lower priority to preempt. The
bottom half sits on the runqueue for milliseconds and occasionally
seconds.
Convert to a hard IRQ handler that schedules work on a WQ_HIGHPRI |
WQ_UNBOUND workqueue:
- The hard IRQ handler runs outside process-scheduler control - it
can still be delayed by higher-priority IRQ handling or local
IRQ-disabled / non-preemptible sections, but not by CFS or
RT-userspace backpressure. tegra_qspi_isr() captures FIFO / trans
status and masks the controller IRQ synchronously with the
hardware event, so the subsequent timeout classification (added
in the following patch) always sees the true state.
- The workqueue worker runs SCHED_NORMAL with HIGHPRI_NICE_LEVEL
(nice -20). A real-time SCHED_FIFO userspace task will preempt it
where it would not have preempted the old irq_thread; that is a
real trade-off. In exchange, WQ_UNBOUND lets the worker migrate
off the interrupt-taking CPU that the threaded IRQ could not
leave, which is the actual failure mode observed in the field.
The following patch (small-PIO fastpath) further removes the
worker from the latency-sensitive TPM path entirely.
The work handler only touches QSPI MMIO when curr_xfer is non-NULL.
curr_xfer is cleared only after the transfer thread has processed the
completion, and while it is set the transfer thread is blocked in
wait_for_completion_timeout() with the SPI core's runtime PM reference
held, so the clocks are guaranteed on.
The ISR returns IRQ_HANDLED unconditionally. Tegra QSPI has a
dedicated, non-shared GIC SPI line on every SoC that uses this driver,
so any spurious / late IRQ (for example after the timeout path has
cleared curr_xfer) must still be acked and re-masked here; otherwise
the level-triggered line could stay asserted and trip the kernel
spurious-IRQ detector into disabling the line ("nobody cared, try to
disable"). The lock-free curr_xfer NULL check lets the ISR bail
without touching FIFO / status when there is no transfer to drive
forward.
handle_dma_based_xfer() snapshots curr_xfer under the spinlock at
function entry and bails immediately when the timeout path has already
cleared it. This avoids waiting up to QSPI_DMA_TIMEOUT on a DMA
completion that belongs to a transfer the synchronous path has already
torn down, and keeps the subsequent dma_unmap / FIFO-drain operations
consistent with the transfer that actually started.
Resources are allocated and torn down manually so that remove() can
stop the controller, free the IRQ (preventing new work from being
queued), then destroy the workqueue (which drains any already-queued
work while the clocks are still on) before runtime PM is disabled.
Signed-off-by: Vishwaroop A <va@nvidia.com>
Link: https://patch.msgid.link/20260813200027.2711863-2-va@nvidia.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Switch to devm_spi_register_controller() and drop the unneeded
.remove callback and dev_set_drvdata().
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Link: https://patch.msgid.link/20260907-ar934x-v1-1-71327eb482bc@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
orion_spi_wait_till_ready() busy-waits in a tight udelay(1) loop, up to
2000 iterations, and is called per byte from the polled, byte-at-a-time
transfer path. On SoCs such as the Armada 388 (e.g. SolidRun Helios4),
which also run SATA over the shared internal MBus fabric, this stalls
the CPU for the whole transfer and delays servicing of SATA interrupts.
Under sustained activity this can cause SATA timeouts and link resets
(sometimes renegotiating down to SATA II, 3 Gbps).
Add cond_resched() to the wait loop so the scheduler can run pending
IRQs between polls. This is a no-op at runtime unless the kernel is
built with CONFIG_PREEMPT enabled, where it lets other peripheral
interrupts be serviced during SPI transfers.
Built with LLVM=1 ARCH=powerpc; passes checkpatch --strict.
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://patch.msgid.link/20260907005750.230103-1-rosenp@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Fix typos in comments, reported by scripts/checkpatch.pl using the
misspelling list in scripts/spelling.txt. Only touches comments, no code
changes.
Assisted-by: Cursor:claude-opus-5
Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
Link: https://patch.msgid.link/20260904110420.13707-1-hemanth.selam@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Miquel Raynal <miquel.raynal@bootlin.com> says:
Mark pointed out that the DTR capability was not correctly enabled since
I had to set the extra ctlr->dtr_caps flag. For testing, I commented out
the spi-mem ops/caps and figured out DTR variants were still not picked
up. This was due to the spi-mem fallback implementation of ->exec_op()
not forwarding the DTR flag.
Link: https://patch.msgid.link/20260904-perso-ma35d1-master-v1-0-b6936e8c6fa1@bootlin.com
|
|
The feature was implemented but not actually enabled for regular SPI
operations (as opposed to spi-mem operations). Make sure the missing
capability is actually set.
Reported-by: Mark Brown <broonie@kernel.org>
Closes: https://lore.kernel.org/all/09c3928f-4b58-4ac6-8e1a-84dfe3ff6b92@sirena.org.uk/
Fixes: 15e9362f6190 ("spi: ma35d1-qspi: Add DTR support")
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://patch.msgid.link/20260904-perso-ma35d1-master-v1-2-b6936e8c6fa1@bootlin.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Most spi-mem operations today go through controllers implementing the
spi-mem API. But it is also totally possible to use any standard SPI
controller to operate these memories. If the controllers support DTR,
there is no reason to prevent this feature from being used.
Extend spi_mem_exec_op()'s fallback to the standard SPI API, by filling
the transfer DTR information. Doing so also requires checking the
dtr_caps flag, of course.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://patch.msgid.link/20260904-perso-ma35d1-master-v1-1-b6936e8c6fa1@bootlin.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
This is another run of the Coccinelle script for converting kmalloc()
family of allocations to kmalloc_obj() via the existing rules in
scripts/coccinelle/api/kmalloc_objs.cocci
This catches both the set of kmalloc() uses added since the first
kmalloc_obj() conversions in v7.0 and adds a large group missed in the
first pass due to Coccinelle not interacting well with the cleanup.h
scoped_...() family of macros[1]. I worked around this with spatch's
"--macro-file" argument to a file with all the scoped_...() macros mapped
to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control
flow indicator I could find.
Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc,
riscv, and s390 with no new warnings.
Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1]
Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2]
Signed-off-by: Kees Cook <kees+treewide@kernel.org>
|
|
mtk_nor_probe() takes a runtime PM reference with
pm_runtime_get_noresume() before registering the controller, but the
error path never drops it.
Balance the get with pm_runtime_put_noidle() in the error path.
Fixes: 3bfd9103c7af ("spi: spi-mtk-nor: Add power management support")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Link: https://patch.msgid.link/20260904-mtk-nor-v1-1-cefdca098f83@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
nuvoton_qspi_probe() pulses the exclusive reset and leaves it
deasserted for normal operation. Later probe failures returned
without re-asserting the reset, leaving the controller out of
reset after a failed probe. Assert the reset on those error
paths.
Fixes: 78b16af159ae ("spi: ma35d1-qspi: Add Nuvoton MA35D1 QSPI controller support")
Signed-off-by: Li Youhong <liyouhong@kylinos.cn>
Link: https://patch.msgid.link/20260901025129.359960-1-dayou5941@163.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
When the rx channel request fails, the driver carries on without DMA
but the tx channel it already acquired stayed claimed until devm
teardown.
Release it on the error path so it goes straight back to the DMA
engine for other users.
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Link: https://patch.msgid.link/20260904-ingenic-v1-1-06218181a4f8@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Xianwei Zhao <xianwei.zhao@amlogic.com> says:
Add bindings for A9 with some features, and driver for A9 base on A4.
Fix the incorrect keep_ss of the last descriptor.
Link: https://patch.msgid.link/20260731-a9-spisg-v3-0-a15da3f70029@amlogic.com
|
|
The Amlogic A9 SPISG controller extends the A4 controller with additional
configuration options, including:
- Extended CS setup timing
- Hardware-controlled CS hold timing
- MOSI idle output configuration
- Configurable word delay
Add SoC-specific capability data and configure these features when they
are supported by the underlying hardware while keeping compatibility with
existing A4 controllers.
Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
Link: https://patch.msgid.link/20260731-a9-spisg-v3-4-a15da3f70029@amlogic.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The driver currently unconditionally clears CFG_KEEP_SS on the last
descriptor, causing the last transfer's cs_change setting to be ignored.
Record the cs_change value of the last SPI transfer and use it to
program CFG_KEEP_SS on the final descriptor. When a null descriptor is
inserted to implement the cs-hold delay, keep CFG_KEEP_SS set on the
preceding transfer descriptor and apply the recorded value to the final
descriptor instead.
This ensures the controller handles chip select correctly for the last
transfer regardless of whether a cs-hold delay is required.
Fixes: cef9991e04ae ("spi: Add Amlogic SPISG driver")
Signed-off-by: Sunny Luo <sunny.luo@amlogic.com>
Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
Link: https://patch.msgid.link/20260731-a9-spisg-v3-3-a15da3f70029@amlogic.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The CFG_BLOCK_NUM field can encode at most 20 bits, so reduce
SPISG_BLOCK_MAX to 0xfffff to avoid programming a zero-length transfer.
Perform the delay calculation in 64-bit arithmetic to avoid overflow
when converting nanoseconds to SPI clock cycles.
Stop the controller on transfer timeout by clearing the descriptor list
register before returning an error.
Fixes: cef9991e04ae ("spi: Add Amlogic SPISG driver")
Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
Link: https://patch.msgid.link/20260731-a9-spisg-v3-2-a15da3f70029@amlogic.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Praveen Talari <praveen.talari@oss.qualcomm.com> says:
On VM-based platforms, if an SPI DMA transfer is in progress when the
guest is torn down (via reboot/shutdown or a panic/crash), the DMA
engine can keep issuing transactions to IOVAs that have already been
invalidated as part of teardown. The SMMU then raises context faults,
which can affect other VMs sharing the same SMMU instance and obscure
the real root cause of the crash.
This series adds two independent quiesce paths for the GENI SPI
controller so that any in-progress transfer is stopped and the DMA
engine is left idle before the IOVA mappings are torn down:
- Patch 1 adds a platform shutdown() callback that suspends the SPI
controller (via spi_controller_suspend()) on a normal
reboot/shutdown path, where sleeping is safe.
- Patch 2 registers a panic notifier that cancels/aborts the
in-flight command and resets the TX/RX DMA FSMs (or terminates the
GPI DMA channels) when the kernel panics, covering the crash path
as well. The notifier bails out early if the device is not
runtime-active or has no active command, and otherwise uses
readl_poll_timeout_atomic() to poll status registers directly
instead of waiting on completions/IRQs like the regular
error-handling path does, since panic notifiers run with IRQs and
preemption disabled. The notifier is registered before
devm_spi_register_controller() so a panic during child device
probing is still handled.
Link: https://patch.msgid.link/20260818-add-shutdown-and-panic-notifier-for-spi-v3-0-8b62c4bc2d21@oss.qualcomm.com
|
|
When a VM crashes with an active SPI DMA transfer in progress, the
SMMU raises context faults as the DMA engine continues to access
IOVAs that are invalidated when the VM's memory context is torn down.
These faults can affect other VMs sharing the same SMMU instance and
obscure the root cause of the crash.
Register a panic notifier that cancels (or aborts, if cancel doesn't
complete) the in-flight command and resets the TX/RX DMA FSMs, so the
DMA engine stops issuing transactions against invalidated IOVAs
before the system halts. For GPI DMA mode, the DMA channels are
terminated directly via dmaengine_terminate_async().
The notifier bails out early if the device is not runtime-active or
if there's no active GENI command, avoiding unnecessary register
accesses while the SE is clock-gated or idle.
Since panic notifiers run with IRQs and preemption disabled,
completion-based waits used by the regular error-handling path
(handle_se_timeout()) cannot be reused here. Instead, the relevant
status registers are polled directly with
readl_poll_timeout_atomic(), which is safe to call in this context.
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
Link: https://patch.msgid.link/20260818-add-shutdown-and-panic-notifier-for-spi-v3-2-8b62c4bc2d21@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
During system reboot, an active SPI transfer can leave the GENI Serial
Engine in an indeterminate state. On VM-based platforms, if a DMA
transfer is in progress when the VM is shut down, the SMMU can raise
context faults as the DMA engine continues to access IOVAs that have
already been invalidated during VM teardown.
Add a shutdown callback to suspend the SPI controller and abort any
in-progress transfer, ensuring the DMA engine is idle and all IOVA
mappings are retired before the system resets.
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
Link: https://patch.msgid.link/20260818-add-shutdown-and-panic-notifier-for-spi-v3-1-8b62c4bc2d21@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
pm_runtime_put_sync() is called in the probe error path and in remove
when nothing holds a runtime PM reference anymore, so it underflows
the usage count.
Fixes: 0e6f357a5deb ("spi: omap2-mcspi: Fix PM regression with deferred probe for pm_runtime_reinit")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Link: https://patch.msgid.link/20260826-mcspi-v1-1-0a8dd7f6dd56@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
void
The function always returned 0 and had no error paths, so change its
return type to void. Drop the now-dead ret variable and error check
in spi_geni_prepare_message().
setup_fifo_params() is called for both GENI_SE_FIFO and GENI_SE_DMA
modes, so the "fifo" in the name is misleading. Rename it to
setup_spi_params() to better reflect its purpose of configuring SPI
mode parameters (CS, CPHA, CPOL, loopback, LSB-first).
No functional change.
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
Link: https://patch.msgid.link/20260824-spi-qcom-geni-cleanup-setup-fifo-params-v1-1-bdf98ae62953@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
wait_for_completion_interruptible_timeout() returns -ERESTARTSYS when
interrupted by a signal, 0 on timeout, and positive on success. The
previous check was:
if (!wait_for_completion_interruptible_timeout(...))
SIGKILL caused the interrupted path to fall through as if the transfer
succeeded. The loop then re-entered mutex_lock() on the next
iteration, which is TASK_UNINTERRUPTIBLE. The process could not be
killed while blocked there.
Check ret <= 0 and return -EINTR for the interrupted case so the process
can exit promptly on SIGKILL.
Signed-off-by: Andrew Gaylard <ag@ffroot.co.za>
Link: https://patch.msgid.link/20260820125835.1584270-1-ag@ffroot.co.za
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
sh_msiof_spi_setup() ignores pm_runtime_get_sync() before programming
native chip-select registers and marking the configuration initialized.
Use the checked runtime-PM helper and return failure before register
access.
Fixes: 7ff0b53c4051 ("spi: sh-msiof: Avoid writing to registers from spi_master.setup()")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260830140133.24156-1-pengpeng@iscas.ac.cn
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Andy Shevchenko <andriy.shevchenko@linux.intel.com> says:
With time the section order is diverged, put it back into order.
Link: https://patch.msgid.link/20260821105541.1432348-1-andriy.shevchenko@linux.intel.com
|
|
The comments in all sections tell that the list of the sections
should be alphabetically ordered. With time this went apart,
mostly for Freescale entries. So, put the things into order again.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260821105541.1432348-4-andriy.shevchenko@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The sections defined under 'if SPI_MASTER' already imply that
the SPI_MASTER is selected. Drop redundant dependencies.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260821105541.1432348-3-andriy.shevchenko@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
There are a couple of sections which indented using spaces and
not tabs. Fix them.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260821105541.1432348-2-andriy.shevchenko@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The completion iused for SPI transfers is initialized twice in the
same function, without it being used in between. Drop the redundant
initialization.
Signed-off-by: Francesco Valla <francesco@valla.it>
Link: https://patch.msgid.link/20260830-virtio-spi-fix-v1-1-62f486f4acdc@valla.it
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown:
"A couple of fixes that came in during the merge window: Geert fixed an
uninitialised data bug in the amlogic-spisg driver which could crash
and in the Loongson driver Li Jun hooked up the existing suspend
operations more fully to fix hibernation"
* tag 'spi-fix-v7.3-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
spi: loongson: pm: add .freeze .poweroff .thaw .restore
spi: amlogic-spisg: Make sure clk_init_data is fully initialized
|
|
after execute s4, the spi error,
[ 1104.754246][ 4] [ T1] tpm_tis_spi spi-SMO0768:00: SPI transfer failed: -110
[ 1104.761503][ 4] [ T1] spi_master spi1: failed to transfer one message from queue
[ 1104.769201][ 4] [ T1] spi_master spi1: noqueue transfer failed
[ 1104.776344][ 4] [ T1] tpm_tis_spi spi-SMO0768:00: SPI transfer failed: -110
[ 1104.783609][ 4] [ T1] spi_master spi1: failed to transfer one message from queue
[ 1104.791308][ 4] [ T1] spi_master spi1: noqueue transfer failed
[ 1104.797446][ 4] [ T1] gttadd tpm_chip_start1 ret = -110
and in s4 the loongson_spi_resume&suspend are not
called at all. use DEFINE_SIMPLE_DEV_PM_OPS() add .freeze .poweroff
.thaw .restore, after s4 the spi communication is normal.
Signed-off-by: Li Jun <lijun01@kylinos.cn>
Link: https://patch.msgid.link/20260820092351.101605-1-lijun01@kylinos.cn
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The clk_init_data structure contains several mutually-exclusive members
for different methods to specify the possible parents of a clock,
prompting drivers to initialize only the members they need. However,
not initializing all members may cause subtle issues, which are only
exposed when CONFIG_INIT_STACK_ALL_PATTERN or CONFIG_INIT_STACK_NONE is
enabled.
aml_spisg_clk_init() fills in init.parent_data, and assumes that
init.parent_names is NULL. However, the latter in uninitialized, and
thus may cause a crash.
Make sure all members are fully initialized, to fix such bugs, and to
avoid future breakage when converting drivers to a different method for
specifying the parents.
Fixes: cef9991e04aed330 ("spi: Add Amlogic SPISG driver")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Reviewed-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
Link: https://patch.msgid.link/9fb35ae0aedb7a6db0db6c78a8193c7602dd9d44.1787165329.git.geert+renesas@glider.be
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"Along with a lot of driver specific work we've got a couple of core
features here. The bigger one is that we've now got support for
instantiating devices from sysfs similarly to how it's already done
for I2C, this is used with development boards with non-enumerable
expansion headers since SPI devices need to be manually specified. We
also have support for the DQS signal on higher end flash devices.
- Support for instantiating devices from sysfs, useful for
development boards with non-enumerable plugin modules, from
Vishwaroop A.
- Support for DQS in spi-mem, an additional signal used by flash
devices to avoid clock skew from Miquel Raynal.
- Support for more advanced SPI modes on DesignWare controllers from
Sudip Mukherjee.
- Changes from Jisheng Zhang to update to modern methods of
specifying the PM callbacks.
- Fixes for DMA mapping error handling, plus KUnit tests for this,
from Honghui Jiang.
- Substantial cleanup and performance work in the nxp-spi driver.
- Support for Microchip LAN969x, Nuvoton MA35D1 QSPI, Qualcomm
SA8255p and SA8797P, and StarFive JHB100 SFC"
* tag 'spi-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (132 commits)
spi: Add KUnit coverage for DMA mapping error paths
spi: Clear current DMA devices when unmapping a message
spi: Move __spi_unmap_msg() before __spi_map_msg()
spi: Fix DMA mapping ownership on partial map failure
spi: dt-bindings: sun6i: Add compatibles for A733's SPI controllers
spi: ma35d1-qspi: Use the existing update helper
spi: ma35d1-qspi: Add DTR support
spi: ma35d1-qspi: Allow several command bytes
spi: ma35d1-qspi: Move speed setting to bus configuration
spi: ma35d1-qspi: Remove redundant reset operation
spi: dw: Remove shadowed dws in dw_spi_setup()
spi: img-spfi: don't disable runtime PM on DMA deferred probe
spi: mtk-nor: Propagate errors from IRQ request
spi: mtk-nor: Propagate errors from optional IRQ lookup
spi: spi-qpic-snand: Handle Macronix quad read opcode 0x6b
spi: spi-qpic-snand: add quad mode support
spi: spi-qpic-snand: move command mapping helper
spi: hisi-sfc-v3xx: Propagate errors from optional IRQ lookup
spi: meson-spifc: use devm_pm_runtime_set_active_enabled
spi: sprd-adi: Fix probe succeeding without registering the controller
...
|