]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
spi: fix resource leaks on device setup failure
authorJohan Hovold <johan@kernel.org>
Fri, 10 Apr 2026 15:49:06 +0000 (17:49 +0200)
committerMark Brown <broonie@kernel.org>
Wed, 22 Apr 2026 14:10:17 +0000 (15:10 +0100)
Make sure to call controller cleanup() if spi_setup() fails while
registering a device to avoid leaking any resources allocated by
setup().

Fixes: c7299fea6769 ("spi: Fix spi device unregister flow")
Cc: stable@vger.kernel.org # 5.13
Cc: Saravana Kannan <saravanak@kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260410154907.129248-2-johan@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi.c

index a0b2bd3b8186504a2430b192660339c4e6d21874..3e434a9885bc3cc4403f6ab36d0bc9bd77b09fdc 100644 (file)
@@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
 
 #include "internals.h"
 
+static int __spi_setup(struct spi_device *spi, bool initial_setup);
+
 static DEFINE_IDR(spi_controller_idr);
 
 static void spidev_release(struct device *dev)
@@ -743,7 +745,7 @@ static int __spi_add_device(struct spi_device *spi, struct spi_device *parent)
         * normally rely on the device being setup.  Devices
         * using SPI_CS_HIGH can't coexist well otherwise...
         */
-       status = spi_setup(spi);
+       status = __spi_setup(spi, true);
        if (status < 0) {
                dev_err(dev, "can't setup %s, status %d\n",
                                dev_name(&spi->dev), status);
@@ -4049,27 +4051,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
        return status;
 }
 
-/**
- * spi_setup - setup SPI mode and clock rate
- * @spi: the device whose settings are being modified
- * Context: can sleep, and no requests are queued to the device
- *
- * SPI protocol drivers may need to update the transfer mode if the
- * device doesn't work with its default.  They may likewise need
- * to update clock rates or word sizes from initial values.  This function
- * changes those settings, and must be called from a context that can sleep.
- * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
- * effect the next time the device is selected and data is transferred to
- * or from it.  When this function returns, the SPI device is deselected.
- *
- * Note that this call will fail if the protocol driver specifies an option
- * that the underlying controller or its driver does not support.  For
- * example, not all hardware supports wire transfers using nine bit words,
- * LSB-first wire encoding, or active-high chipselects.
- *
- * Return: zero on success, else a negative error code.
- */
-int spi_setup(struct spi_device *spi)
+static int __spi_setup(struct spi_device *spi, bool initial_setup)
 {
        unsigned        bad_bits, ugly_bits;
        int             status;
@@ -4154,7 +4136,7 @@ int spi_setup(struct spi_device *spi)
        status = spi_set_cs_timing(spi);
        if (status) {
                mutex_unlock(&spi->controller->io_mutex);
-               return status;
+               goto err_cleanup;
        }
 
        if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
@@ -4163,7 +4145,7 @@ int spi_setup(struct spi_device *spi)
                        mutex_unlock(&spi->controller->io_mutex);
                        dev_err(&spi->controller->dev, "Failed to power device: %d\n",
                                status);
-                       return status;
+                       goto err_cleanup;
                }
 
                /*
@@ -4199,6 +4181,37 @@ int spi_setup(struct spi_device *spi)
                        status);
 
        return status;
+
+err_cleanup:
+       if (initial_setup)
+               spi_cleanup(spi);
+
+       return status;
+}
+
+/**
+ * spi_setup - setup SPI mode and clock rate
+ * @spi: the device whose settings are being modified
+ * Context: can sleep, and no requests are queued to the device
+ *
+ * SPI protocol drivers may need to update the transfer mode if the
+ * device doesn't work with its default.  They may likewise need
+ * to update clock rates or word sizes from initial values.  This function
+ * changes those settings, and must be called from a context that can sleep.
+ * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
+ * effect the next time the device is selected and data is transferred to
+ * or from it.  When this function returns, the SPI device is deselected.
+ *
+ * Note that this call will fail if the protocol driver specifies an option
+ * that the underlying controller or its driver does not support.  For
+ * example, not all hardware supports wire transfers using nine bit words,
+ * LSB-first wire encoding, or active-high chipselects.
+ *
+ * Return: zero on success, else a negative error code.
+ */
+int spi_setup(struct spi_device *spi)
+{
+       return __spi_setup(spi, false);
 }
 EXPORT_SYMBOL_GPL(spi_setup);