V4L/DVB (10756): cx18: Slim down instance handling, build names from v4l2_device...
authorAndy Walls <awalls@radix.net>
Sat, 14 Feb 2009 20:08:37 +0000 (17:08 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:01 +0000 (12:43 -0300)
Convert card instance handling to a lighter weight mechanism like ivtv.
Also convert name strings and debug messages to use v4l2_device.name.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-streams.c

index 2a45bbc757e8889bc665f85931422ccfc41cc227..f69e688ab6f4fb6692948b6f986000363c97aa68 100644 (file)
 
 #include <media/tveeprom.h>
 
-
-/* var to keep track of the number of array elements in use */
-int cx18_cards_active;
-
 /* If you have already X v4l cards, then set this to X. This way
    the device numbers stay matched. Example: you have a WinTV card
    without radio and a Compro H900 with. Normally this would give a
@@ -50,12 +46,6 @@ int cx18_cards_active;
    setting this to 1 you ensure that radio0 is now also radio1. */
 int cx18_first_minor;
 
-/* Master variable for all cx18 info */
-struct cx18 *cx18_cards[CX18_MAX_CARDS];
-
-/* Protects cx18_cards_active */
-DEFINE_SPINLOCK(cx18_cards_lock);
-
 /* add your revision and whatnot here */
 static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
        {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
@@ -65,6 +55,8 @@ static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
 
+static atomic_t cx18_instance = ATOMIC_INIT(0);
+
 /* Parameter declarations */
 static int cardtype[CX18_MAX_CARDS];
 static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
@@ -491,9 +483,9 @@ static void cx18_process_options(struct cx18 *cx)
                cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */
        }
 
-       cx->options.cardtype = cardtype[cx->num];
-       cx->options.tuner = tuner[cx->num];
-       cx->options.radio = radio[cx->num];
+       cx->options.cardtype = cardtype[cx->instance];
+       cx->options.tuner = tuner[cx->instance];
+       cx->options.radio = radio[cx->instance];
 
        cx->std = cx18_parse_std(cx);
        if (cx->options.cardtype == -1) {
@@ -550,7 +542,7 @@ done:
 }
 
 /* Precondition: the cx18 structure has been memset to 0. Only
-   the dev and num fields have been filled in.
+   the dev and instance fields have been filled in.
    No assumptions on the card type may be made here (see cx18_init_struct2
    for that).
  */
@@ -567,7 +559,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
        mutex_init(&cx->epu2apu_mb_lock);
        mutex_init(&cx->epu2cpu_mb_lock);
 
-       cx->work_queue = create_singlethread_workqueue(cx->name);
+       cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name);
        if (cx->work_queue == NULL) {
                CX18_ERR("Unable to create work hander thread\n");
                return -ENOMEM;
@@ -647,15 +639,16 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
        CX18_DEBUG_INFO("Enabling pci device\n");
 
        if (pci_enable_device(pci_dev)) {
-               CX18_ERR("Can't enable device %d!\n", cx->num);
+               CX18_ERR("Can't enable device %d!\n", cx->instance);
                return -EIO;
        }
        if (pci_set_dma_mask(pci_dev, 0xffffffff)) {
-               CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
+               CX18_ERR("No suitable DMA available, card %d\n", cx->instance);
                return -EIO;
        }
        if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
-               CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
+               CX18_ERR("Cannot request encoder memory region, card %d\n",
+                        cx->instance);
                return -EIO;
        }
 
@@ -741,44 +734,42 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
        u32 devtype;
        struct cx18 *cx;
 
-       spin_lock(&cx18_cards_lock);
-
-       /* Make sure we've got a place for this card */
-       if (cx18_cards_active == CX18_MAX_CARDS) {
-               printk(KERN_ERR "cx18:  Maximum number of cards detected (%d).\n",
-                             cx18_cards_active);
-               spin_unlock(&cx18_cards_lock);
+       /* FIXME - module parameter arrays constrain max instances */
+       i = atomic_inc_return(&cx18_instance) - 1;
+       if (i >= CX18_MAX_CARDS) {
+               printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
+                      "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
                return -ENOMEM;
        }
 
        cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
-       if (!cx) {
-               spin_unlock(&cx18_cards_lock);
+       if (cx == NULL) {
+               printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
+                      i);
                return -ENOMEM;
        }
-       cx18_cards[cx18_cards_active] = cx;
-       cx->num = cx18_cards_active++;
-       snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num);
-       CX18_INFO("Initializing card #%d\n", cx->num);
-
-       spin_unlock(&cx18_cards_lock);
-
        cx->pci_dev = pci_dev;
