[patch 2.6.25-rc1 1/3] gpiolib: better rmmod infrastructure

From: David Brownell
Date: Sun Feb 10 2008 - 19:23:21 EST


From: Guennadi Liakhovetski <g.liakhovetski@xxxxxxxxxxxxxx>

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@xxxxxxxxxxxxxx>
[ gpio_ensure_requested() needs to update module usecounts too ]
Signed-off-by: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx>
---
drivers/gpio/gpiolib.c | 15 ++++++++++++---
include/asm-generic/gpio.h | 2 ++
2 files changed, 14 insertions(+), 3 deletions(-)

--- g26.orig/drivers/gpio/gpiolib.c 2008-02-10 16:06:30.000000000 -0800
+++ g26/drivers/gpio/gpiolib.c 2008-02-10 16:18:35.000000000 -0800
@@ -68,6 +68,9 @@ static void gpio_ensure_requested(struct
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));
}
}

@@ -177,6 +180,9 @@ int gpio_request(unsigned gpio, const ch
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.
*/
@@ -184,8 +190,10 @@ int gpio_request(unsigned gpio, const ch
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)
@@ -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);
--- g26.orig/include/asm-generic/gpio.h 2008-02-10 16:06:30.000000000 -0800
+++ g26/include/asm-generic/gpio.h 2008-02-10 16:18:30.000000000 -0800
@@ -17,6 +17,7 @@
#endif

struct seq_file;
+struct module;

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

int (*direction_input)(struct gpio_chip *chip,
unsigned offset);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/