aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@pengutronix.de>2008-04-28 05:14:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:34 -0400
commit438d8908b379b6322fc3b28d45c9ebdddf58bc20 (patch)
treece9439dc8c7e5d9e80f514751fb3b4ce4e414233
parent73fcdc9e15c27bb92595c611c8938a36645ea20d (diff)
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>
-rw-r--r--drivers/gpio/gpiolib.c15
-rw-r--r--include/asm-generic/gpio.h2
2 files changed, 14 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index d8db2f8ee411..eb75d12e83b7 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -68,6 +68,9 @@ static void gpio_ensure_requested(struct gpio_desc *desc)
68 if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { 68 if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
69 pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc)); 69 pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc));
70 desc_set_label(desc, "[auto]"); 70 desc_set_label(desc, "[auto]");
71 if (!try_module_get(desc->chip->owner))
72 pr_err("GPIO-%d: module can't be gotten \n",
73 (int)(desc - gpio_desc));
71 } 74 }
72} 75}
73 76
@@ -177,6 +180,9 @@ int gpio_request(unsigned gpio, const char *label)
177 if (desc->chip == NULL) 180 if (desc->chip == NULL)
178 goto done; 181 goto done;
179 182
183 if (!try_module_get(desc->chip->owner))
184 goto done;
185
180 /* NOTE: gpio_request() can be called in early boot, 186 /* NOTE: gpio_request() can be called in early boot,
181 * before IRQs are enabled. 187 * before IRQs are enabled.
182 */ 188 */
@@ -184,8 +190,10 @@ int gpio_request(unsigned gpio, const char *label)
184 if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { 190 if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
185 desc_set_label(desc, label ? : "?"); 191 desc_set_label(desc, label ? : "?");
186 status = 0; 192 status = 0;
187 } else 193 } else {
188 status = -EBUSY; 194 status = -EBUSY;
195 module_put(desc->chip->owner);
196 }
189 197
190done: 198done:
191 if (status) 199 if (status)
@@ -209,9 +217,10 @@ void gpio_free(unsigned gpio)
209 spin_lock_irqsave(&gpio_lock, flags); 217 spin_lock_irqsave(&gpio_lock, flags);
210 218
211 desc = &gpio_desc[gpio]; 219 desc = &gpio_desc[gpio];
212 if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) 220 if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) {
213 desc_set_label(desc, NULL); 221 desc_set_label(desc, NULL);
214 else 222 module_put(desc->chip->owner);
223 } else
215 WARN_ON(extra_checks); 224 WARN_ON(extra_checks);
216 225
217 spin_unlock_irqrestore(&gpio_lock, flags); 226 spin_unlock_irqrestore(&gpio_lock, flags);
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index f29a502f4a6c..7e77b6ff45bb 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -17,6 +17,7 @@
17#endif 17#endif
18 18
19struct seq_file; 19struct seq_file;
20struct module;
20 21
21/** 22/**
22 * struct gpio_chip - abstract a GPIO controller 23 * struct gpio_chip - abstract a GPIO controller
@@ -48,6 +49,7 @@ struct seq_file;
48 */ 49 */
49struct gpio_chip { 50struct gpio_chip {
50 char *label; 51 char *label;
52 struct module *owner;
51 53
52 int (*direction_input)(struct gpio_chip *chip, 54 int (*direction_input)(struct gpio_chip *chip,
53 unsigned offset); 55 unsigned offset);