Commit 7bc46560 authored by Tejun Heo's avatar Tejun Heo

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: default avatarTejun 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
parent b56c0d89
...@@ -695,6 +695,8 @@ static void ivtv_process_options(struct ivtv *itv) ...@@ -695,6 +695,8 @@ static void ivtv_process_options(struct ivtv *itv)
*/ */
static int __devinit ivtv_init_struct1(struct ivtv *itv) 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->base_addr = pci_resource_start(itv->pdev, 0);
itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ 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) */ 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,13 +708,17 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
spin_lock_init(&itv->lock); spin_lock_init(&itv->lock);
spin_lock_init(&itv->dma_reg_lock); spin_lock_init(&itv->dma_reg_lock);
itv->irq_work_queues = create_singlethread_workqueue(itv->v4l2_dev.name); init_kthread_worker(&itv->irq_worker);
if (itv->irq_work_queues == NULL) { itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker,
IVTV_ERR("Could not create ivtv workqueue\n"); itv->v4l2_dev.name);
if (IS_ERR(itv->irq_worker_task)) {
IVTV_ERR("Could not create ivtv task\n");
return -1; 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 */ /* start counting open_id at 1 */
itv->open_id = 1; itv->open_id = 1;
...@@ -996,7 +1002,7 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, ...@@ -996,7 +1002,7 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
/* PCI Device Setup */ /* PCI Device Setup */
retval = ivtv_setup_pci(itv, pdev, pci_id); retval = ivtv_setup_pci(itv, pdev, pci_id);
if (retval == -EIO) if (retval == -EIO)
goto free_workqueue; goto free_worker;
if (retval == -ENXIO) if (retval == -ENXIO)
goto free_mem; goto free_mem;
...@@ -1208,8 +1214,8 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, ...@@ -1208,8 +1214,8 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (itv->has_cx23415) if (itv->has_cx23415)
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
free_workqueue: free_worker:
destroy_workqueue(itv->irq_work_queues); kthread_stop(itv->irq_worker_task);
err: err:
if (retval == 0) if (retval == 0)
retval = -ENODEV; retval = -ENODEV;
...@@ -1353,9 +1359,9 @@ static void ivtv_remove(struct pci_dev *pdev) ...@@ -1353,9 +1359,9 @@ static void ivtv_remove(struct pci_dev *pdev)
ivtv_set_irq_mask(itv, 0xffffffff); ivtv_set_irq_mask(itv, 0xffffffff);
del_timer_sync(&itv->dma_timer); del_timer_sync(&itv->dma_timer);
/* Stop all Work Queues */ /* Kill irq worker */
flush_workqueue(itv->irq_work_queues); flush_kthread_worker(&itv->irq_worker);
destroy_workqueue(itv->irq_work_queues); kthread_stop(itv->irq_worker_task);
ivtv_streams_cleanup(itv, 1); ivtv_streams_cleanup(itv, 1);
ivtv_udma_free(itv); ivtv_udma_free(itv);
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/workqueue.h> #include <linux/kthread.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -257,7 +257,6 @@ struct ivtv_mailbox_data { ...@@ -257,7 +257,6 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ #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_INITED 21 /* set after first open */
#define IVTV_F_I_FAILED 22 /* set if first open failed */ #define IVTV_F_I_FAILED 22 /* set if first open failed */
#define IVTV_F_I_WORK_INITED 23 /* worker thread was initialized */
/* Event notifications */ /* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
...@@ -663,8 +662,9 @@ struct ivtv { ...@@ -663,8 +662,9 @@ struct ivtv {
/* Interrupts & DMA */ /* Interrupts & DMA */
u32 irqmask; /* active interrupts */ u32 irqmask; /* active interrupts */
u32 irq_rr_idx; /* round-robin stream index */ u32 irq_rr_idx; /* round-robin stream index */
struct workqueue_struct *irq_work_queues; /* workqueue for PIO/YUV/VBI actions */ struct kthread_worker irq_worker; /* kthread worker for PIO/YUV/VBI actions */
struct work_struct irq_work_queue; /* work entry */ struct task_struct *irq_worker_task; /* task for irq_worker */
struct kthread_work irq_work; /* kthread work entry */
spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
int cur_dma_stream; /* index of current stream doing DMA (-1 if none) */ int cur_dma_stream; /* index of current stream doing DMA (-1 if none) */
int cur_pio_stream; /* index of current stream doing PIO (-1 if none) */ int cur_pio_stream; /* index of current stream doing PIO (-1 if none) */
......
...@@ -71,19 +71,10 @@ static void ivtv_pio_work_handler(struct ivtv *itv) ...@@ -71,19 +71,10 @@ static void ivtv_pio_work_handler(struct ivtv *itv)
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
} }
void ivtv_irq_work_handler(struct work_struct *work) void ivtv_irq_work_handler(struct kthread_work *work)
{ {
struct ivtv *itv = container_of(work, struct ivtv, irq_work_queue); struct ivtv *itv = container_of(work, struct ivtv, irq_work);
DEFINE_WAIT(wait);
if (test_and_clear_bit(IVTV_F_I_WORK_INITED, &itv->i_flags)) {
struct sched_param param = { .sched_priority = 99 };
/* This thread must use the FIFO scheduler as it
is realtime sensitive. */
sched_setscheduler(current, SCHED_FIFO, &param);
}
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags)) if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
ivtv_pio_work_handler(itv); ivtv_pio_work_handler(itv);
...@@ -975,7 +966,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) ...@@ -975,7 +966,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
} }
if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) { if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) {
queue_work(itv->irq_work_queues, &itv->irq_work_queue); queue_kthread_work(&itv->irq_worker, &itv->irq_work);
} }
spin_unlock(&itv->dma_reg_lock); spin_unlock(&itv->dma_reg_lock);
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
irqreturn_t ivtv_irq_handler(int irq, void *dev_id); irqreturn_t ivtv_irq_handler(int irq, void *dev_id);
void ivtv_irq_work_handler(struct work_struct *work); void ivtv_irq_work_handler(struct kthread_work *work);
void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock);
void ivtv_unfinished_dma(unsigned long arg); void ivtv_unfinished_dma(unsigned long arg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment