V4L/DVB (9776): cx18: Change to per CX23418 device work queues for deferrable work...
authorAndy Walls <awalls@radix.net>
Wed, 26 Nov 2008 00:43:05 +0000 (21:43 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 30 Dec 2008 11:38:19 +0000 (09:38 -0200)
cx18: Change to per CX23418 device work queues for deferrable work handling.
Needed to support 2.6.22 and earlier kernels that can't selectively cancel
work orders.  Also will provide slightly better performance on SMP systems.

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-mailbox.c

index fbcbb500ca74304432e49b5850466be8e3a20b62..a893caff0aa9fe6d04994a376bcf3d2ad1f864f1 100644 (file)
@@ -56,9 +56,6 @@ struct cx18 *cx18_cards[CX18_MAX_CARDS];
 /* Protects cx18_cards_active */
 DEFINE_SPINLOCK(cx18_cards_lock);
 
-/* Queue for deferrable IRQ handling work for all cx18 cards in system */
-struct workqueue_struct *cx18_work_queue;
-
 /* add your revision and whatnot here */
 static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
        {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
@@ -446,6 +443,12 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
 
        spin_lock_init(&cx->lock);
 
+       cx->work_queue = create_singlethread_workqueue(cx->name);
+       if (cx->work_queue == NULL) {
+               CX18_ERR("Unable to create work hander thread\n");
+               return -ENOMEM;
+       }
+
        for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
                cx->epu_work_order[i].cx = cx;
                cx->epu_work_order[i].str = cx->epu_debug_str;
@@ -655,12 +658,9 @@ static int __devinit cx18_probe(struct pci_dev *dev,
 
        /* PCI Device Setup */
        retval = cx18_setup_pci(cx, dev, pci_id);
-       if (retval != 0) {
-               if (retval == -EIO)
-                       goto free_workqueue;
-               else if (retval == -ENXIO)
-                       goto free_mem;
-       }
+       if (retval != 0)
+               goto free_workqueue;
+
        /* save cx in the pci struct for later use */
        pci_set_drvdata(dev, cx);
 
@@ -830,6 +830,7 @@ free_map:
 free_mem:
        release_mem_region(cx->base_addr, CX18_MEM_SIZE);
 free_workqueue:
+       destroy_workqueue(cx->work_queue);
 err:
        if (retval == 0)
                retval = -ENODEV;
@@ -938,6 +939,8 @@ static void cx18_remove(struct pci_dev *pci_dev)
 
        cx18_cancel_epu_work_orders(cx);
 
+       destroy_workqueue(cx->work_queue);
+
        cx18_streams_cleanup(cx, 1);
 
        exit_cx18_i2c(cx);
@@ -979,17 +982,8 @@ static int module_start(void)
                printk(KERN_INFO "cx18:   Debug value must be >= 0 and <= 511!\n");
        }
 
-       cx18_work_queue = create_singlethread_workqueue("cx18");
-       if (cx18_work_queue == NULL) {
-               printk(KERN_ERR
-                      "cx18:   Unable to create work hander thread\n");
-               return -ENOMEM;
-       }
-
        if (pci_register_driver(&cx18_pci_driver)) {
                printk(KERN_ERR "cx18:   Error detecting PCI card\n");
-               destroy_workqueue(cx18_work_queue);
-               cx18_work_queue = NULL;
                return -ENODEV;
        }
        printk(KERN_INFO "cx18:  End initialization\n");
@@ -1002,9 +996,6 @@ static void module_cleanup(void)
 
        pci_unregister_driver(&cx18_pci_driver);
 
-       destroy_workqueue(cx18_work_queue);
-       cx18_work_queue = NULL;
-
        for (i = 0; i < cx18_cards_active; i++) {
                if (cx18_cards[i] == NULL)
                        continue;
index ca1f43781941b8af9f6468d89a4a470eacaee149..94c196a91295391b957e123886cee3e3e2691a7d 100644 (file)
@@ -447,6 +447,7 @@ struct cx18 {
        u32 sw2_irq_mask;
        u32 hw2_irq_mask;
 
+       struct workqueue_struct *work_queue;
        struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS];
        char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
 
@@ -478,7 +479,6 @@ extern struct cx18 *cx18_cards[];
 extern int cx18_cards_active;
 extern int cx18_first_minor;
 extern spinlock_t cx18_cards_lock;
-extern struct workqueue_struct *cx18_work_queue;
 
 /*==============Prototypes==================*/
 
index 70a82721b5519d34649e41eb6722861728c9831d..b013e817926a78c7d66c7dd56f3c1df0d356e7d5 100644 (file)
@@ -454,7 +454,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
         */
        submit = epu_cmd_irq(cx, order);
        if (submit > 0) {
-               queue_work(cx18_work_queue, &order->work);
+               queue_work(cx->work_queue, &order->work);
        }
 }