diff options
author | Michael Büsch <mb@bu3sch.de> | 2008-03-19 11:32:08 +0000 |
---|---|---|
committer | Michael Büsch <mb@bu3sch.de> | 2008-03-19 11:32:08 +0000 |
commit | 68523387b35c1cd3cbac5a39aec3cef0df84b5de (patch) | |
tree | 8f083c4d8d70ef8ae5cd2034d0d766a988d5a2fa | |
parent | c7ac9d32824c4f0585b3dcad1a0d60a5e257c0cb (diff) | |
download | upstream-68523387b35c1cd3cbac5a39aec3cef0df84b5de.tar.gz upstream-68523387b35c1cd3cbac5a39aec3cef0df84b5de.tar.bz2 upstream-68523387b35c1cd3cbac5a39aec3cef0df84b5de.zip |
GPIODEV: Fix open-count race condition.
SVN-Revision: 10625
-rw-r--r-- | target/linux/generic-2.6/files/drivers/gpio/gpio_dev.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/target/linux/generic-2.6/files/drivers/gpio/gpio_dev.c b/target/linux/generic-2.6/files/drivers/gpio/gpio_dev.c index 690a3fb8c5..48ef76f8a9 100644 --- a/target/linux/generic-2.6/files/drivers/gpio/gpio_dev.c +++ b/target/linux/generic-2.6/files/drivers/gpio/gpio_dev.c @@ -25,6 +25,7 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/gpio.h> +#include <asm/atomic.h> #include <linux/init.h> #include <linux/genhd.h> #include <linux/device.h> @@ -35,10 +36,12 @@ #define DEVNAME "gpio" static int dev_major; -static int gpio_is_open = 0; -unsigned int gpio_access_mask = 0; +static unsigned int gpio_access_mask; static struct class *gpio_class; +/* Counter is 1, if the device is not opened and zero (or less) if opened. */ +static atomic_t gpio_open_cnt = ATOMIC_INIT(1); + static int gpio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { @@ -94,15 +97,18 @@ gpio_open(struct inode *inode, struct file *file) goto out; } - if (gpio_is_open) - { + /* FIXME: We should really allow multiple applications to open the device + * at the same time, as long as the apps access different IO pins. + * The generic gpio-registration functions can be used for that. + * Two new IOCTLs have to be introduced for that. Need to check userspace + * compatibility first. --mb */ + if (!atomic_dec_and_test(&gpio_open_cnt)) { + atomic_inc(&gpio_open_cnt); printk(KERN_ERR DRVNAME ": Device with minor ID %d already in use\n", dev_minor); result = -EBUSY; goto out; } - gpio_is_open = 1; - out: return result; } @@ -110,7 +116,8 @@ out: static int gpio_close(struct inode * inode, struct file * file) { - gpio_is_open = 0; + smp_mb__before_atomic_inc(); + atomic_inc(&gpio_open_cnt); return 0; } |