Hi Charles,

On 2018-11-22 18:30, Charles Keepax wrote:
> Currently, a GPIO can be requested multiple times when the
> NONEXCLUSIVE flag is set, however it must still be freed a single
> time. This makes client code rather complex, since multiple drivers
> may request the GPIO but only a single one can free it. Rather than
> manually handling this in each driver add some basic reference
> counting into the core.  Currently, this is fairly primitive but
> so is the support for the NONEXCLUSIVE flag and the implementation
> covers those use-cases.
>
> Reported-by: Marek Szyprowski <m.szyprow...@samsung.com>
> Signed-off-by: Charles Keepax <ckee...@opensource.cirrus.com>
Tested-by: Marek Szyprowski <m.szyprow...@samsung.com>
> ---
>  drivers/gpio/gpiolib.c | 13 ++++++++++++-
>  drivers/gpio/gpiolib.h |  2 ++
>  2 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index 230e41562462b..42ba86fb495a5 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -2407,6 +2407,13 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
>  
>       might_sleep();
>  
> +     if (desc->n_users > 1) {
> +             desc->n_users--;
> +             return true;
> +     } else {
> +             desc->n_users = 0;
> +     }
> +
>       gpiod_unexport(desc);
>  
>       spin_lock_irqsave(&gpio_lock, flags);
> @@ -4142,7 +4149,8 @@ struct gpio_desc *__must_check gpiod_get_index(struct 
> device *dev,
>                        */
>                       dev_info(dev, "nonexclusive access to GPIO for %s\n",
>                                con_id ? con_id : devname);
> -                     return desc;
> +
> +                     goto done;
>               } else {
>                       return ERR_PTR(status);
>               }
> @@ -4155,6 +4163,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct 
> device *dev,
>               return ERR_PTR(status);
>       }
>  
> +done:
> +     desc->n_users++;
> +
>       return desc;
>  }
>  EXPORT_SYMBOL_GPL(gpiod_get_index);
> diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
> index 087d865286a0c..f96eda90281a3 100644
> --- a/drivers/gpio/gpiolib.h
> +++ b/drivers/gpio/gpiolib.h
> @@ -230,6 +230,8 @@ struct gpio_desc {
>       const char              *label;
>       /* Name of the GPIO */
>       const char              *name;
> +
> +     unsigned int            n_users;
>  };
>  
>  int gpiod_request(struct gpio_desc *desc, const char *label);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

Reply via email to