Skip to content

Commit

Permalink
gpiolib: better rmmod infrastructure
Browse files Browse the repository at this point in the history
As long as one or more GPIOs on a gpio chip are used its driver should not be
unloaded.  The existing mechanism (gpiochip_remove failure) doesn't address
that, since rmmod can no longer be made to fail by having the cleanup code
report errors.  Module usecounts are the solution.

Assuming standard "initialize struct to zero" policies, this change won't
affect SOC platform drivers.  However, drivers for external chips (on I2C and
SPI busses) should be updated if they can be built as modules.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de>
[ gpio_ensure_requested() needs to update module usecounts too ]
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Guennadi Liakhovetski authored and Linus Torvalds committed Apr 28, 2008
1 parent 73fcdc9 commit 438d890
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 3 deletions.
15 changes: 12 additions & 3 deletions drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ static void gpio_ensure_requested(struct gpio_desc *desc)
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc));
desc_set_label(desc, "[auto]");
if (!try_module_get(desc->chip->owner))
pr_err("GPIO-%d: module can't be gotten \n",
(int)(desc - gpio_desc));
}
}

Expand Down Expand Up @@ -177,15 +180,20 @@ int gpio_request(unsigned gpio, const char *label)
if (desc->chip == NULL)
goto done;

if (!try_module_get(desc->chip->owner))
goto done;

/* NOTE: gpio_request() can be called in early boot,
* before IRQs are enabled.
*/

if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
desc_set_label(desc, label ? : "?");
status = 0;
} else
} else {
status = -EBUSY;
module_put(desc->chip->owner);
}

done:
if (status)
Expand All @@ -209,9 +217,10 @@ void gpio_free(unsigned gpio)
spin_lock_irqsave(&gpio_lock, flags);

desc = &gpio_desc[gpio];
if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags))
if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) {
desc_set_label(desc, NULL);
else
module_put(desc->chip->owner);
} else
WARN_ON(extra_checks);

spin_unlock_irqrestore(&gpio_lock, flags);
Expand Down
2 changes: 2 additions & 0 deletions include/asm-generic/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#endif

struct seq_file;
struct module;

/**
* struct gpio_chip - abstract a GPIO controller
Expand Down Expand Up @@ -48,6 +49,7 @@ struct seq_file;
*/
struct gpio_chip {
char *label;
struct module *owner;

int (*direction_input)(struct gpio_chip *chip,
unsigned offset);
Expand Down

0 comments on commit 438d890

Please sign in to comment.