+       cx->instance = i;
+
        retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev);
        if (retval) {
-               CX18_ERR("Call to v4l2_device_register() failed\n");
-               goto err;
+               printk(KERN_ERR "cx18: v4l2_device_register of card %d failed"
+                      "\n", cx->instance);
+               kfree(cx);
+               return retval;
        }
-       CX18_DEBUG_INFO("registered v4l2_device name: %s\n", cx->v4l2_dev.name);
+       snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d",
+                cx->instance);
+       CX18_INFO("Initializing card %d\n", cx->instance);
 
        cx18_process_options(cx);
        if (cx->options.cardtype == -1) {
                retval = -ENODEV;
-               goto unregister_v4l2;
+               goto err;
        }
        if (cx18_init_struct1(cx)) {
                retval = -ENOMEM;
-               goto unregister_v4l2;
+               goto err;
        }
 
        CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
@@ -829,8 +820,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
                goto free_map;
        }
 
-       CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);
-
        if (cx->card->hw_all & CX18_HW_TVEEPROM) {
                /* Based on the model number the cardtype may be changed.
                   The PCI IDs are not always reliable. */
@@ -847,7 +836,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
 
        /* Register IRQ */
        retval = request_irq(cx->pci_dev->irq, cx18_irq_handler,
-                            IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
+                            IRQF_SHARED | IRQF_DISABLED,
+                            cx->v4l2_dev.name, (void *)cx);
        if (retval) {
                CX18_ERR("Failed to register irq %d\n", retval);
                goto free_i2c;
@@ -933,8 +923,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
                goto free_streams;
        }
 
-       CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
-
+       CX18_INFO("Initialized card: %s\n", cx->card_name);
        return 0;
 
 free_streams:
@@ -949,18 +938,13 @@ free_mem:
        release_mem_region(cx->base_addr, CX18_MEM_SIZE);
 free_workqueue:
        destroy_workqueue(cx->work_queue);
-unregister_v4l2:
-       v4l2_device_unregister(&cx->v4l2_dev);
 err:
        if (retval == 0)
                retval = -ENODEV;
        CX18_ERR("Error %d on initialization\n", retval);
 
-       i = cx->num;
-       spin_lock(&cx18_cards_lock);
-       kfree(cx18_cards[i]);
-       cx18_cards[i] = NULL;
-       spin_unlock(&cx18_cards_lock);
+       v4l2_device_unregister(&cx->v4l2_dev);
+       kfree(cx);
        return retval;
 }
 
@@ -1069,9 +1053,9 @@ static void cx18_cancel_epu_work_orders(struct cx18 *cx)
 static void cx18_remove(struct pci_dev *pci_dev)
 {
        struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct cx18 *cx = container_of(v4l2_dev, struct cx18, v4l2_dev);
+       struct cx18 *cx = to_cx18(v4l2_dev);
 
-       CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
+       CX18_DEBUG_INFO("Removing Card\n");
 
        /* Stop all captures */
        CX18_DEBUG_INFO("Stopping all streams\n");
@@ -1099,10 +1083,12 @@ static void cx18_remove(struct pci_dev *pci_dev)
        release_mem_region(cx->base_addr, CX18_MEM_SIZE);
 
        pci_disable_device(cx->pci_dev);
+       /* FIXME - we leak cx->vbi.sliced_mpeg_data[i] allocations */
 
-       v4l2_device_unregister(v4l2_dev);
+       CX18_INFO("Removed %s\n", cx->card_name);
 
-       CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
+       v4l2_device_unregister(v4l2_dev);
+       kfree(cx);
 }
 
 /* define a pci_driver for card detection */
