aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-06-29 04:07:09 -0400
committerTejun Heo <tj@kernel.org>2010-06-29 04:07:09 -0400
commit7bc465605ffa90b281d6b774fcb13911636a6d45 (patch)
treed3f17ab707db89632b47a8247c1d5b4716830e99
parentb56c0d8937e665a27d90517ee7a746d0aa05af46 (diff)
ivtv: use kthread_worker instead of workqueue
Upcoming workqueue updates will no longer guarantee fixed workqueue to worker kthread association, so giving RT priority to the irq worker won't work. Use kthread_worker which guarantees specific kthread association instead. This also makes setting the priority cleaner. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Andy Walls <awalls@md.metrocast.net> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: ivtv-devel@ivtvdriver.org Cc: linux-media@vger.kernel.org
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c26
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h8
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c15
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.h2
4 files changed, 24 insertions, 27 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 1b79475ca134..49e0b1cc3544 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -695,6 +695,8 @@ done:
695 */ 695 */
696static int __devinit ivtv_init_struct1(struct ivtv *itv) 696static int __devinit ivtv_init_struct1(struct ivtv *itv)
697{ 697{
698 struct sched_param param = { .sched_priority = 99 };
699
698 itv->base_addr = pci_resource_start(itv->pdev, 0); 700 itv->base_addr = pci_resource_start(itv->pdev, 0);
699 itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ 701 itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
700 itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ 702 itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */
@@ -706,13 +708,17 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
706 spin_lock_init(&itv->lock); 708 spin_lock_init(&itv->lock);
707 spin_lock_init(&itv->dma_reg_lock); 709 spin_lock_init(&itv->dma_reg_lock);
708 710
709 itv->irq_work_queues = create_singlethread_workqueue(itv->v4l2_dev.name); 711 init_kthread_worker(&itv->irq_worker);
710 if (itv->irq_work_queues == NULL) { 712 itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker,
711 IVTV_ERR("Could not create ivtv workqueue\n"); 713 itv->v4l2_dev.name);
714 if (IS_ERR(itv->irq_worker_task)) {
715 IVTV_ERR("Could not create ivtv task\n");
712 return -1; 716 return -1;
713 } 717 }
718 /* must use the FIFO scheduler as it is realtime sensitive */
719 sched_setscheduler(itv->irq_worker_task, SCHED_FIFO, &param);
714 720
715 INIT_WORK(&itv->irq_work_queue, ivtv_irq_work_handler); 721 init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
716 722
717 /* start counting open_id at 1 */ 723 /* start counting open_id at 1 */
718 itv->open_id = 1; 724 itv->open_id = 1;
@@ -996,7 +1002,7 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
996 /* PCI Device Setup */ 1002 /* PCI Device Setup */
997 retval = ivtv_setup_pci(itv, pdev, pci_id); 1003 retval = ivtv_setup_pci(itv, pdev, pci_id);
998 if (retval == -EIO) 1004 if (retval == -EIO)
999 goto free_workqueue; 1005 goto free_worker;
1000 if (retval == -ENXIO) 1006 if (retval == -ENXIO)
1001 goto free_mem; 1007 goto free_mem;
1002 1008
@@ -1208,8 +1214,8 @@ free_mem:
1208 release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); 1214 release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
1209 if (itv->has_cx23415) 1215 if (itv->has_cx23415)
1210 release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); 1216 release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
1211free_workqueue: 1217free_worker:
1212 destroy_workqueue(itv->irq_work_queues); 1218 kthread_stop(itv->irq_worker_task);
1213err: 1219err:
1214 if (retval == 0) 1220 if (retval == 0)
1215 retval = -ENODEV; 1221 retval = -ENODEV;
@@ -1353,9 +1359,9 @@ static void ivtv_remove(struct pci_dev *pdev)
1353 ivtv_set_irq_mask(itv, 0xffffffff); 1359 ivtv_set_irq_mask(itv, 0xffffffff);
1354 del_timer_sync(&itv->dma_timer); 1360 del_timer_sync(&itv->dma_timer);
1355 1361
1356 /* Stop all Work Queues */ 1362 /* Kill irq worker */
1357 flush_workqueue(itv->irq_work_queues); 1363 flush_kthread_worker(&itv->irq_worker);
1358 destroy_workqueue(itv->irq_work_queues); 1364 kthread_stop(itv->irq_worker_task);
1359 1365
1360 ivtv_streams_cleanup(itv, 1); 1366 ivtv_streams_cleanup(itv, 1);
1361 ivtv_udma_free(itv); 1367 ivtv_udma_free(itv);
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 5b45fd2b2645..51f7f2a9cf5e 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -51,7 +51,7 @@
51#include <linux/unistd.h> 51#include <linux/unistd.h>
52#include <linux/pagemap.h> 52#include <linux/pagemap.h>
53#include <linux/scatterlist.h> 53#include <linux/scatterlist.h>
54#include <linux/workqueue.h> 54#include <linux/kthread.h>
55#include <linux/mutex.h> 55#include <linux/mutex.h>
56#include <linux/slab.h> 56#include <linux/slab.h>
57#include <asm/uaccess.h> 57#include <asm/uaccess.h>
@@ -257,7 +257,6 @@ struct ivtv_mailbox_data {
257#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ 257#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */
258#define IVTV_F_I_INITED 21 /* set after first open */ 258#define IVTV_F_I_INITED 21 /* set after first open */
259#define IVTV_F_I_FAILED 22 /* set if first open failed */ 259#define IVTV_F_I_FAILED 22 /* set if first open failed */
260#define IVTV_F_I_WORK_INITED 23 /* worker thread was initialized */
261 260
262/* Event notifications */ 261/* Event notifications */
263#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ 262#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
@@ -663,8 +662,9 @@ struct ivtv {
663 /* Interrupts & DMA */ 662 /* Interrupts & DMA */
664 u32 irqmask; /* active interrupts */ 663 u32 irqmask; /* active interrupts */
665 u32 irq_rr_idx; /* round-robin stream index */ 664 u32 irq_rr_idx; /* round-robin stream index */
666 struct workqueue_struct *irq_work_queues; /* workqueue for PIO/YUV/VBI actions */ 665 struct kthread_worker irq_worker; /* kthread worker for PIO/YUV/VBI actions */
667 struct work_struct irq_work_queue; /* work entry */ 666 struct task_struct *irq_worker_task; /* task for irq_worker */
667 struct kthread_work irq_work; /* kthread work entry */
668 spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ 668 spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
669 int cur_dma_stream; /* index of current stream doing DMA (-1 if none) */ 669 int cur_dma_stream; /* index of current stream doing DMA (-1 if none) */
670 int cur_pio_stream; /* index of current stream doing PIO (-1 if none) */ 670 int cur_pio_stream; /* index of current stream doing PIO (-1 if none) */
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index fea1ec33b0df..9b4faf009196 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -71,19 +71,10 @@ static void ivtv_pio_work_handler(struct ivtv *itv)
71 write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); 71 write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
72} 72}
73 73
74void ivtv_irq_work_handler(struct work_struct *work) 74void ivtv_irq_work_handler(struct kthread_work *work)
75{ 75{
76 struct ivtv *itv = container_of(work, struct ivtv, irq_work_queue); 76 struct ivtv *itv = container_of(work, struct ivtv, irq_work);
77 77
78 DEFINE_WAIT(wait);
79
80 if (test_and_clear_bit(IVTV_F_I_WORK_INITED, &itv->i_flags)) {
81 struct sched_param param = { .sched_priority = 99 };
82
83 /* This thread must use the FIFO scheduler as it
84 is realtime sensitive. */
85 sched_setscheduler(current, SCHED_FIFO, &param);
86 }
87 if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags)) 78 if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
88 ivtv_pio_work_handler(itv); 79 ivtv_pio_work_handler(itv);
89 80
@@ -975,7 +966,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
975 } 966 }
976 967
977 if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) { 968 if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) {
978 queue_work(itv->irq_work_queues, &itv->irq_work_queue); 969 queue_kthread_work(&itv->irq_worker, &itv->irq_work);
979 } 970 }
980 971
981 spin_unlock(&itv->dma_reg_lock); 972 spin_unlock(&itv->dma_reg_lock);
diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/video/ivtv/ivtv-irq.h
index f879a5822e71..1e84433737cc 100644
--- a/drivers/media/video/ivtv/ivtv-irq.h
+++ b/drivers/media/video/ivtv/ivtv-irq.h
@@ -46,7 +46,7 @@
46 46
47irqreturn_t ivtv_irq_handler(int irq, void *dev_id); 47irqreturn_t ivtv_irq_handler(int irq, void *dev_id);
48 48
49void ivtv_irq_work_handler(struct work_struct *work); 49void ivtv_irq_work_handler(struct kthread_work *work);
50void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); 50void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock);
51void ivtv_unfinished_dma(unsigned long arg); 51void ivtv_unfinished_dma(unsigned long arg);
52 52