V4L/DVB (10645): vivi: introduce v4l2_device and do several cleanups
authorHans Verkuil <hverkuil@xs4all.nl>
Sat, 14 Feb 2009 16:23:12 +0000 (13:23 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:42:50 +0000 (12:42 -0300)
- add v4l2_device
- remove BKL
- make the debug parameter settable on the fly
- set bus_info in querycap

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/vivi.c

index 0f25d68..625e966 100644 (file)
 #include <linux/videodev.h>
 #endif
 #include <linux/interrupt.h>
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/kthread.h>
 #include <linux/highmem.h>
 #include <linux/freezer.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include "font.h"
 
 #define VIVI_MODULE_NAME "vivi"
 
 #define WAKE_DENOMINATOR 1001
 #define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
 
-#include "font.h"
-
 #define VIVI_MAJOR_VERSION 0
-#define VIVI_MINOR_VERSION 5
+#define VIVI_MINOR_VERSION 6
 #define VIVI_RELEASE 0
 #define VIVI_VERSION \
        KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
 
-/* Declare static vars that will be used as parameters */
-static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
-static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
-static int n_devs = 1;                 /* Number of virtual devices */
+MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
+MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static unsigned video_nr = -1;
+module_param(video_nr, uint, 0644);
+MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
+
+static unsigned n_devs = 1;
+module_param(n_devs, uint, 0644);
+MODULE_PARM_DESC(n_devs, "number of video devices to create");
+
+static unsigned debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit, uint, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
 
 /* supported controls */
 static struct v4l2_queryctrl vivi_qctrl[] = {
@@ -112,11 +127,8 @@ static struct v4l2_queryctrl vivi_qctrl[] = {
 
 static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
 
-#define dprintk(dev, level, fmt, arg...)                               \
-       do {                                                            \
-               if (dev->vfd->debug >= (level))                         \
-                       printk(KERN_DEBUG "vivi: " fmt , ## arg);       \
-       } while (0)
+#define dprintk(dev, level, fmt, arg...) \
+       v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
 
 /* ------------------------------------------------------------------
        Basic structures
@@ -206,6 +218,7 @@ static LIST_HEAD(vivi_devlist);
 
 struct vivi_dev {
        struct list_head           vivi_devlist;
+       struct v4l2_device         v4l2_dev;
 
        spinlock_t                 slock;
        struct mutex               mutex;
@@ -656,7 +669,7 @@ static int vivi_start_thread(struct vivi_fh *fh)
        dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
 
        if (IS_ERR(dma_q->kthread)) {
-               printk(KERN_ERR "vivi: kernel_thread() failed\n");
+               v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
                return PTR_ERR(dma_q->kthread);
        }
        /* Wakes thread */
@@ -799,8 +812,12 @@ static struct videobuf_queue_ops vivi_video_qops = {
 static int vidioc_querycap(struct file *file, void  *priv,
                                        struct v4l2_capability *cap)
 {
+       struct vivi_fh  *fh  = priv;
+       struct vivi_dev *dev = fh->dev;
+
        strcpy(cap->driver, "vivi");
        strcpy(cap->card, "vivi");
+       strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
        cap->version = VIVI_VERSION;
        cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
                                V4L2_CAP_STREAMING     |
@@ -1124,32 +1141,21 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static int vivi_open(struct file *file)
 {
-       int minor = video_devdata(file)->minor;
-       struct vivi_dev *dev;
+       struct vivi_dev *dev = video_drvdata(file);
        struct vivi_fh *fh = NULL;
        int i;
        int retval = 0;
 
-       printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
-
-       lock_kernel();
-       list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
-               if (dev->vfd->minor == minor)
-                       goto found;
-       unlock_kernel();
-       return -ENODEV;
-
-found:
        mutex_lock(&dev->mutex);
        dev->users++;
 
        if (dev->users > 1) {
                dev->users--;
-               retval = -EBUSY;
-               goto unlock;
+               mutex_unlock(&dev->mutex);
+               return -EBUSY;
        }
 
-       dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
+       dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
                v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
 
        /* allocate + initialize per filehandle data */
@@ -1157,14 +1163,11 @@ found:
        if (NULL == fh) {
                dev->users--;
                retval = -ENOMEM;
-               goto unlock;
        }
-unlock:
        mutex_unlock(&dev->mutex);
-       if (retval) {
-               unlock_kernel();
+
+       if (retval)
                return retval;
-       }
 
        file->private_data = fh;
        fh->dev      = dev;
@@ -1193,7 +1196,6 @@ unlock:
                        sizeof(struct vivi_buffer), fh);
 
        vivi_start_thread(fh);
-       unlock_kernel();
 
        return 0;
 }
@@ -1249,32 +1251,6 @@ static int vivi_close(struct file *file)
        return 0;
 }
 
-static int vivi_release(void)
-{
-       struct vivi_dev *dev;
-       struct list_head *list;
-
-       while (!list_empty(&vivi_devlist)) {
-               list = vivi_devlist.next;
-               list_del(list);
-               dev = list_entry(list, struct vivi_dev, vivi_devlist);
-
-               if (-1 != dev->vfd->minor) {
-                       printk(KERN_INFO "%s: unregistering /dev/video%d\n",
-                               VIVI_MODULE_NAME, dev->vfd->num);
-                       video_unregister_device(dev->vfd);
-               } else {
-                       printk(KERN_INFO "%s: releasing /dev/video%d\n",
-                               VIVI_MODULE_NAME, dev->vfd->num);
-                       video_device_release(dev->vfd);
-               }
-
-               kfree(dev);
-       }
-
-       return 0;
-}
-
 static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct vivi_fh  *fh = file->private_data;
@@ -1337,84 +1313,126 @@ static struct video_device vivi_template = {
        .tvnorms              = V4L2_STD_525_60,
        .current_norm         = V4L2_STD_NTSC_M,
 };
+
 /* -----------------------------------------------------------------
        Initialization and module stuff
    ------------------------------------------------------------------*/
 
-/* This routine allocates from 1 to n_devs virtual drivers.
+static int vivi_release(void)
+{
+       struct vivi_dev *dev;
+       struct list_head *list;
 
-   The real maximum number of virtual drivers will depend on how many drivers
-   will succeed. This is limited to the maximum number of devices that
-   videodev supports, which is equal to VIDEO_NUM_DEVICES.
- */
-static int __init vivi_init(void)
+       while (!list_empty(&vivi_devlist)) {
+               list = vivi_devlist.next;
+               list_del(list);
+               dev = list_entry(list, struct vivi_dev, vivi_devlist);
+
+               v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n",
+                       dev->vfd->num);
+               video_unregister_device(dev->vfd);
+               v4l2_device_unregister(&dev->v4l2_dev);
+               kfree(dev);
+       }
+
+       return 0;
+}
+
+static int __init vivi_create_instance(int i)
 {
-       int ret = -ENOMEM, i;
        struct vivi_dev *dev;
        struct video_device *vfd;
+       int ret;
 
-       if (n_devs <= 0)
-               n_devs = 1;
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
 
-       for (i = 0; i < n_devs; i++) {
-               dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-               if (!dev)
-                       break;
+       snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
+                       "%s-%03d", VIVI_MODULE_NAME, i);
+       ret = v4l2_device_register(NULL, &dev->v4l2_dev);
+       if (ret)
+               goto free_dev;
 
-               /* init video dma queues */
-               INIT_LIST_HEAD(&dev->vidq.active);
-               init_waitqueue_head(&dev->vidq.wq);
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       init_waitqueue_head(&dev->vidq.wq);
 
-               /* initialize locks */
-               spin_lock_init(&dev->slock);
-               mutex_init(&dev->mutex);
+       /* initialize locks */
+       spin_lock_init(&dev->slock);
+       mutex_init(&dev->mutex);
 
-               vfd = video_device_alloc();
-               if (!vfd) {
-                       kfree(dev);
-                       break;
-               }
+       ret = -ENOMEM;
+       vfd = video_device_alloc();
+       if (!vfd)
+               goto unreg_dev;
 
-               *vfd = vivi_template;
+       *vfd = vivi_template;
 
-               ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-               if (ret < 0) {
-                       video_device_release(vfd);
-                       kfree(dev);
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+       if (ret < 0)
+               goto rel_vdev;
 
-                       /* If some registers succeeded, keep driver */
-                       if (i)
-                               ret = 0;
+       video_set_drvdata(vfd, dev);
 
-                       break;
-               }
+       /* Now that everything is fine, let's add it to device list */
+       list_add_tail(&dev->vivi_devlist, &vivi_devlist);
 
-               /* Now that everything is fine, let's add it to device list */
-               list_add_tail(&dev->vivi_devlist, &vivi_devlist);
+       snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
+                       vivi_template.name, vfd->num);
 
-               snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
-                        vivi_template.name, vfd->minor);
+       if (video_nr >= 0)
+               video_nr++;
 
-               if (video_nr >= 0)
-                       video_nr++;
+       dev->vfd = vfd;
+       v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
+                       vfd->num);
+       return 0;
+
+rel_vdev:
+       video_device_release(vfd);
+unreg_dev:
+       v4l2_device_unregister(&dev->v4l2_dev);
+free_dev:
+       kfree(dev);
+       return ret;
+}
 
