diff options
author | Tejun Heo <tj@kernel.org> | 2010-06-29 04:07:09 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-06-29 04:07:09 -0400 |
commit | 7bc465605ffa90b281d6b774fcb13911636a6d45 (patch) | |
tree | d3f17ab707db89632b47a8247c1d5b4716830e99 /drivers/media/video/ivtv | |
parent | b56c0d8937e665a27d90517ee7a746d0aa05af46 (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
Diffstat (limited to 'drivers/media/video/ivtv')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 26 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 8 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.c | 15 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.h | 2 |
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 | */ |
696 | static int __devinit ivtv_init_struct1(struct ivtv *itv) | 696 | static 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, ¶m); | ||
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); |
1211 | free_workqueue: | 1217 | free_worker: |
1212 | destroy_workqueue(itv->irq_work_queues); | 1218 | kthread_stop(itv->irq_worker_task); |
1213 | err: | 1219 | err: |
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 | ||
74 | void ivtv_irq_work_handler(struct work_struct *work) | 74 | void 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, ¶m); | ||
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 | ||
47 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id); | 47 | irqreturn_t ivtv_irq_handler(int irq, void *dev_id); |
48 | 48 | ||
49 | void ivtv_irq_work_handler(struct work_struct *work); | 49 | void ivtv_irq_work_handler(struct kthread_work *work); |
50 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); | 50 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); |
51 | void ivtv_unfinished_dma(unsigned long arg); | 51 | void ivtv_unfinished_dma(unsigned long arg); |
52 | 52 | ||