summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/dahdi/dahdi-base.c58
-rw-r--r--include/dahdi/kernel.h2
2 files changed, 26 insertions, 34 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c
index 7a46ecf..60a070e 100644
--- a/drivers/dahdi/dahdi-base.c
+++ b/drivers/dahdi/dahdi-base.c
@@ -4981,70 +4981,62 @@ static int dahdi_ioctl_iomux(struct file *file, unsigned long data)
{
struct dahdi_chan *const chan = chan_from_file(file);
unsigned long flags;
- int ret;
+ unsigned int iomask;
DEFINE_WAIT(wait);
- if (!chan)
- return -EINVAL;
+ if (get_user(iomask, (int __user *)data))
+ return -EFAULT;
- get_user(chan->iomask, (int __user *)data);
- if (!chan->iomask)
+ if (unlikely(!iomask || !chan))
return -EINVAL;
while (1) {
+ unsigned int wait_result;
- ret = 0;
+ wait_result = 0;
prepare_to_wait(&chan->eventbufq, &wait, TASK_INTERRUPTIBLE);
spin_lock_irqsave(&chan->lock, flags);
- /* if looking for read */
- if (chan->iomask & DAHDI_IOMUX_READ) {
- /* if read available */
+ chan->iomask = iomask;
+ if (iomask & DAHDI_IOMUX_READ) {
if ((chan->outreadbuf > -1) && !chan->rxdisable)
- ret |= DAHDI_IOMUX_READ;
+ wait_result |= DAHDI_IOMUX_READ;
}
-
- /* if looking for write avail */
- if (chan->iomask & DAHDI_IOMUX_WRITE) {
+ if (iomask & DAHDI_IOMUX_WRITE) {
if (chan->inwritebuf > -1)
- ret |= DAHDI_IOMUX_WRITE;
+ wait_result |= DAHDI_IOMUX_WRITE;
}
- /* if looking for write empty */
- if (chan->iomask & DAHDI_IOMUX_WRITEEMPTY) {
+ if (iomask & DAHDI_IOMUX_WRITEEMPTY) {
/* if everything empty -- be sure the transmitter is
* enabled */
chan->txdisable = 0;
if (chan->outwritebuf < 0)
- ret |= DAHDI_IOMUX_WRITEEMPTY;
+ wait_result |= DAHDI_IOMUX_WRITEEMPTY;
}
- /* if looking for signalling event */
- if (chan->iomask & DAHDI_IOMUX_SIGEVENT) {
- /* if event */
+ if (iomask & DAHDI_IOMUX_SIGEVENT) {
if (chan->eventinidx != chan->eventoutidx)
- ret |= DAHDI_IOMUX_SIGEVENT;
+ wait_result |= DAHDI_IOMUX_SIGEVENT;
}
spin_unlock_irqrestore(&chan->lock, flags);
- /* if something to return, or not to wait */
- if (ret || (chan->iomask & DAHDI_IOMUX_NOWAIT)) {
- /* set return value */
- put_user(ret, (int __user *)data);
- ret = 0;
- break; /* get out of loop */
+ if (wait_result || (iomask & DAHDI_IOMUX_NOWAIT)) {
+ put_user(wait_result, (int __user *)data);
+ break;
}
- if (!signal_pending(current)) {
- schedule();
- continue;
+ if (signal_pending(current)) {
+ finish_wait(&chan->eventbufq, &wait);
+ return -ERESTARTSYS;
}
- ret = -ERESTARTSYS;
- break;
+ schedule();
}
finish_wait(&chan->eventbufq, &wait);
+ spin_lock_irqsave(&chan->lock, flags);
chan->iomask = 0;
- return ret;
+ spin_unlock_irqrestore(&chan->lock, flags);
+ return 0;
}
#ifdef CONFIG_DAHDI_MIRROR
diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h
index d7b5ba1..f904da9 100644
--- a/include/dahdi/kernel.h
+++ b/include/dahdi/kernel.h
@@ -509,7 +509,7 @@ struct dahdi_chan {
int cadencepos; /*!< Where in the cadence we are */
/* I/O Mask */
- int iomask; /*! I/O Mux signal mask */
+ unsigned int iomask; /*! I/O Mux signal mask */
wait_queue_head_t sel; /*! thingy for select stuff */
/* HDLC state machines */