spi: fix resource leaks on device setup failure

Johan Hovold <johan@kernel.org> says:

Make sure to call controller cleanup() if spi_setup() fails while
registering a device to avoid leaking any resources allocated by
setup().
This commit is contained in:
Mark Brown
2026-04-22 15:10:22 +01:00
2 changed files with 38 additions and 25 deletions

View 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);

View File

@@ -701,7 +701,7 @@ struct spi_controller {
int (*transfer)(struct spi_device *spi,
struct spi_message *mesg);
/* Called on release() to free memory provided by spi_controller */
/* Called on deregistration to free memory provided by spi_controller */
void (*cleanup)(struct spi_device *spi);
/*