[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20181122173015.23905-2-ckeepax@opensource.cirrus.com>
Date: Thu, 22 Nov 2018 17:30:14 +0000
From: Charles Keepax <ckeepax@...nsource.cirrus.com>
To: <broonie@...nel.org>
CC: <linus.walleij@...aro.org>, <lgirdwood@...il.com>,
<m.szyprowski@...sung.com>, <linux-kernel@...r.kernel.org>,
<patches@...nsource.cirrus.com>
Subject: [PATCH 2/3] regulator: Only free GPIOs if the core requested them
Currently, the regulator core will take ownership of any GPIO passed
into it. Makes end driver code fairly error prone as the normal devm_
patterns of allocation don't work. Update the regulator core to only
free the GPIO if it requested it, this allows the drivers to manage the
GPIO lifetime as they normally would.
Reported-by: Marek Szyprowski <m.szyprowski@...sung.com>
Signed-off-by: Charles Keepax <ckeepax@...nsource.cirrus.com>
---
drivers/regulator/core.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index dbe2f2e6e6254..9da7d27c7145e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -83,6 +83,7 @@ struct regulator_enable_gpio {
u32 enable_count; /* a number of enabled shared GPIO */
u32 request_count; /* a number of requested shared GPIO */
unsigned int ena_gpio_invert:1;
+ unsigned int locally_requested:1;
};
/*
@@ -2233,19 +2234,20 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
}
}
+ pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
+ if (pin == NULL)
+ return -ENOMEM;
+
if (!config->ena_gpiod) {
ret = gpio_request_one(config->ena_gpio,
GPIOF_DIR_OUT | config->ena_gpio_flags,
rdev_get_name(rdev));
- if (ret)
+ if (ret) {
+ kfree(pin);
return ret;
- }
+ }
- pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
- if (pin == NULL) {
- if (!config->ena_gpiod)
- gpio_free(config->ena_gpio);
- return -ENOMEM;
+ pin->locally_requested = 1;
}
pin->gpiod = gpiod;
@@ -2270,7 +2272,8 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
if (pin->gpiod == rdev->ena_pin->gpiod) {
if (pin->request_count <= 1) {
pin->request_count = 0;
- gpiod_put(pin->gpiod);
+ if (pin->locally_requested)
+ gpiod_put(pin->gpiod);
list_del(&pin->list);
kfree(pin);
rdev->ena_pin = NULL;
--
2.11.0
Powered by blists - more mailing lists