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 t...@kernel.org
Cc: Andy Walls awa...@md.metrocast.net
Cc: Andrew Morton a...@linux-foundation.org
Cc: ivtv-de...@ivtvdriver.org
Cc: linux-media@vger.kernel.org
---
drivers/media/video/ivtv/ivtv-driver.c | 26 --
drivers/media/video/ivtv/ivtv-driver.h |8
drivers/media/video/ivtv/ivtv-irq.c| 15 +++
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 1b79475..49e0b1c 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -695,6 +695,8 @@ done:
*/
static int __devinit ivtv_init_struct1(struct ivtv *itv)
{
+ struct sched_param param = { .sched_priority = 99 };
+
itv-base_addr = pci_resource_start(itv-pdev, 0);
itv-enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
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)
spin_lock_init(itv-lock);
spin_lock_init(itv-dma_reg_lock);
- itv-irq_work_queues =
create_singlethread_workqueue(itv-v4l2_dev.name);
- if (itv-irq_work_queues == NULL) {
- IVTV_ERR(Could not create ivtv workqueue\n);
+ init_kthread_worker(itv-irq_worker);
+ itv-irq_worker_task = kthread_run(kthread_worker_fn, itv-irq_worker,
+ itv-v4l2_dev.name);
+ if (IS_ERR(itv-irq_worker_task)) {
+ IVTV_ERR(Could not create ivtv task\n);
return -1;
}
+ /* must use the FIFO scheduler as it is realtime sensitive */
+ sched_setscheduler(itv-irq_worker_task, SCHED_FIFO, param);
- INIT_WORK(itv-irq_work_queue, ivtv_irq_work_handler);
+ init_kthread_work(itv-irq_work, ivtv_irq_work_handler);
/* start counting open_id at 1 */
itv-open_id = 1;
@@ -996,7 +1002,7 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
/* PCI Device Setup */
retval = ivtv_setup_pci(itv, pdev, pci_id);
if (retval == -EIO)
- goto free_workqueue;
+ goto free_worker;
if (retval == -ENXIO)
goto free_mem;
@@ -1208,8 +1214,8 @@ free_mem:
release_mem_region(itv-base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (itv-has_cx23415)
release_mem_region(itv-base_addr + IVTV_DECODER_OFFSET,
IVTV_DECODER_SIZE);
-free_workqueue:
- destroy_workqueue(itv-irq_work_queues);
+free_worker:
+ kthread_stop(itv-irq_worker_task);
err:
if (retval == 0)
retval = -ENODEV;
@@ -1353,9 +1359,9 @@ static void ivtv_remove(struct pci_dev *pdev)
ivtv_set_irq_mask(itv, 0x);
del_timer_sync(itv-dma_timer);
- /* Stop all Work Queues */
- flush_workqueue(itv-irq_work_queues);
- destroy_workqueue(itv-irq_work_queues);
+ /* Kill irq worker */
+ flush_kthread_worker(itv-irq_worker);
+ kthread_stop(itv-irq_worker_task);
ivtv_streams_cleanup(itv, 1);
ivtv_udma_free(itv);
diff --git a/drivers/media/video/ivtv/ivtv-driver.h
b/drivers/media/video/ivtv/ivtv-driver.h
index 5b45fd2..51f7f2a 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -51,7 +51,7 @@
#include linux/unistd.h
#include linux/pagemap.h
#include linux/scatterlist.h
-#include linux/workqueue.h
+#include linux/kthread.h
#include linux/mutex.h
#include linux/slab.h
#include asm/uaccess.h
@@ -257,7 +257,6 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */
#define IVTV_F_I_INITED 21 /* set after first open */
#define IVTV_F_I_FAILED 22 /* set if first open failed */
-#define IVTV_F_I_WORK_INITED 23 /* worker thread was initialized */
/* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
@@ -663,8 +662,9 @@ struct ivtv {
/* Interrupts DMA */
u32 irqmask;/* active interrupts */
u32 irq_rr_idx; /* round-robin stream index */
- struct workqueue_struct *irq_work_queues; /* workqueue for
PIO/YUV/VBI actions */
- struct work_struct irq_work_queue; /* work entry */
+ struct kthread_worker irq_worker; /* kthread worker for
PIO/YUV/VBI actions */
+ struct task_struct *irq_worker_task;/* task for irq_worker
*/
+ struct