Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 208477
b: refs/heads/master
c: 9c4ba94
h: refs/heads/master
i:
  208475: 6752344
v: v3
  • Loading branch information
David Brownell authored and Linus Torvalds committed Aug 11, 2010
1 parent d726340 commit 39e3896
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 49946f68149a723659eca253376ac555d4b73280
refs/heads/master: 9c4ba9466117b16a2b85034bb87db528aaeb3f07
35 changes: 29 additions & 6 deletions trunk/Documentation/gpio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,11 @@ and configure pullups/pulldowns appropriately.)
Spinlock-Safe GPIO access
-------------------------
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.
(That includes hardirq contexts on RT kernels.)
Those don't need to sleep, and can safely be done from inside hard
(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 */
int gpio_get_value(unsigned gpio);
Expand Down Expand Up @@ -210,9 +211,31 @@ To access such GPIOs, a different set of accessors is defined:
/* GPIO OUTPUT, might sleep */
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
same as the spinlock-safe calls.

Accessing such GPIOs requires a context which may sleep, for example
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
Expand Down
12 changes: 6 additions & 6 deletions trunk/drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ void gpio_free(unsigned gpio)
if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
if (chip->free) {
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);
spin_lock_irqsave(&gpio_lock, flags);
}
Expand Down Expand Up @@ -1410,7 +1410,7 @@ int gpio_direction_input(unsigned gpio)

spin_unlock_irqrestore(&gpio_lock, flags);

might_sleep_if(extra_checks && chip->can_sleep);
might_sleep_if(chip->can_sleep);

if (status) {
status = chip->request(chip, gpio);
Expand Down Expand Up @@ -1463,7 +1463,7 @@ int gpio_direction_output(unsigned gpio, int value)

spin_unlock_irqrestore(&gpio_lock, flags);

might_sleep_if(extra_checks && chip->can_sleep);
might_sleep_if(chip->can_sleep);

if (status) {
status = chip->request(chip, gpio);
Expand Down Expand Up @@ -1521,7 +1521,7 @@ int gpio_set_debounce(unsigned gpio, unsigned debounce)

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);

Expand Down Expand Up @@ -1571,7 +1571,7 @@ int __gpio_get_value(unsigned gpio)
struct gpio_chip *chip;

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;
}
EXPORT_SYMBOL_GPL(__gpio_get_value);
Expand All @@ -1590,7 +1590,7 @@ void __gpio_set_value(unsigned gpio, int value)
struct gpio_chip *chip;

chip = gpio_to_chip(gpio);
WARN_ON(extra_checks && chip->can_sleep);
WARN_ON(chip->can_sleep);
chip->set(chip, gpio - chip->base, value);
}
EXPORT_SYMBOL_GPL(__gpio_set_value);
Expand Down

0 comments on commit 39e3896

Please sign in to comment.