]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
spi: cadence-qspi: Fix exec_mem_op error handling
authorEmanuele Ghidoli <emanuele.ghidoli@toradex.com>
Fri, 13 Mar 2026 13:52:31 +0000 (14:52 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 30 Mar 2026 20:34:53 +0000 (21:34 +0100)
cqspi_exec_mem_op() increments the runtime PM usage counter before all
refcount checks are performed. If one of these checks fails, the function
returns without dropping the PM reference.

Move the pm_runtime_resume_and_get() call after the refcount checks so
that runtime PM is only acquired when the operation can proceed and
drop the inflight_ops refcount if the PM resume fails.

Cc: stable@vger.kernel.org
Fixes: 7446284023e8 ("spi: cadence-quadspi: Implement refcount to handle unbind during busy")
Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
Link: https://patch.msgid.link/20260313135236.46642-1-ghidoliemanuele@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-cadence-quadspi.c

index 5fb0cb07c110cc1ddfdf5fdb497b8ad7aa0cf3b7..2ead419e896e2df18ce07ee0833cf523722db802 100644 (file)
@@ -1483,14 +1483,6 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
        if (refcount_read(&cqspi->inflight_ops) == 0)
                return -ENODEV;
 
-       if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
-               ret = pm_runtime_resume_and_get(dev);
-               if (ret) {
-                       dev_err(&mem->spi->dev, "resume failed with %d\n", ret);
-                       return ret;
-               }
-       }
-
        if (!refcount_read(&cqspi->refcount))
                return -EBUSY;
 
@@ -1502,6 +1494,14 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
                return -EBUSY;
        }
 
+       if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) {
+               ret = pm_runtime_resume_and_get(dev);
+               if (ret) {
+                       dev_err(&mem->spi->dev, "resume failed with %d\n", ret);
+                       goto dec_inflight_refcount;
+               }
+       }
+
        ret = cqspi_mem_process(mem, op);
 
        if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM)))
@@ -1510,6 +1510,7 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
        if (ret)
                dev_err(&mem->spi->dev, "operation failed with %d\n", ret);
 
+dec_inflight_refcount:
        if (refcount_read(&cqspi->inflight_ops) > 1)
                refcount_dec(&cqspi->inflight_ops);