@@ -1117,8 +1103,6 @@ static int module_start(void)
 {
        printk(KERN_INFO "cx18:  Start initialization, version %s\n", CX18_VERSION);
 
-       memset(cx18_cards, 0, sizeof(cx18_cards));
-
        /* Validate parameters */
        if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
                printk(KERN_ERR "cx18:  Exiting, cx18_first_minor must be between 0 and %d\n",
@@ -1141,16 +1125,7 @@ static int module_start(void)
 
 static void module_cleanup(void)
 {
-       int i;
-
        pci_unregister_driver(&cx18_pci_driver);
-
-       for (i = 0; i < cx18_cards_active; i++) {
-               if (cx18_cards[i] == NULL)
-                       continue;
-               kfree(cx18_cards[i]);
-       }
-
 }
 
 module_init(module_start);
index 7fc914c521f7cf22f42831ab79fc1021a5c1dfba..def82bd1078ad5e8ea495a3cce20078091ec139d 100644 (file)
 /* Flag to turn on high volume debugging */
 #define CX18_DBGFLG_HIGHVOL (1 << 8)
 
-/* NOTE: extra space before comma in 'cx->num , ## args' is required for
+/* NOTE: extra space before comma in 'fmt , ## args' is required for
    gcc-2.95, otherwise it won't compile. */
 #define CX18_DEBUG(x, type, fmt, args...) \
        do { \
                if ((x) & cx18_debug) \
-                       printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \
+                       v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
        } while (0)
 #define CX18_DEBUG_WARN(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
 #define CX18_DEBUG_INFO(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
 #define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
        do { \
                if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
-                       printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \
+                       v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
        } while (0)
 #define CX18_DEBUG_HI_WARN(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
 #define CX18_DEBUG_HI_INFO(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
 #define CX18_DEBUG_HI_IRQ(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
 
 /* Standard kernel messages */
-#define CX18_ERR(fmt, args...)      printk(KERN_ERR  "cx18-%d: " fmt, cx->num , ## args)
-#define CX18_WARN(fmt, args...)     printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args)
-#define CX18_INFO(fmt, args...)     printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args)
+#define CX18_ERR(fmt, args...)      v4l2_err(&cx->v4l2_dev, fmt , ## args)
+#define CX18_WARN(fmt, args...)     v4l2_warn(&cx->v4l2_dev, fmt , ## args)
+#define CX18_INFO(fmt, args...)     v4l2_info(&cx->v4l2_dev, fmt , ## args)
 
 /* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
 #define MPEG_FRAME_TYPE_IFRAME 1
@@ -445,8 +445,7 @@ struct cx18_i2c_algo_callback_data {
 
 /* Struct to hold info about cx18 cards */
 struct cx18 {
-       int num;                /* board number, -1 during init! */
-       char name[8];           /* board name for printk and interrupts (e.g. 'cx180') */
+       int instance;
        struct pci_dev *pci_dev;
        struct v4l2_device v4l2_dev;
 
@@ -455,8 +454,8 @@ struct cx18 {
        const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
        u8 is_50hz;
        u8 is_60hz;
-       u8 is_out_50hz;
-       u8 is_out_60hz;
+       u8 is_out_50hz; /* FIXME - remove, we don't have an output decoder */
+       u8 is_out_60hz; /* FIXME - remove, we don't have an output decoder */
        u8 nof_inputs;          /* number of video inputs */
        u8 nof_audio_inputs;    /* number of audio inputs */
        u16 buffer_id;          /* buffer ID counter */
@@ -547,11 +546,13 @@ struct cx18 {
        v4l2_std_id tuner_std;  /* The norm of the tuner (fixed) */
 };
 
+static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct cx18, v4l2_dev);
+}
+
 /* Globals */
-extern struct cx18 *cx18_cards[];
-extern int cx18_cards_active;
 extern int cx18_first_minor;
-extern spinlock_t cx18_cards_lock;
 
 /*==============Prototypes==================*/
 
index 68dd50ac4bfef97f39da3792c5a471111d521b95..757982ea37660340531b87a2a73df3e4fa8388f4 100644 (file)
@@ -682,38 +682,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
 
 int cx18_v4l2_open(struct file *filp)
 {
-       int res, x, y = 0;
-       struct cx18 *cx = NULL;
-       struct cx18_stream *s = NULL;
-       int minor = video_devdata(filp)->minor;
-
-       /* Find which card this open was on */
-       spin_lock(&cx18_cards_lock);
-       for (x = 0; cx == NULL && x < cx18_cards_active; x++) {
-               /* find out which stream this open was on */
-               for (y = 0; y < CX18_MAX_STREAMS; y++) {
-                       if (cx18_cards[x] == NULL)
-                               continue;
-                       s = &cx18_cards[x]->streams[y];
-                       if (s->video_dev && s->video_dev->minor == minor) {
-                               cx = cx18_cards[x];
-                               break;
-                       }
-               }
-       }
-       spin_unlock(&cx18_cards_lock);
-
-       if (cx == NULL) {
-               /* Couldn't find a device registered
-                  on that minor, shouldn't happen! */
-               printk(KERN_WARNING "No cx18 device found on minor %d\n",
-                               minor);
-               return -ENXIO;
-       }
+       int res;
+       struct video_device *video_dev = video_devdata(filp);
+       struct cx18_stream *s = video_get_drvdata(video_dev);
+       struct cx18 *cx = s->cx;;
 
        mutex_lock(&cx->serialize_lock);
        if (cx18_init_on_first_open(cx)) {
-               CX18_ERR("Failed to initialize on minor %d\n", minor);
+               CX18_ERR("Failed to initialize on minor %d\n",
+                        video_dev->minor);
                mutex_unlock(&cx->serialize_lock);
                return -ENXIO;
        }
index 200d9257a926af61ea1002c9133ccd0a5b691538..db2c3e6997d0fb178145d8bbe6a301d88c587954 100644 (file)
@@ -358,7 +358,7 @@ int init_cx18_i2c(struct cx18 *cx)
                cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
 
                sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
-                               " #%d-%d", cx->num, i);
+                               " #%d-%d", cx->instance, i);
                i2c_set_adapdata(&cx->i2c_adap[i], cx);
 
                memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
index 5c8e9cb244f99217de76da7ddd06ba2e02b556ae..3277b3d3ceae7e70aeb0f2cb74d2ee09617a40ce 100644 (file)
@@ -387,20 +387,17 @@ static int cx18_g_chip_ident(struct file *file, void *fh,
 static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
 {
        struct v4l2_dbg_register *regs = arg;
-       unsigned long flags;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
                return -EINVAL;
 
-       spin_lock_irqsave(&cx18_cards_lock, flags);
        regs->size = 4;
        if (cmd == VIDIOC_DBG_G_REGISTER)
                regs->val = cx18_read_enc(cx, regs->reg);
        else
                cx18_write_enc(cx, regs->val, regs->reg);
-       spin_unlock_irqrestore(&cx18_cards_lock, flags);
        return 0;
 }
 
@@ -847,7 +844,7 @@ static int cx18_log_status(struct file *file, void *fh)
        int i;
 
        CX18_INFO("=================  START STATUS CARD #%d  "
-                 "=================\n", cx->num);
+                 "=================\n", cx->instance);
        CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
        if (cx->hw_flags & CX18_HW_TVEEPROM) {
                struct tveeprom tv;
@@ -865,7 +862,7 @@ static int cx18_log_status(struct file *file, void *fh)
        mutex_unlock(&cx->gpio_lock);
        CX18_INFO("Tuner: %s\n",
                test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
-       cx2341x_log_status(&cx->params, cx->name);
+       cx2341x_log_status(&cx->params, cx->v4l2_dev.name);
        CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
        for (i = 0; i < CX18_MAX_STREAMS; i++) {
                struct cx18_stream *s = &cx->streams[i];
@@ -880,7 +877,8 @@ static int cx18_log_status(struct file *file, void *fh)
        CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
                        (long long)cx->mpg_data_received,
                        (long long)cx->vbi_data_inserted);
-       CX18_INFO("==================  END STATUS CARD #%d  ==================\n", cx->num);
+       CX18_INFO("==================  END STATUS CARD #%d  "
+                 "==================\n", cx->instance);
        return 0;
 }
 
index 778aa0c0f9b545dff009dbb7d79401cdd693fe40..eff4a14d01522a330e7706d1f4b23369b25fca8d 100644 (file)
@@ -130,7 +130,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
        struct cx18_stream *s = &cx->streams[type];
        u32 cap = cx->v4l2_cap;
        int num_offset = cx18_stream_info[type].num_offset;
-       int num = cx->num + cx18_first_minor + num_offset;
+       int num = cx->instance + cx18_first_minor + num_offset;
 
        /* These four fields are always initialized. If video_dev == NULL, then
           this stream is not in use. In that case no other fields but these
@@ -170,11 +170,11 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
                return -ENOMEM;
        }
 
-       snprintf(s->video_dev->name, sizeof(s->video_dev->name), "cx18-%d",
-                       cx->num);
+       snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s",
+                cx->v4l2_dev.name, s->name);
 
        s->video_dev->num = num;
-       s->video_dev->parent = &cx->pci_dev->dev;
+       s->video_dev->v4l2_dev = &cx->v4l2_dev;
        s->video_dev->fops = &cx18_v4l2_enc_fops;
        s->video_dev->release = video_device_release;
        s->video_dev->tvnorms = V4L2_STD_ALL;
@@ -239,6 +239,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
                        num = s_mpg->video_dev->num
                            + cx18_stream_info[type].num_offset;
        }
+       video_set_drvdata(s->video_dev, s);
 
        /* Register device. First try the desired minor, then any free one. */
        ret = video_register_device(s->video_dev, vfl_type, num);