diff options
Diffstat (limited to 'target/linux/generic-2.6/patches-2.6.25/960-backport_gpiolib_better_rmmod_infrastructure.patch')
-rw-r--r-- | target/linux/generic-2.6/patches-2.6.25/960-backport_gpiolib_better_rmmod_infrastructure.patch | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/target/linux/generic-2.6/patches-2.6.25/960-backport_gpiolib_better_rmmod_infrastructure.patch b/target/linux/generic-2.6/patches-2.6.25/960-backport_gpiolib_better_rmmod_infrastructure.patch new file mode 100644 index 0000000000..a6822fc14e --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.25/960-backport_gpiolib_better_rmmod_infrastructure.patch @@ -0,0 +1,93 @@ +From: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> +Date: Mon, 28 Apr 2008 09:14:44 +0000 (-0700) +Subject: gpiolib: better rmmod infrastructure +X-Git-Tag: v2.6.26-rc1~851 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=438d8908b379b6322fc3b28d45c9ebdddf58bc20 + +gpiolib: better rmmod infrastructure + +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> +--- + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index d8db2f8..eb75d12 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -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)); + } + } + +@@ -177,6 +180,9 @@ 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. + */ +@@ -184,8 +190,10 @@ int gpio_request(unsigned gpio, const char *label) + 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); +diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h +index f29a502..7e77b6f 100644 +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -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); |