-               dev->vfd = vfd;
-               printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
-                       VIVI_MODULE_NAME, vfd->num);
+/* This routine allocates from 1 to n_devs virtual drivers.
+
+   The real maximum number of virtual drivers will depend on how many drivers
+   will succeed. This is limited to the maximum number of devices that
+   videodev supports, which is equal to VIDEO_NUM_DEVICES.
+ */
+static int __init vivi_init(void)
+{
+       int ret, i;
+
+       if (n_devs <= 0)
+               n_devs = 1;
+
+       for (i = 0; i < n_devs; i++) {
+               ret = vivi_create_instance(i);
+               if (ret) {
+                       /* If some instantiations succeeded, keep driver */
+                       if (i)
+                               ret = 0;
+                       break;
+               }
        }
 
        if (ret < 0) {
-               vivi_release();
                printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
-       } else {
-               printk(KERN_INFO "Video Technology Magazine Virtual Video "
+               return ret;
+       }
+
+       printk(KERN_INFO "Video Technology Magazine Virtual Video "
                        "Capture Board ver %u.%u.%u successfully loaded.\n",
                        (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
                        VIVI_VERSION & 0xFF);
 
-               /* n_devs will reflect the actual number of allocated devices */
-               n_devs = i;
-       }
+       /* n_devs will reflect the actual number of allocated devices */
+       n_devs = i;
 
        return ret;
 }
@@ -1426,19 +1444,3 @@ static void __exit vivi_exit(void)
 
 module_init(vivi_init);
 module_exit(vivi_exit);
-
-MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
-MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
-MODULE_LICENSE("Dual BSD/GPL");
-
-module_param(video_nr, uint, 0444);
-MODULE_PARM_DESC(video_nr, "video iminor start number");
-
-module_param(n_devs, uint, 0444);
-MODULE_PARM_DESC(n_devs, "number of video devices to create");
-
-module_param_named(debug, vivi_template.debug, int, 0444);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");