Skip to content

Commit 2cba054

Browse files
geertubrgl
authored andcommitted
gpio: aggregator: Fix calling into sleeping GPIO controllers
If the parent GPIO controller is a sleeping controller (e.g. a GPIO controller connected to I2C), getting or setting a GPIO triggers a might_sleep() warning. This happens because the GPIO Aggregator takes the can_sleep flag into account only for its internal locking, not for calling into the parent GPIO controller. Fix this by using the gpiod_[gs]et*_cansleep() APIs when calling into a sleeping GPIO controller. Reported-by: Mikko Salomäki <[email protected]> Fixes: 828546e ("gpio: Add GPIO Aggregator") Signed-off-by: Geert Uytterhoeven <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 26291c5 commit 2cba054

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

drivers/gpio/gpio-aggregator.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset)
278278
{
279279
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
280280

281-
return gpiod_get_value(fwd->descs[offset]);
281+
return chip->can_sleep ? gpiod_get_value_cansleep(fwd->descs[offset])
282+
: gpiod_get_value(fwd->descs[offset]);
282283
}
283284

284285
static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
@@ -293,7 +294,10 @@ static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
293294
for_each_set_bit(i, mask, fwd->chip.ngpio)
294295
descs[j++] = fwd->descs[i];
295296

296-
error = gpiod_get_array_value(j, descs, NULL, values);
297+
if (fwd->chip.can_sleep)
298+
error = gpiod_get_array_value_cansleep(j, descs, NULL, values);
299+
else
300+
error = gpiod_get_array_value(j, descs, NULL, values);
297301
if (error)
298302
return error;
299303

@@ -328,7 +332,10 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value)
328332
{
329333
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
330334

331-
gpiod_set_value(fwd->descs[offset], value);
335+
if (chip->can_sleep)
336+
gpiod_set_value_cansleep(fwd->descs[offset], value);
337+
else
338+
gpiod_set_value(fwd->descs[offset], value);
332339
}
333340

334341
static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
@@ -343,7 +350,10 @@ static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
343350
descs[j++] = fwd->descs[i];
344351
}
345352

346-
gpiod_set_array_value(j, descs, NULL, values);
353+
if (fwd->chip.can_sleep)
354+
gpiod_set_array_value_cansleep(j, descs, NULL, values);
355+
else
356+
gpiod_set_array_value(j, descs, NULL, values);
347357
}
348358

349359
static void gpio_fwd_set_multiple_locked(struct gpio_chip *chip,

0 commit comments

Comments
 (0)