aboutsummaryrefslogtreecommitdiff
path: root/arch/cris/arch-v32/drivers/mach-fs/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/arch-v32/drivers/mach-fs/gpio.c')
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/gpio.c63
1 files changed, 34 insertions, 29 deletions
diff --git a/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
index fe1fde89388..009f4ee1bd0 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
@@ -22,7 +22,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/etraxgpio.h>
#include <hwregs/reg_map.h>
@@ -30,7 +30,6 @@
#include <hwregs/gio_defs.h>
#include <hwregs/intr_vect_defs.h>
#include <asm/io.h>
-#include <asm/system.h>
#include <asm/irq.h>
#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
@@ -64,6 +63,7 @@ static int dp_cnt;
#define DP(x)
#endif
+static DEFINE_MUTEX(gpio_mutex);
static char gpio_name[] = "etrax gpio";
#if 0
@@ -74,8 +74,7 @@ static wait_queue_head_t *gpio_wq;
static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
unsigned long arg);
#endif
-static int gpio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static ssize_t gpio_write(struct file *file, const char *buf, size_t count,
loff_t *off);
static int gpio_open(struct inode *inode, struct file *filp);
@@ -185,7 +184,7 @@ static volatile unsigned long *dir_oe[NUM_PORTS] = {
static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait)
{
unsigned int mask = 0;
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ struct gpio_private *priv = file->private_data;
unsigned long data;
poll_wait(file, &priv->alarm_wq, wait);
if (priv->minor == GPIO_MINOR_A) {
@@ -353,7 +352,7 @@ gpio_pa_interrupt(int irq, void *dev_id)
static ssize_t gpio_write(struct file *file, const char *buf, size_t count,
loff_t *off)
{
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ struct gpio_private *priv = file->private_data;
unsigned char data, clk_mask, data_mask, write_msb;
unsigned long flags;
unsigned long shadow;
@@ -430,7 +429,7 @@ gpio_open(struct inode *inode, struct file *filp)
if (!priv)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&gpio_mutex);
memset(priv, 0, sizeof(*priv));
priv->minor = p;
@@ -451,7 +450,7 @@ gpio_open(struct inode *inode, struct file *filp)
alarmlist = priv;
spin_unlock_irq(&alarm_lock);
- unlock_kernel();
+ mutex_unlock(&gpio_mutex);
return 0;
}
@@ -468,7 +467,7 @@ gpio_release(struct inode *inode, struct file *filp)
spin_lock_irq(&alarm_lock);
p = alarmlist;
- todel = (struct gpio_private *)filp->private_data;
+ todel = filp->private_data;
if (p == todel) {
alarmlist = todel->next;
@@ -557,17 +556,15 @@ inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg)
return dir_shadow;
} /* setget_output */
-static int
-gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
+static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
static int
-gpio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long flags;
unsigned long val;
unsigned long shadow;
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ struct gpio_private *priv = file->private_data;
if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
return -EINVAL;
@@ -707,6 +704,17 @@ gpio_ioctl(struct inode *inode, struct file *file,
return 0;
}
+static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+
+ mutex_lock(&gpio_mutex);
+ ret = gpio_ioctl_unlocked(file, cmd, arg);
+ mutex_unlock(&gpio_mutex);
+
+ return ret;
+}
+
#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
static int
virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -714,7 +722,7 @@ virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned long flags;
unsigned short val;
unsigned short shadow;
- struct gpio_private *priv = (struct gpio_private *)file->private_data;
+ struct gpio_private *priv = file->private_data;
switch (_IOC_NR(cmd)) {
case IO_SETBITS:
@@ -855,13 +863,14 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
return 0;
}
-struct file_operations gpio_fops = {
- .owner = THIS_MODULE,
- .poll = gpio_poll,
- .ioctl = gpio_ioctl,
- .write = gpio_write,
- .open = gpio_open,
- .release = gpio_release,
+static const struct file_operations gpio_fops = {
+ .owner = THIS_MODULE,
+ .poll = gpio_poll,
+ .unlocked_ioctl = gpio_ioctl,
+ .write = gpio_write,
+ .open = gpio_open,
+ .release = gpio_release,
+ .llseek = noop_llseek,
};
#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
@@ -949,17 +958,13 @@ gpio_init(void)
printk(KERN_INFO "ETRAX FS GPIO driver v2.5, (c) 2003-2007 "
"Axis Communications AB\n");
- /* We call etrax_gpio_wake_up_check() from timer interrupt and
- * from cpu_idle() in kernel/process.c
- * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
- * in some tests.
- */
+ /* We call etrax_gpio_wake_up_check() from timer interrupt */
if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "gpio poll", &alarmlist))
+ IRQF_SHARED, "gpio poll", &alarmlist))
printk(KERN_ERR "timer0 irq for gpio\n");
if (request_irq(GIO_INTR_VECT, gpio_pa_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "gpio PA", &alarmlist))
+ IRQF_SHARED, "gpio PA", &alarmlist))
printk(KERN_ERR "PA irq for gpio\n");
#ifdef CONFIG_ETRAX_VIRTUAL_GPIO