OSDN Git Service

spi: spi_register_controller(): free bus id on error paths
authorAaro Koskinen <aaro.koskinen@nokia.com>
Wed, 4 Mar 2020 11:17:40 +0000 (13:17 +0200)
committerMark Brown <broonie@kernel.org>
Wed, 4 Mar 2020 14:28:57 +0000 (14:28 +0000)
Some error paths leave the bus id allocated. As a result the IDR
allocation will fail after a deferred probe. Fix by freeing the bus id
always on error.

Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
Message-Id: <20200304111740.27915-1-aaro.koskinen@nokia.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi.c

index 197c9e0..94145b2 100644 (file)
@@ -2645,7 +2645,7 @@ int spi_register_controller(struct spi_controller *ctlr)
                if (ctlr->use_gpio_descriptors) {
                        status = spi_get_gpio_descs(ctlr);
                        if (status)
-                               return status;
+                               goto free_bus_id;
                        /*
                         * A controller using GPIO descriptors always
                         * supports SPI_CS_HIGH if need be.
@@ -2655,7 +2655,7 @@ int spi_register_controller(struct spi_controller *ctlr)
                        /* Legacy code path for GPIOs from DT */
                        status = of_spi_get_gpio_numbers(ctlr);
                        if (status)
-                               return status;
+                               goto free_bus_id;
                }
        }
 
@@ -2663,17 +2663,14 @@ int spi_register_controller(struct spi_controller *ctlr)
         * Even if it's just one always-selected device, there must
         * be at least one chipselect.
         */
-       if (!ctlr->num_chipselect)
-               return -EINVAL;
+       if (!ctlr->num_chipselect) {
+               status = -EINVAL;
+               goto free_bus_id;
+       }
 
        status = device_add(&ctlr->dev);
-       if (status < 0) {
-               /* free bus id */
-               mutex_lock(&board_lock);
-               idr_remove(&spi_master_idr, ctlr->bus_num);
-               mutex_unlock(&board_lock);
-               goto done;
-       }
+       if (status < 0)
+               goto free_bus_id;
        dev_dbg(dev, "registered %s %s\n",
                        spi_controller_is_slave(ctlr) ? "slave" : "master",
                        dev_name(&ctlr->dev));
@@ -2689,11 +2686,7 @@ int spi_register_controller(struct spi_controller *ctlr)
                status = spi_controller_initialize_queue(ctlr);
                if (status) {
                        device_del(&ctlr->dev);
-                       /* free bus id */
-                       mutex_lock(&board_lock);
-                       idr_remove(&spi_master_idr, ctlr->bus_num);
-                       mutex_unlock(&board_lock);
-                       goto done;
+                       goto free_bus_id;
                }
        }
        /* add statistics */
@@ -2708,7 +2701,12 @@ int spi_register_controller(struct spi_controller *ctlr)
        /* Register devices from the device tree and ACPI */
        of_register_spi_devices(ctlr);
        acpi_register_spi_devices(ctlr);
-done:
+       return status;
+
+free_bus_id:
+       mutex_lock(&board_lock);
+       idr_remove(&spi_master_idr, ctlr->bus_num);
+       mutex_unlock(&board_lock);
        return status;
 }
 EXPORT_SYMBOL_GPL(spi_register_controller);