Hi Charles, On 2018-11-22 18:30, Charles Keepax wrote: > 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 <[email protected]> > Signed-off-by: Charles Keepax <[email protected]>
Tested-by: Marek Szyprowski <[email protected]> > --- > 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; Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland

