Messages in this thread Patch in this message | | | From | Linus Walleij <> | Subject | [PATCH] regulator: core: do not put managed GPIOd:s | Date | Thu, 22 Nov 2018 17:04:21 +0100 |
| |
Some drivers have been converted to pass GPIO descriptors rather than GPIO numbers to the regulator core. We should not issue gpiod_put() on those descriptors, but rather let the driver reference count it with devm_* if they so desire.
Currently the regulator core issues gpiod_put() on all descriptors as it assumes it was obtained with the sequence gpio_request_one()/gpio_to_desc(), as gpio_request_one() will be equivalent to gpiod_get().
We introduce a helper bool that deal with this situation by making sure the core only issue gpiod_put() if the GPIO was requested from within the core itself.
A subsequent patch set will delete legacy GPIO handling and get rid of this ugliness, so it is a stepgap patch.
Fixes: e45e290a882e ("regulator: core: Support passing an initialized GPIO enable descriptor") Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Charles Keepax <ckeepax@opensource.cirrus.com> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Reported-by: Charles Keepax <ckeepax@opensource.cirrus.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- Mark: I will rebase my v7 series for removing legacy GPIO on this if it solves Marek's probel, it can be applied for fixes if need be but I don't know how big this problem is. --- drivers/regulator/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 03a03763457c..05bb2db6cff5 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -80,6 +80,7 @@ struct regulator_map { struct regulator_enable_gpio { struct list_head list; struct gpio_desc *gpiod; + bool gpiod_needs_put; u32 enable_count; /* a number of enabled shared GPIO */ u32 request_count; /* a number of requested shared GPIO */ unsigned int ena_gpio_invert:1; @@ -2247,6 +2248,8 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, } pin->gpiod = gpiod; + if (!config->ena_gpiod) + pin->gpiod_needs_put = true; pin->ena_gpio_invert = config->ena_gpio_invert; list_add(&pin->list, ®ulator_ena_gpio_list); @@ -2268,7 +2271,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->gpiod_needs_put) + gpiod_put(pin->gpiod); list_del(&pin->list); kfree(pin); rdev->ena_pin = NULL; -- 2.19.1
| |