aboutsummaryrefslogtreecommitdiff
path: root/arch/cris/arch-v32/drivers/sync_serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/arch-v32/drivers/sync_serial.c')
-rw-r--r--arch/cris/arch-v32/drivers/sync_serial.c80
1 files changed, 51 insertions, 29 deletions
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index 47c377df6fb..bbb806b6883 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -13,12 +13,13 @@
#include <linux/errno.h>
#include <linux/major.h>
#include <linux/sched.h>
-#include <linux/slab.h>
+#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
+#include <linux/wait.h>
#include <asm/io.h>
#include <dma.h>
@@ -33,7 +34,7 @@
#include <asm/sync_serial.h>
-/* The receiver is a bit tricky beacuse of the continuous stream of data.*/
+/* The receiver is a bit tricky because of the continuous stream of data.*/
/* */
/* Three DMA descriptors are linked together. Each DMA descriptor is */
/* responsible for port->bufchunk of a common buffer. */
@@ -145,6 +146,7 @@ typedef struct sync_port
spinlock_t lock;
} sync_port;
+static DEFINE_MUTEX(sync_serial_mutex);
static int etrax_sync_serial_init(void);
static void initialize_port(int portnbr);
static inline int sync_data_avail(struct sync_port *port);
@@ -153,7 +155,7 @@ static int sync_serial_open(struct inode *, struct file*);
static int sync_serial_release(struct inode*, struct file*);
static unsigned int sync_serial_poll(struct file *filp, poll_table *wait);
-static int sync_serial_ioctl(struct inode*, struct file*,
+static int sync_serial_ioctl(struct file *,
unsigned int cmd, unsigned long arg);
static ssize_t sync_serial_write(struct file * file, const char * buf,
size_t count, loff_t *ppos);
@@ -241,13 +243,14 @@ static struct sync_port ports[]=
#define NBR_PORTS ARRAY_SIZE(ports)
static const struct file_operations sync_serial_fops = {
- .owner = THIS_MODULE,
- .write = sync_serial_write,
- .read = sync_serial_read,
- .poll = sync_serial_poll,
- .ioctl = sync_serial_ioctl,
- .open = sync_serial_open,
- .release = sync_serial_release
+ .owner = THIS_MODULE,
+ .write = sync_serial_write,
+ .read = sync_serial_read,
+ .poll = sync_serial_poll,
+ .unlocked_ioctl = sync_serial_ioctl,
+ .open = sync_serial_open,
+ .release = sync_serial_release,
+ .llseek = noop_llseek,
};
static int __init etrax_sync_serial_init(void)
@@ -429,23 +432,26 @@ static inline int sync_data_avail_to_end(struct sync_port *port)
static int sync_serial_open(struct inode *inode, struct file *file)
{
int dev = iminor(inode);
+ int ret = -EBUSY;
sync_port *port;
reg_dma_rw_cfg cfg = {.en = regk_dma_yes};
reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes};
+ mutex_lock(&sync_serial_mutex);
DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
{
DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev));
- return -ENODEV;
+ ret = -ENODEV;
+ goto out;
}
port = &ports[dev];
/* Allow open this device twice (assuming one reader and one writer) */
if (port->busy == 2)
{
DEBUG(printk(KERN_DEBUG "Device is busy.. \n"));
- return -EBUSY;
+ goto out;
}
@@ -459,7 +465,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
"synchronous serial 0 dma tr",
&ports[0])) {
printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ");
- return -EBUSY;
+ goto out;
} else if (request_irq(DMA_IN_INTR_VECT,
rx_interrupt,
0,
@@ -467,7 +473,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
&ports[0])) {
free_irq(DMA_OUT_INTR_VECT, &port[0]);
printk(KERN_CRIT "Can't allocate sync serial port 0 IRQ");
- return -EBUSY;
+ goto out;
} else if (crisv32_request_dma(OUT_DMA_NBR,
"synchronous serial 0 dma tr",
DMA_VERBOSE_ON_ERROR,
@@ -476,7 +482,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
free_irq(DMA_OUT_INTR_VECT, &port[0]);
free_irq(DMA_IN_INTR_VECT, &port[0]);
printk(KERN_CRIT "Can't allocate sync serial port 0 TX DMA channel");
- return -EBUSY;
+ goto out;
} else if (crisv32_request_dma(IN_DMA_NBR,
"synchronous serial 0 dma rec",
DMA_VERBOSE_ON_ERROR,
@@ -486,7 +492,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
free_irq(DMA_OUT_INTR_VECT, &port[0]);
free_irq(DMA_IN_INTR_VECT, &port[0]);
printk(KERN_CRIT "Can't allocate sync serial port 1 RX DMA channel");
- return -EBUSY;
+ goto out;
}
#endif
}
@@ -499,7 +505,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
"synchronous serial 1 dma tr",
&ports[1])) {
printk(KERN_CRIT "Can't allocate sync serial port 1 IRQ");
- return -EBUSY;
+ goto out;
} else if (request_irq(DMA7_INTR_VECT,
rx_interrupt,
0,
@@ -507,7 +513,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
&ports[1])) {
free_irq(DMA6_INTR_VECT, &ports[1]);
printk(KERN_CRIT "Can't allocate sync serial port 3 IRQ");
- return -EBUSY;
+ goto out;
} else if (crisv32_request_dma(
SYNC_SER1_TX_DMA_NBR,
"synchronous serial 1 dma tr",
@@ -517,7 +523,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
free_irq(DMA6_INTR_VECT, &ports[1]);
free_irq(DMA7_INTR_VECT, &ports[1]);
printk(KERN_CRIT "Can't allocate sync serial port 3 TX DMA channel");
- return -EBUSY;
+ goto out;
} else if (crisv32_request_dma(
SYNC_SER1_RX_DMA_NBR,
"synchronous serial 3 dma rec",
@@ -528,7 +534,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
free_irq(DMA6_INTR_VECT, &ports[1]);
free_irq(DMA7_INTR_VECT, &ports[1]);
printk(KERN_CRIT "Can't allocate sync serial port 3 RX DMA channel");
- return -EBUSY;
+ goto out;
}
#endif
}
@@ -554,7 +560,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
"synchronous serial manual irq",
&ports[0])) {
printk("Can't allocate sync serial manual irq");
- return -EBUSY;
+ goto out;
}
}
#ifdef CONFIG_ETRAXFS
@@ -565,7 +571,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
"synchronous serial manual irq",
&ports[1])) {
printk(KERN_CRIT "Can't allocate sync serial manual irq");
- return -EBUSY;
+ goto out;
}
}
#endif
@@ -578,7 +584,10 @@ static int sync_serial_open(struct inode *inode, struct file *file)
} /* port->init_irqs */
port->busy++;
- return 0;
+ ret = 0;
+out:
+ mutex_unlock(&sync_serial_mutex);
+ return ret;
}
static int sync_serial_release(struct inode *inode, struct file *file)
@@ -601,7 +610,7 @@ static int sync_serial_release(struct inode *inode, struct file *file)
static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
{
- int dev = iminor(file->f_path.dentry->d_inode);
+ int dev = iminor(file_inode(file));
unsigned int mask = 0;
sync_port *port;
DEBUGPOLL( static unsigned int prev_mask = 0; );
@@ -644,12 +653,12 @@ static unsigned int sync_serial_poll(struct file *file, poll_table *wait)
return mask;
}
-static int sync_serial_ioctl(struct inode *inode, struct file *file,
+static int sync_serial_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int return_val = 0;
int dma_w_size = regk_dma_set_w_size1;
- int dev = iminor(file->f_path.dentry->d_inode);
+ int dev = iminor(file_inode(file));
sync_port *port;
reg_sser_rw_tr_cfg tr_cfg;
reg_sser_rw_rec_cfg rec_cfg;
@@ -955,11 +964,23 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file,
return return_val;
}
+static long sync_serial_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ long ret;
+
+ mutex_lock(&sync_serial_mutex);
+ ret = sync_serial_ioctl_unlocked(file, cmd, arg);
+ mutex_unlock(&sync_serial_mutex);
+
+ return ret;
+}
+
/* NOTE: sync_serial_write does not support concurrency */
static ssize_t sync_serial_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
- int dev = iminor(file->f_path.dentry->d_inode);
+ int dev = iminor(file_inode(file));
DECLARE_WAITQUEUE(wait, current);
struct sync_port *port;
int trunc_count;
@@ -1082,7 +1103,7 @@ static ssize_t sync_serial_write(struct file *file, const char *buf,
static ssize_t sync_serial_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
- int dev = iminor(file->f_path.dentry->d_inode);
+ int dev = iminor(file_inode(file));
int avail;
sync_port *port;
unsigned char* start;
@@ -1124,7 +1145,8 @@ static ssize_t sync_serial_read(struct file * file, char * buf,
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
- interruptible_sleep_on(&port->in_wait_q);
+ wait_event_interruptible(port->in_wait_q,
+ !(start == end && !port->full));
if (signal_pending(current))
return -EINTR;