mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 16:07:17 -04:00
gpio: don't set label from irq helpers
We will soon serialize access to the descriptor label using SRCU. The write-side of the protection will require calling synchronize_srcu() which must not be called from atomic context. We have two irq helpers: gpiochip_lock_as_irq() and gpiochip_unlock_as_irq() that set the label if the GPIO is not requested but is being used as interrupt. They are called with a spinlock held from the interrupt subsystem. They must not do it if we are to use SRCU so instead let's move the special corner case to a dedicated getter. Don't actually set the label to "interrupt" in the above case but rather use the newly added gpiod_get_label() helper to hide the logic that atomically checks the descriptor flags and returns the address of a static "interrupt" string. Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
@@ -107,7 +107,14 @@ static bool gpiolib_initialized;
|
||||
|
||||
const char *gpiod_get_label(struct gpio_desc *desc)
|
||||
{
|
||||
return desc->label;
|
||||
unsigned long flags;
|
||||
|
||||
flags = READ_ONCE(desc->flags);
|
||||
if (test_bit(FLAG_USED_AS_IRQ, &flags) &&
|
||||
!test_bit(FLAG_REQUESTED, &flags))
|
||||
return "interrupt";
|
||||
|
||||
return test_bit(FLAG_REQUESTED, &flags) ? desc->label : NULL;
|
||||
}
|
||||
|
||||
static inline void desc_set_label(struct gpio_desc *d, const char *label)
|
||||
@@ -3599,14 +3606,6 @@ int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset)
|
||||
set_bit(FLAG_USED_AS_IRQ, &desc->flags);
|
||||
set_bit(FLAG_IRQ_IS_ENABLED, &desc->flags);
|
||||
|
||||
/*
|
||||
* If the consumer has not set up a label (such as when the
|
||||
* IRQ is referenced from .to_irq()) we set up a label here
|
||||
* so it is clear this is used as an interrupt.
|
||||
*/
|
||||
if (!desc->label)
|
||||
desc_set_label(desc, "interrupt");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
|
||||
@@ -3629,10 +3628,6 @@ void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset)
|
||||
|
||||
clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
|
||||
clear_bit(FLAG_IRQ_IS_ENABLED, &desc->flags);
|
||||
|
||||
/* If we only had this marking, erase it */
|
||||
if (desc->label && !strcmp(desc->label, "interrupt"))
|
||||
desc_set_label(desc, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user