surprise :p

SVN-Revision: 11894
This commit is contained in:
Gabor Juhos
2008-07-21 17:08:14 +00:00
parent 3d9c4c9073
commit f529a37420
54 changed files with 6655 additions and 18 deletions

View File

@@ -0,0 +1,17 @@
diff -Nur a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
--- a/drivers/mtd/devices/m25p80.c 2008-07-06 14:36:59.000000000 +0200
+++ b/drivers/mtd/devices/m25p80.c 2008-07-06 15:17:48.000000000 +0200
@@ -631,12 +631,10 @@
struct mtd_partition *parts = NULL;
int nr_parts = 0;
-#ifdef CONFIG_MTD_CMDLINE_PARTS
- static const char *part_probes[] = { "cmdlinepart", NULL, };
+ static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL, };
nr_parts = parse_mtd_partitions(&flash->mtd,
part_probes, &parts, 0);
-#endif
if (nr_parts <= 0 && data && data->parts) {
parts = data->parts;

View File

@@ -1,18 +0,0 @@
Backport gpio_is_valid() for gpiolib from linux-2.6.26
Index: linux-2.6.25.10/include/asm-generic/gpio.h
===================================================================
--- linux-2.6.25.10.orig/include/asm-generic/gpio.h 2008-07-03 05:46:47.000000000 +0200
+++ linux-2.6.25.10/include/asm-generic/gpio.h 2008-07-20 20:32:12.000000000 +0200
@@ -16,6 +16,12 @@
#define ARCH_NR_GPIOS 256
#endif
+static inline int gpio_is_valid(int number)
+{
+ /* only some non-negative numbers are valid */
+ return ((unsigned)number) < ARCH_NR_GPIOS;
+}
+
struct seq_file;
/**

View File

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

View File

@@ -0,0 +1,136 @@
From: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de>
Date: Mon, 28 Apr 2008 09:14:46 +0000 (-0700)
Subject: gpio: define gpio_is_valid()
X-Git-Tag: v2.6.26-rc1~849
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=e6de1808f8ebfeb7e49f3c5a30cb8f2032beb287
gpio: define gpio_is_valid()
Introduce a gpio_is_valid() predicate; use it in gpiolib.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de>
[ use inline function; follow the gpio_* naming convention;
work without gpiolib; all programming interfaces need docs ]
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/Documentation/gpio.txt b/Documentation/gpio.txt
index 5463009..c35ca9e 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -107,6 +107,16 @@ type of GPIO controller, and on one particular board 80-95 with an FPGA.
The numbers need not be contiguous; either of those platforms could also
use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
+If you want to initialize a structure with an invalid GPIO number, use
+some negative number (perhaps "-EINVAL"); that will never be valid. To
+test if a number could reference a GPIO, you may use this predicate:
+
+ int gpio_is_valid(int number);
+
+A number that's not valid will be rejected by calls which may request
+or free GPIOs (see below). Other numbers may also be rejected; for
+example, a number might be valid but unused on a given board.
+
Whether a platform supports multiple GPIO controllers is currently a
platform-specific implementation issue.
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index eb75d12..623fcd9 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -99,7 +99,7 @@ int gpiochip_add(struct gpio_chip *chip)
* dynamic allocation. We don't currently support that.
*/
- if (chip->base < 0 || (chip->base + chip->ngpio) >= ARCH_NR_GPIOS) {
+ if (chip->base < 0 || !gpio_is_valid(chip->base + chip->ngpio)) {
status = -EINVAL;
goto fail;
}
@@ -174,7 +174,7 @@ int gpio_request(unsigned gpio, const char *label)
spin_lock_irqsave(&gpio_lock, flags);
- if (gpio >= ARCH_NR_GPIOS)
+ if (!gpio_is_valid(gpio))
goto done;
desc = &gpio_desc[gpio];
if (desc->chip == NULL)
@@ -209,7 +209,7 @@ void gpio_free(unsigned gpio)
unsigned long flags;
struct gpio_desc *desc;
- if (gpio >= ARCH_NR_GPIOS) {
+ if (!gpio_is_valid(gpio)) {
WARN_ON(extra_checks);
return;
}
@@ -245,7 +245,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
{
unsigned gpio = chip->base + offset;
- if (gpio >= ARCH_NR_GPIOS || gpio_desc[gpio].chip != chip)
+ if (!gpio_is_valid(gpio) || gpio_desc[gpio].chip != chip)
return NULL;
if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0)
return NULL;
@@ -276,7 +276,7 @@ int gpio_direction_input(unsigned gpio)
spin_lock_irqsave(&gpio_lock, flags);
- if (gpio >= ARCH_NR_GPIOS)
+ if (!gpio_is_valid(gpio))
goto fail;
chip = desc->chip;
if (!chip || !chip->get || !chip->direction_input)
@@ -314,7 +314,7 @@ int gpio_direction_output(unsigned gpio, int value)
spin_lock_irqsave(&gpio_lock, flags);
- if (gpio >= ARCH_NR_GPIOS)
+ if (!gpio_is_valid(gpio))
goto fail;
chip = desc->chip;
if (!chip || !chip->set || !chip->direction_output)
@@ -531,7 +531,7 @@ static int gpiolib_show(struct seq_file *s, void *unused)
/* REVISIT this isn't locked against gpio_chip removal ... */
- for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {
+ for (gpio = 0; gpio_is_valid(gpio); gpio++) {
if (chip == gpio_desc[gpio].chip)
continue;
chip = gpio_desc[gpio].chip;
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 7e77b6f..464c5b3 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -16,6 +16,12 @@
#define ARCH_NR_GPIOS 256
#endif
+static inline int gpio_is_valid(int number)
+{
+ /* only some non-negative numbers are valid */
+ return ((unsigned)number) < ARCH_NR_GPIOS;
+}
+
struct seq_file;
struct module;
@@ -99,6 +105,12 @@ extern int __gpio_cansleep(unsigned gpio);
#else
+static inline int gpio_is_valid(int number)
+{
+ /* only non-negative numbers are valid */
+ return number >= 0;
+}
+
/* platforms that don't directly support access to GPIOs through I2C, SPI,
* or other blocking infrastructure can use these wrappers.
*/

View File

@@ -0,0 +1,118 @@
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Mon, 28 Apr 2008 09:14:46 +0000 (-0700)
Subject: gpiolib: dynamic gpio number allocation
X-Git-Tag: v2.6.26-rc1~848
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8d0aab2f16c4fa170f32e7a74a52cd0122bbafef
gpiolib: dynamic gpio number allocation
If gpio_chip->base is negative during registration, gpiolib performs dynamic
base allocation. This is useful for devices that aren't always present, such
as GPIOs on hotplugged devices rather than mainboards. (This behavior was
previously specified but not implemented.)
To avoid using any numbers that may have been explicitly assigned but not yet
registered, this dynamic allocation assigns GPIO numbers from the biggest
number on down, instead of from the smallest on up.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
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 623fcd9..2ba6127 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -80,6 +80,33 @@ static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
return gpio_desc[gpio].chip;
}
+/* dynamic allocation of GPIOs, e.g. on a hotplugged device */
+static int gpiochip_find_base(int ngpio)
+{
+ int i;
+ int spare = 0;
+ int base = -ENOSPC;
+
+ for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
+ struct gpio_chip *chip = gpio_desc[i].chip;
+
+ if (!chip) {
+ spare++;
+ if (spare == ngpio) {
+ base = i;
+ break;
+ }
+ } else {
+ spare = 0;
+ i -= chip->ngpio - 1;
+ }
+ }
+
+ if (gpio_is_valid(base))
+ pr_debug("%s: found new base at %d\n", __func__, base);
+ return base;
+}
+
/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
@@ -88,38 +115,49 @@ static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
* Returns a negative errno if the chip can't be registered, such as
* because the chip->base is invalid or already associated with a
* different chip. Otherwise it returns zero as a success code.
+ *
+ * If chip->base is negative, this requests dynamic assignment of
+ * a range of valid GPIOs.
*/
int gpiochip_add(struct gpio_chip *chip)
{
unsigned long flags;
int status = 0;
unsigned id;
+ int base = chip->base;
- /* NOTE chip->base negative is reserved to mean a request for
- * dynamic allocation. We don't currently support that.
- */
-
- if (chip->base < 0 || !gpio_is_valid(chip->base + chip->ngpio)) {
+ if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio))
+ && base >= 0) {
status = -EINVAL;
goto fail;
}
spin_lock_irqsave(&gpio_lock, flags);
+ if (base < 0) {
+ base = gpiochip_find_base(chip->ngpio);
+ if (base < 0) {
+ status = base;
+ goto fail_unlock;
+ }
+ chip->base = base;
+ }
+
/* these GPIO numbers must not be managed by another gpio_chip */
- for (id = chip->base; id < chip->base + chip->ngpio; id++) {
+ for (id = base; id < base + chip->ngpio; id++) {
if (gpio_desc[id].chip != NULL) {
status = -EBUSY;
break;
}
}
if (status == 0) {
- for (id = chip->base; id < chip->base + chip->ngpio; id++) {
+ for (id = base; id < base + chip->ngpio; id++) {
gpio_desc[id].chip = chip;
gpio_desc[id].flags = 0;
}
}
+fail_unlock:
spin_unlock_irqrestore(&gpio_lock, flags);
fail:
/* failures here can mean systems won't boot... */

View File

@@ -0,0 +1,116 @@
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Mon, 28 Apr 2008 09:14:47 +0000 (-0700)
Subject: gpiochip_reserve()
X-Git-Tag: v2.6.26-rc1~847
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=169b6a7a6e91e1ea32136681b475cbaf2074bf35
gpiochip_reserve()
Add a new function gpiochip_reserve() to reserve ranges of gpios that platform
code has pre-allocated. That is, this marks gpio numbers which will be
claimed by drivers that haven't yet been loaded, and thus are not available
for dynamic gpio number allocation.
[akpm@linux-foundation.org: remove unneeded __must_check]
[david-b@pacbell.net: don't export gpiochip_reserve (section fix)]
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
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 2ba6127..24c62b8 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -43,6 +43,7 @@ struct gpio_desc {
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
#define FLAG_IS_OUT 1
+#define FLAG_RESERVED 2
#ifdef CONFIG_DEBUG_FS
const char *label;
@@ -88,9 +89,10 @@ static int gpiochip_find_base(int ngpio)
int base = -ENOSPC;
for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
- struct gpio_chip *chip = gpio_desc[i].chip;
+ struct gpio_desc *desc = &gpio_desc[i];
+ struct gpio_chip *chip = desc->chip;
- if (!chip) {
+ if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) {
spare++;
if (spare == ngpio) {
base = i;
@@ -98,7 +100,8 @@ static int gpiochip_find_base(int ngpio)
}
} else {
spare = 0;
- i -= chip->ngpio - 1;
+ if (chip)
+ i -= chip->ngpio - 1;
}
}
@@ -108,6 +111,47 @@ static int gpiochip_find_base(int ngpio)
}
/**
+ * gpiochip_reserve() - reserve range of gpios to use with platform code only
+ * @start: starting gpio number
+ * @ngpio: number of gpios to reserve
+ * Context: platform init, potentially before irqs or kmalloc will work
+ *
+ * Returns a negative errno if any gpio within the range is already reserved
+ * or registered, else returns zero as a success code. Use this function
+ * to mark a range of gpios as unavailable for dynamic gpio number allocation,
+ * for example because its driver support is not yet loaded.
+ */
+int __init gpiochip_reserve(int start, int ngpio)
+{
+ int ret = 0;
+ unsigned long flags;
+ int i;
+
+ if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio))
+ return -EINVAL;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ for (i = start; i < start + ngpio; i++) {
+ struct gpio_desc *desc = &gpio_desc[i];
+
+ if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ set_bit(FLAG_RESERVED, &desc->flags);
+ }
+
+ pr_debug("%s: reserved gpios from %d to %d\n",
+ __func__, start, start + ngpio - 1);
+err:
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ return ret;
+}
+
+/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
* Context: potentially before irqs or kmalloc will work
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 464c5b3..ecf675a 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -74,6 +74,7 @@ struct gpio_chip {
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
unsigned offset);
+extern int __init __must_check gpiochip_reserve(int start, int ngpio);
/* add/remove chips */
extern int gpiochip_add(struct gpio_chip *chip);

View File

@@ -0,0 +1,48 @@
From: Trent Piepho <xyzzy@speakeasy.org>
Date: Fri, 23 May 2008 20:04:44 +0000 (-0700)
Subject: gpiolib: fix off by one errors
X-Git-Tag: v2.6.26-rc4~31
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=bff5fda972dc23bd1806a47c2098ae173585d013
gpiolib: fix off by one errors
The last gpio belonging to a chip is chip->base + chip->ngpios - 1. Some
places in the code, but not all, forgot the critical minus one.
Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Acked-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 7f138c6..beaf6b3 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -127,7 +127,7 @@ int __init gpiochip_reserve(int start, int ngpio)
unsigned long flags;
int i;
- if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio))
+ if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1))
return -EINVAL;
spin_lock_irqsave(&gpio_lock, flags);
@@ -170,7 +170,7 @@ int gpiochip_add(struct gpio_chip *chip)
unsigned id;
int base = chip->base;
- if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio))
+ if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
&& base >= 0) {
status = -EINVAL;
goto fail;
@@ -207,7 +207,7 @@ fail:
/* failures here can mean systems won't boot... */
if (status)
pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n",
- chip->base, chip->base + chip->ngpio,
+ chip->base, chip->base + chip->ngpio - 1,
chip->label ? : "generic");
return status;
}