Skip to content

Commit 6409d04

Browse files
committed
gpiolib: don't call sleeping functions with a spinlock taken
We must not call pinctrl_gpio_can_use_line() with the gpio_lock taken as it takes a mutex internally. Let's move the call before taking the spinlock and store the return value. This isn't perfect - there's a moment between calling pinctrl_gpio_can_use_line() and taking the spinlock where the situation can change but it isn't a regression either: previously this part wasn't protected at all and it only affects the information user-space is seeing. Reported-by: Geert Uytterhoeven <[email protected]> Fixes: d2ac257 ("gpiolib: provide a dedicated function for setting lineinfo") Signed-off-by: Bartosz Golaszewski <[email protected]> Acked-by: Linus Walleij <[email protected]>
1 parent 4e15415 commit 6409d04

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

drivers/gpio/gpiolib.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1158,8 +1158,19 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
11581158
struct gpioline_info *info)
11591159
{
11601160
struct gpio_chip *gc = desc->gdev->chip;
1161+
bool ok_for_pinctrl;
11611162
unsigned long flags;
11621163

1164+
/*
1165+
* This function takes a mutex so we must check this before taking
1166+
* the spinlock.
1167+
*
1168+
* FIXME: find a non-racy way to retrieve this information. Maybe a
1169+
* lock common to both frameworks?
1170+
*/
1171+
ok_for_pinctrl =
1172+
pinctrl_gpio_can_use_line(gc->base + info->line_offset);
1173+
11631174
spin_lock_irqsave(&gpio_lock, flags);
11641175

11651176
if (desc->name) {
@@ -1186,7 +1197,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
11861197
test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
11871198
test_bit(FLAG_EXPORT, &desc->flags) ||
11881199
test_bit(FLAG_SYSFS, &desc->flags) ||
1189-
!pinctrl_gpio_can_use_line(gc->base + info->line_offset))
1200+
!ok_for_pinctrl)
11901201
info->flags |= GPIOLINE_FLAG_KERNEL;
11911202
if (test_bit(FLAG_IS_OUT, &desc->flags))
11921203
info->flags |= GPIOLINE_FLAG_IS_OUT;

0 commit comments

Comments
 (0)