The driver acquires the 'vbat' regulator during probing but never enables
it. Consequently, in the suspend method, the driver disables the regulator
without enabling it first, causing an 'Unbalanced regulator_disable()'
error.
Enable the regulator in the probe() method and add the remove() method with
regulator disabling to fix this.
Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
---
drivers/input/misc/drv260x.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index c4dd410c303e..71fbdabc6589 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -520,19 +520,37 @@ static int drv260x_probe(struct i2c_client *client)
return error;
}
+ error = regulator_enable(haptics->regulator);
+ if (error) {
+ dev_err(dev, "Failed to enable regulator\n");
+ return error;
+ }
+
error = drv260x_init(haptics);
if (error) {
dev_err(dev, "Device init failed: %d\n", error);
- return error;
+ goto err_regulator_disable;
}
error = input_register_device(haptics->input_dev);
if (error) {
dev_err(dev, "couldn't register input device: %d\n", error);
- return error;
+ goto err_regulator_disable;
}
return 0;
+
+err_regulator_disable:
+ regulator_disable(haptics->regulator);
+
+ return error;
+}
+
+static void drv260x_remove(struct i2c_client *client)
+{
+ struct drv260x_data *haptics = i2c_get_clientdata(client);
+
+ regulator_disable(haptics->regulator);
}
static int drv260x_suspend(struct device *dev)
@@ -626,6 +644,7 @@ MODULE_DEVICE_TABLE(of, drv260x_of_match);
static struct i2c_driver drv260x_driver = {
.probe = drv260x_probe,
+ .remove = drv260x_remove,
.driver = {
.name = "drv260x-haptics",
.of_match_table = drv260x_of_match,
--
2.51.0
Hi Yauhen,
On Sun, Feb 15, 2026 at 04:14:34PM +0200, Yauhen Kharuzhy wrote:
> +static void drv260x_remove(struct i2c_client *client)
> +{
> + struct drv260x_data *haptics = i2c_get_clientdata(client);
> +
> + regulator_disable(haptics->regulator);
> }
This will result in power being shut off the first thing during
unbinding, which is too early.
I switched this to devm_add_action_or_reset() and applied.
Thanks.
--
Dmitry
On Wed, Feb 18, 2026 at 06:43:30PM -0800, Dmitry Torokhov wrote:
> Hi Yauhen,
>
> On Sun, Feb 15, 2026 at 04:14:34PM +0200, Yauhen Kharuzhy wrote:
> > +static void drv260x_remove(struct i2c_client *client)
> > +{
> > + struct drv260x_data *haptics = i2c_get_clientdata(client);
> > +
> > + regulator_disable(haptics->regulator);
> > }
>
> This will result in power being shut off the first thing during
> unbinding, which is too early.
>
> I switched this to devm_add_action_or_reset() and applied.
Do you mean that, in this case, regulator_disable() may be called before any
devm_* registered actions? Good point, thanks.
--
Yauhen Kharuzhy
On Thu, Feb 19, 2026 at 12:11:47PM +0200, Yauhen Kharuzhy wrote:
> On Wed, Feb 18, 2026 at 06:43:30PM -0800, Dmitry Torokhov wrote:
> > Hi Yauhen,
> >
> > On Sun, Feb 15, 2026 at 04:14:34PM +0200, Yauhen Kharuzhy wrote:
> > > +static void drv260x_remove(struct i2c_client *client)
> > > +{
> > > + struct drv260x_data *haptics = i2c_get_clientdata(client);
> > > +
> > > + regulator_disable(haptics->regulator);
> > > }
> >
> > This will result in power being shut off the first thing during
> > unbinding, which is too early.
> >
> > I switched this to devm_add_action_or_reset() and applied.
>
> Do you mean that, in this case, regulator_disable() may be called before any
> devm_* registered actions? Good point, thanks.
>
Yes, all devm* actions are run after remove() completes.
Thanks.
--
Dmitry
© 2016 - 2026 Red Hat, Inc.