Merge branch 'for-linus' of git://neil.brown.name/md
[pandora-kernel.git] / drivers / uio / uio.c
index 0a12e90..3a6934b 100644 (file)
@@ -297,12 +297,17 @@ static int uio_open(struct inode *inode, struct file *filep)
        struct uio_listener *listener;
        int ret = 0;
 
+       lock_kernel();
        idev = idr_find(&uio_idr, iminor(inode));
-       if (!idev)
-               return -ENODEV;
+       if (!idev) {
+               ret = -ENODEV;
+               goto out;
+       }
 
-       if (!try_module_get(idev->owner))
-               return -ENODEV;
+       if (!try_module_get(idev->owner)) {
+               ret = -ENODEV;
+               goto out;
+       }
 
        listener = kmalloc(sizeof(*listener), GFP_KERNEL);
        if (!listener) {
@@ -319,7 +324,7 @@ static int uio_open(struct inode *inode, struct file *filep)
                if (ret)
                        goto err_infoopen;
        }
-
+       unlock_kernel();
        return 0;
 
 err_infoopen:
@@ -329,6 +334,8 @@ err_alloc_listener:
 
        module_put(idev->owner);
 
+out:
+       unlock_kernel();
        return ret;
 }
 
@@ -420,6 +427,31 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
        return retval;
 }
 
+static ssize_t uio_write(struct file *filep, const char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       struct uio_listener *listener = filep->private_data;
+       struct uio_device *idev = listener->dev;
+       ssize_t retval;
+       s32 irq_on;
+
+       if (idev->info->irq == UIO_IRQ_NONE)
+               return -EIO;
+
+       if (count != sizeof(s32))
+               return -EINVAL;
+
+       if (!idev->info->irqcontrol)
+               return -ENOSYS;
+
+       if (copy_from_user(&irq_on, buf, count))
+               return -EFAULT;
+
+       retval = idev->info->irqcontrol(idev->info, irq_on);
+
+       return retval ? retval : sizeof(s32);
+}
+
 static int uio_find_mem_index(struct vm_area_struct *vma)
 {
        int mi;
@@ -539,6 +571,7 @@ static const struct file_operations uio_fops = {
        .open           = uio_open,
        .release        = uio_release,
        .read           = uio_read,
+       .write          = uio_write,
        .mmap           = uio_mmap,
        .poll           = uio_poll,
        .fasync         = uio_fasync,