media: ov8865: Disable only enabled regulators on error path
authorSakari Ailus <sakari.ailus@linux.intel.com>
Wed, 15 Dec 2021 08:38:48 +0000 (09:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jan 2022 10:02:54 +0000 (11:02 +0100)
commit cbe0b3af73bf72fad197756f026084404e2bcdc7 upstream.

If powering on the sensor failed, the entire power-off sequence was run
independently of how far the power-on sequence proceeded before the error.
This lead to disabling regulators and/or clock that was not enabled.

Fix this by disabling only clocks and regulators that were enabled
previously.

Fixes: 11c0d8fdccc5 ("media: i2c: Add support for the OV8865 image sensor")
Cc: stable@vger.kernel.org
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/media/i2c/ov8865.c

index ce50f3ea87b8e9b4db5f909d73c9d4387e765a81..ff8908a38061a379b8921a80f5b7edf5c48e304c 100644 (file)
@@ -2330,27 +2330,27 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on)
                if (ret) {
                        dev_err(sensor->dev,
                                "failed to enable DOVDD regulator\n");
-                       goto disable;
+                       return ret;
                }
 
                ret = regulator_enable(sensor->avdd);
                if (ret) {
                        dev_err(sensor->dev,
                                "failed to enable AVDD regulator\n");
-                       goto disable;
+                       goto disable_dovdd;
                }
 
                ret = regulator_enable(sensor->dvdd);
                if (ret) {
                        dev_err(sensor->dev,
                                "failed to enable DVDD regulator\n");
-                       goto disable;
+                       goto disable_avdd;
                }
 
                ret = clk_prepare_enable(sensor->extclk);
                if (ret) {
                        dev_err(sensor->dev, "failed to enable EXTCLK clock\n");
-                       goto disable;
+                       goto disable_dvdd;
                }
 
                gpiod_set_value_cansleep(sensor->reset, 0);
@@ -2359,14 +2359,16 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on)
                /* Time to enter streaming mode according to power timings. */
                usleep_range(10000, 12000);
        } else {
-disable:
                gpiod_set_value_cansleep(sensor->powerdown, 1);
                gpiod_set_value_cansleep(sensor->reset, 1);
 
                clk_disable_unprepare(sensor->extclk);
 
+disable_dvdd:
                regulator_disable(sensor->dvdd);
+disable_avdd:
                regulator_disable(sensor->avdd);
+disable_dovdd:
                regulator_disable(sensor->dovdd);
        }