Skip to content

Commit 98ce1eb

Browse files
author
Bartosz Golaszewski
committed
gpiolib: introduce gpio_chip setters that return values
Add new variants of the set() and set_multiple() callbacks that have integer return values allowing to indicate failures to users of the GPIO consumer API. Until we convert all GPIO providers treewide to using them, they will live in parallel to the existing ones. Make sure that providers cannot define both. Prefer the new ones and only use the old ones as fallback. Reviewed-by: Linus Walleij <[email protected]> Acked-by: Uwe Kleine-König <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 9b40731 commit 98ce1eb

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

drivers/gpio/gpiolib.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,11 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
958958
int base = 0;
959959
int ret = 0;
960960

961+
/* Only allow one set() and one set_multiple(). */
962+
if ((gc->set && gc->set_rv) ||
963+
(gc->set_multiple && gc->set_multiple_rv))
964+
return -EINVAL;
965+
961966
/*
962967
* First: allocate and populate the internal stat container, and
963968
* set up the struct device.
@@ -2827,11 +2832,21 @@ int gpiod_direction_input_nonotify(struct gpio_desc *desc)
28272832

28282833
static int gpiochip_set(struct gpio_chip *gc, unsigned int offset, int value)
28292834
{
2835+
int ret;
2836+
28302837
lockdep_assert_held(&gc->gpiodev->srcu);
28312838

2832-
if (WARN_ON(unlikely(!gc->set)))
2839+
if (WARN_ON(unlikely(!gc->set && !gc->set_rv)))
28332840
return -EOPNOTSUPP;
28342841

2842+
if (gc->set_rv) {
2843+
ret = gc->set_rv(gc, offset, value);
2844+
if (ret > 0)
2845+
ret = -EBADE;
2846+
2847+
return ret;
2848+
}
2849+
28352850
gc->set(gc, offset, value);
28362851
return 0;
28372852
}
@@ -3593,9 +3608,17 @@ static int gpiochip_set_multiple(struct gpio_chip *gc,
35933608

35943609
lockdep_assert_held(&gc->gpiodev->srcu);
35953610

3596-
if (WARN_ON(unlikely(!gc->set_multiple && !gc->set)))
3611+
if (WARN_ON(unlikely(!gc->set_multiple && !gc->set_multiple_rv)))
35973612
return -EOPNOTSUPP;
35983613

3614+
if (gc->set_multiple_rv) {
3615+
ret = gc->set_multiple_rv(gc, mask, bits);
3616+
if (ret > 0)
3617+
ret = -EBADE;
3618+
3619+
return ret;
3620+
}
3621+
35993622
if (gc->set_multiple) {
36003623
gc->set_multiple(gc, mask, bits);
36013624
return 0;

include/linux/gpio/driver.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ struct gpio_irq_chip {
348348
* stores them in "bits", returns 0 on success or negative error
349349
* @set: assigns output value for signal "offset"
350350
* @set_multiple: assigns output values for multiple signals defined by "mask"
351+
* @set_rv: assigns output value for signal "offset", returns 0 on success or
352+
* negative error value
353+
* @set_multiple_rv: assigns output values for multiple signals defined by
354+
* "mask", returns 0 on success or negative error value
351355
* @set_config: optional hook for all kinds of settings. Uses the same
352356
* packed config format as generic pinconf. Must return 0 on success and
353357
* a negative error number on failure.
@@ -445,6 +449,12 @@ struct gpio_chip {
445449
void (*set_multiple)(struct gpio_chip *gc,
446450
unsigned long *mask,
447451
unsigned long *bits);
452+
int (*set_rv)(struct gpio_chip *gc,
453+
unsigned int offset,
454+
int value);
455+
int (*set_multiple_rv)(struct gpio_chip *gc,
456+
unsigned long *mask,
457+
unsigned long *bits);
448458
int (*set_config)(struct gpio_chip *gc,
449459
unsigned int offset,
450460
unsigned long config);

0 commit comments

Comments
 (0)