gpiolib: decouple might_sleep_if() from DEBUG
Be more consistent about runtime programming interface abuse warnings, which can reduce some confusion and trigger bugfixes. Based on an observation and patch from Jani Nikula. Also update doc to highlight some sleeping-call issues and to match some recent changes. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Jani Nikula <ext-jani.1.nikula@nokia.com> Cc: "Ryan Mallon" <ryan@bluewatersys.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
49946f6814
Коммит
9c4ba94661
|
@ -158,10 +158,11 @@ and configure pullups/pulldowns appropriately.)
|
||||||
Spinlock-Safe GPIO access
|
Spinlock-Safe GPIO access
|
||||||
-------------------------
|
-------------------------
|
||||||
Most GPIO controllers can be accessed with memory read/write instructions.
|
Most GPIO controllers can be accessed with memory read/write instructions.
|
||||||
That doesn't need to sleep, and can safely be done from inside IRQ handlers.
|
Those don't need to sleep, and can safely be done from inside hard
|
||||||
(That includes hardirq contexts on RT kernels.)
|
(nonthreaded) IRQ handlers and similar contexts.
|
||||||
|
|
||||||
Use these calls to access such GPIOs:
|
Use the following calls to access such GPIOs,
|
||||||
|
for which gpio_cansleep() will always return false (see below):
|
||||||
|
|
||||||
/* GPIO INPUT: return zero or nonzero */
|
/* GPIO INPUT: return zero or nonzero */
|
||||||
int gpio_get_value(unsigned gpio);
|
int gpio_get_value(unsigned gpio);
|
||||||
|
@ -210,9 +211,31 @@ To access such GPIOs, a different set of accessors is defined:
|
||||||
/* GPIO OUTPUT, might sleep */
|
/* GPIO OUTPUT, might sleep */
|
||||||
void gpio_set_value_cansleep(unsigned gpio, int value);
|
void gpio_set_value_cansleep(unsigned gpio, int value);
|
||||||
|
|
||||||
Other than the fact that these calls might sleep, and will not be ignored
|
|
||||||
for GPIOs that can't be accessed from IRQ handlers, these calls act the
|
Accessing such GPIOs requires a context which may sleep, for example
|
||||||
same as the spinlock-safe calls.
|
a threaded IRQ handler, and those accessors must be used instead of
|
||||||
|
spinlock-safe accessors without the cansleep() name suffix.
|
||||||
|
|
||||||
|
Other than the fact that these accessors might sleep, and will work
|
||||||
|
on GPIOs that can't be accessed from hardIRQ handlers, these calls act
|
||||||
|
the same as the spinlock-safe calls.
|
||||||
|
|
||||||
|
** IN ADDITION ** calls to setup and configure such GPIOs must be made
|
||||||
|
from contexts which may sleep, since they may need to access the GPIO
|
||||||
|
controller chip too: (These setup calls are usually made from board
|
||||||
|
setup or driver probe/teardown code, so this is an easy constraint.)
|
||||||
|
|
||||||
|
gpio_direction_input()
|
||||||
|
gpio_direction_output()
|
||||||
|
gpio_request()
|
||||||
|
|
||||||
|
## gpio_request_one()
|
||||||
|
## gpio_request_array()
|
||||||
|
## gpio_free_array()
|
||||||
|
|
||||||
|
gpio_free()
|
||||||
|
gpio_set_debounce()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Claiming and Releasing GPIOs
|
Claiming and Releasing GPIOs
|
||||||
|
|
|
@ -1272,7 +1272,7 @@ void gpio_free(unsigned gpio)
|
||||||
if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
|
if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
|
||||||
if (chip->free) {
|
if (chip->free) {
|
||||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||||
might_sleep_if(extra_checks && chip->can_sleep);
|
might_sleep_if(chip->can_sleep);
|
||||||
chip->free(chip, gpio - chip->base);
|
chip->free(chip, gpio - chip->base);
|
||||||
spin_lock_irqsave(&gpio_lock, flags);
|
spin_lock_irqsave(&gpio_lock, flags);
|
||||||
}
|
}
|
||||||
|
@ -1410,7 +1410,7 @@ int gpio_direction_input(unsigned gpio)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||||
|
|
||||||
might_sleep_if(extra_checks && chip->can_sleep);
|
might_sleep_if(chip->can_sleep);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
status = chip->request(chip, gpio);
|
status = chip->request(chip, gpio);
|
||||||
|
@ -1463,7 +1463,7 @@ int gpio_direction_output(unsigned gpio, int value)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||||
|
|
||||||
might_sleep_if(extra_checks && chip->can_sleep);
|
might_sleep_if(chip->can_sleep);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
status = chip->request(chip, gpio);
|
status = chip->request(chip, gpio);
|
||||||
|
@ -1521,7 +1521,7 @@ int gpio_set_debounce(unsigned gpio, unsigned debounce)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||||
|
|
||||||
might_sleep_if(extra_checks && chip->can_sleep);
|
might_sleep_if(chip->can_sleep);
|
||||||
|
|
||||||
return chip->set_debounce(chip, gpio, debounce);
|
return chip->set_debounce(chip, gpio, debounce);
|
||||||
|
|
||||||
|
@ -1571,7 +1571,7 @@ int __gpio_get_value(unsigned gpio)
|
||||||
struct gpio_chip *chip;
|
struct gpio_chip *chip;
|
||||||
|
|
||||||
chip = gpio_to_chip(gpio);
|
chip = gpio_to_chip(gpio);
|
||||||
WARN_ON(extra_checks && chip->can_sleep);
|
WARN_ON(chip->can_sleep);
|
||||||
return chip->get ? chip->get(chip, gpio - chip->base) : 0;
|
return chip->get ? chip->get(chip, gpio - chip->base) : 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__gpio_get_value);
|
EXPORT_SYMBOL_GPL(__gpio_get_value);
|
||||||
|
@ -1590,7 +1590,7 @@ void __gpio_set_value(unsigned gpio, int value)
|
||||||
struct gpio_chip *chip;
|
struct gpio_chip *chip;
|
||||||
|
|
||||||
chip = gpio_to_chip(gpio);
|
chip = gpio_to_chip(gpio);
|
||||||
WARN_ON(extra_checks && chip->can_sleep);
|
WARN_ON(chip->can_sleep);
|
||||||
chip->set(chip, gpio - chip->base, value);
|
chip->set(chip, gpio - chip->base, value);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__gpio_set_value);
|
EXPORT_SYMBOL_GPL(__gpio_set_value);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче