Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / ieee1394 / dv1394.c
index ecf6830..85c2d4c 100644 (file)
@@ -73,7 +73,7 @@
   - fix all XXX showstoppers
   - disable IR/IT DMA interrupts on shutdown
   - flush pci writes to the card by issuing a read
-  - devfs and character device dispatching (* needs testing with Linux 2.2.x)
+  - character device dispatching
   - switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!)
   - keep all video_cards in a list (for open() via chardev), set file->private_data = video
   - dv1394_poll should indicate POLLIN when receiving buffers are available
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
-#include <linux/ioctl32.h>
 #include <linux/compat.h>
 #include <linux/cdev.h>
 
 
 #include "ohci1394.h"
 
-#ifndef virt_to_page
-#define virt_to_page(x) MAP_NR(x)
-#endif
-
-#ifndef vmalloc_32
-#define vmalloc_32(x) vmalloc(x)
-#endif
-
-
 /* DEBUG LEVELS:
    0 - no debugging messages
    1 - some debugging messages, but none during DMA frame transmission
@@ -168,11 +158,16 @@ static inline void flush_pci_write(struct ti_ohci *ohci)
 static void it_tasklet_func(unsigned long data);
 static void ir_tasklet_func(unsigned long data);
 
+#ifdef CONFIG_COMPAT
+static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
+                              unsigned long arg);
+#endif
+
 /* GLOBAL DATA */
 
 /* list of all video_cards */
 static LIST_HEAD(dv1394_cards);
-static spinlock_t dv1394_cards_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dv1394_cards_lock);
 
 /* translate from a struct file* to the corresponding struct video_card* */
 
@@ -1101,7 +1096,6 @@ static int do_dv1394_init_default(struct video_card *video)
 
        init.api_version = DV1394_API_VERSION;
        init.n_frames = DV1394_MAX_FRAMES / 4;
-       /* the following are now set via devfs */
        init.channel = video->channel;
        init.format = video->pal_or_ntsc;
        init.cip_n = video->cip_n;
@@ -1272,7 +1266,7 @@ static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf)
        error-prone code in dv1394.
 */
 
-int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
+static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct video_card *video = file_to_video_card(file);
        int retval = -EINVAL;
@@ -1540,26 +1534,29 @@ static ssize_t dv1394_read(struct file *file,  char __user *buffer, size_t count
 
 /*** DEVICE IOCTL INTERFACE ************************************************/
 
-/* I *think* the VFS serializes ioctl() for us, so we don't have to worry
-   about situations like having two threads in here at once... */
-
-static int dv1394_ioctl(struct inode *inode, struct file *file,
-                          unsigned int cmd, unsigned long arg)
+static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct video_card *video = file_to_video_card(file);
+       struct video_card *video;
        unsigned long flags;
        int ret = -EINVAL;
        void __user *argp = (void __user *)arg;
 
        DECLARE_WAITQUEUE(wait, current);
 
+       lock_kernel();
+       video = file_to_video_card(file);
+
        /* serialize this to prevent multi-threaded mayhem */
        if (file->f_flags & O_NONBLOCK) {
-               if (down_trylock(&video->sem))
+               if (down_trylock(&video->sem)) {
+                       unlock_kernel();
                        return -EAGAIN;
+               }
        } else {
-               if (down_interruptible(&video->sem))
+               if (down_interruptible(&video->sem)) {
+                       unlock_kernel();
                        return -ERESTARTSYS;
+               }
        }
 
        switch(cmd)
@@ -1783,19 +1780,16 @@ static int dv1394_ioctl(struct inode *inode, struct file *file,
 
  out:
        up(&video->sem);
+       unlock_kernel();
        return ret;
 }
 
-
-
 /*** DEVICE FILE INTERFACE CONTINUED ***************************************/
 
 static int dv1394_open(struct inode *inode, struct file *file)
 {
        struct video_card *video = NULL;
 
-       /* if the device was opened through devfs, then file->private_data
-          has already been set to video by devfs */
        if (file->private_data) {
                video = (struct video_card*) file->private_data;
 
@@ -2165,7 +2159,10 @@ static struct file_operations dv1394_fops=
 {
        .owner =        THIS_MODULE,
        .poll =         dv1394_poll,
-       .ioctl =        dv1394_ioctl,
+       .unlocked_ioctl = dv1394_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = dv1394_compat_ioctl,
+#endif
        .mmap =         dv1394_mmap,
        .open =         dv1394_open,
        .write =        dv1394_write,
@@ -2208,14 +2205,12 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
        unsigned long flags;
        int i;
 
-       video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
+       video = kzalloc(sizeof(*video), GFP_KERNEL);
        if (!video) {
                printk(KERN_ERR "dv1394: cannot allocate video_card\n");
-               goto err;
+               return -1;
        }
 
-       memset(video, 0, sizeof(struct video_card));
-
        video->ohci = ohci;
        /* lower 2 bits of id indicate which of four "plugs"
           per host */
@@ -2268,37 +2263,14 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
        list_add_tail(&video->list, &dv1394_cards);
        spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 
-       if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR,
-                               IEEE1394_MINOR_BLOCK_DV1394*16 + video->id),
-                       S_IFCHR|S_IRUGO|S_IWUGO,
-                        "ieee1394/dv/host%d/%s/%s",
-                        (video->id>>2),
-                        (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
-                        (video->mode == MODE_RECEIVE ? "in" : "out")) < 0)
-                       goto err_free;
-
        debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
-
        return 0;
-
- err_free:
-       kfree(video);
- err:
-       return -1;
 }
 
 static void dv1394_un_init(struct video_card *video)
 {
-       char buf[32];
-
        /* obviously nobody has the driver open at this point */
        do_dv1394_shutdown(video, 1);
-       snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2),
-               (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
-               (video->mode == MODE_RECEIVE ? "in" : "out")
-               );
-
-       devfs_remove("ieee1394/%s", buf);
        kfree(video);
 }
 
@@ -2333,9 +2305,8 @@ static void dv1394_remove_host (struct hpsb_host *host)
                        dv1394_un_init(video);
        } while (video != NULL);
 
-       devfs_remove("ieee1394/dv/host%d/NTSC", id);
-       devfs_remove("ieee1394/dv/host%d/PAL", id);
-       devfs_remove("ieee1394/dv/host%d", id);
+       class_device_destroy(hpsb_protocol_class,
+               MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
 }
 
 static void dv1394_add_host (struct hpsb_host *host)
@@ -2349,9 +2320,9 @@ static void dv1394_add_host (struct hpsb_host *host)
 
        ohci = (struct ti_ohci *)host->hostdata;
 
-       devfs_mk_dir("ieee1394/dv/host%d", id);
-       devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
-       devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
+       class_device_create(hpsb_protocol_class, NULL, MKDEV(
+               IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
+               NULL, "dv1394-%d", id);
 
        dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
        dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
@@ -2507,15 +2478,16 @@ struct dv1394_status32 {
        u32 dropped_frames;
 };
 
-static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg,
-                             struct file *file)
+/* RED-PEN: this should use compat_alloc_userspace instead */
+
+static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct dv1394_init32 dv32;
        struct dv1394_init dv;
        mm_segment_t old_fs;
        int ret;
 
-       if (file->f_op->ioctl != dv1394_ioctl)
+       if (file->f_op->unlocked_ioctl != dv1394_ioctl)
                return -EFAULT;
 
        if (copy_from_user(&dv32, (void __user *)arg, sizeof(dv32)))
@@ -2531,28 +2503,25 @@ static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long a
 
        old_fs = get_fs();
        set_fs(KERNEL_DS);
-       ret = dv1394_ioctl(file->f_dentry->d_inode, file,
-                          DV1394_IOC_INIT, (unsigned long)&dv);
+       ret = dv1394_ioctl(file, DV1394_IOC_INIT, (unsigned long)&dv);
        set_fs(old_fs);
 
        return ret;
 }
 
-static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg,
-                                   struct file *file)
+static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct dv1394_status32 dv32;
        struct dv1394_status dv;
        mm_segment_t old_fs;
        int ret;
 
-       if (file->f_op->ioctl != dv1394_ioctl)
+       if (file->f_op->unlocked_ioctl != dv1394_ioctl)
                return -EFAULT;
 
        old_fs = get_fs();
        set_fs(KERNEL_DS);
-       ret = dv1394_ioctl(file->f_dentry->d_inode, file,
-                          DV1394_IOC_GET_STATUS, (unsigned long)&dv);
+       ret = dv1394_ioctl(file, DV1394_IOC_GET_STATUS, (unsigned long)&dv);
        set_fs(old_fs);
 
        if (!ret) {
@@ -2574,6 +2543,29 @@ static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned
 
        return ret;
 }
+
+
+
+static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       switch (cmd) {
+       case DV1394_IOC_SHUTDOWN:
+       case DV1394_IOC_SUBMIT_FRAMES:
+       case DV1394_IOC_WAIT_FRAMES:
+       case DV1394_IOC_RECEIVE_FRAMES:
+       case DV1394_IOC_START_RECEIVE:
+               return dv1394_ioctl(file, cmd, arg);
+
+       case DV1394_IOC32_INIT:
+               return handle_dv1394_init(file, cmd, arg);
+       case DV1394_IOC32_GET_STATUS:
+               return handle_dv1394_get_status(file, cmd, arg);
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
 #endif /* CONFIG_COMPAT */
 
 
@@ -2586,25 +2578,9 @@ MODULE_LICENSE("GPL");
 
 static void __exit dv1394_exit_module(void)
 {
-#ifdef CONFIG_COMPAT
-       int ret;
-
-       ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN);
-       ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES);
-       ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES);
-       ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES);
-       ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE);
-       ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT);
-       ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS);
-       if (ret)
-               printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n");
-#endif
-
        hpsb_unregister_protocol(&dv1394_driver);
-
        hpsb_unregister_highlevel(&dv1394_highlevel);
        cdev_del(&dv1394_cdev);
-       devfs_remove("ieee1394/dv");
 }
 
 static int __init dv1394_init_module(void)
@@ -2620,39 +2596,18 @@ static int __init dv1394_init_module(void)
                return ret;
        }
 
-       devfs_mk_dir("ieee1394/dv");
-
        hpsb_register_highlevel(&dv1394_highlevel);
 
        ret = hpsb_register_protocol(&dv1394_driver);
        if (ret) {
                printk(KERN_ERR "dv1394: failed to register protocol\n");
                hpsb_unregister_highlevel(&dv1394_highlevel);
-               devfs_remove("ieee1394/dv");
                cdev_del(&dv1394_cdev);
                return ret;
        }
 
-#ifdef CONFIG_COMPAT
-       {
-               /* First compatible ones */
-               ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL);
-               ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL);
-               ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL);
-               ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL);
-               ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL);
-
-               /* These need to be handled by translation */
-               ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init);
-               ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status);
-               if (ret)
-                       printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n");
-       }
-#endif
-
        return 0;
 }
 
 module_init(dv1394_init_module);
 module_exit(dv1394_exit_module);
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16);