V4L/DVB (9592): cx18: Use default kernel work queue; fix streaming flag for work...
authorAndy Walls <awalls@radix.net>
Thu, 6 Nov 2008 00:19:15 +0000 (21:19 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 30 Dec 2008 11:38:01 +0000 (09:38 -0200)
cx18: Use default kernel work queue; fix streaming flag for work handler.
Eliminate cx18 specific work queue and use the kernel default work queue.
Fixed the F_STREAMING_FLAG for the TS stream so cx18_dvb_work_handler()
can know when it is not safe to send MDLs to the firmware.

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-dvb.c
drivers/media/video/cx18/cx18-irq.c
drivers/media/video/cx18/cx18-streams.c

index d7879fb1d21f56d1fcecc4fccaf4788637a83a60..6799eab8b6ac6655e9c43ef95ad1546867b9b8dc 100644 (file)
@@ -449,12 +449,6 @@ 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("Could not create work queue\n");
-               return -1;
-       }
-
        INIT_WORK(&cx->work, cx18_work_handler);
 
        /* start counting open_id at 1 */
@@ -837,7 +831,6 @@ 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,8 +931,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
 
        cx18_halt_firmware(cx);
 
-       flush_workqueue(cx->work_queue);
-       destroy_workqueue(cx->work_queue);
+       flush_scheduled_work();
 
        cx18_streams_cleanup(cx, 1);
 
index fe9e5bb979e074b4f6d3512f6c5b2c86cf2f09aa..04f1c624da7c7864459c7dca9764cfbdc92a0eb6 100644 (file)
@@ -207,7 +207,6 @@ struct cx18_options {
 #define CX18_F_I_WORK_HANDLER_DVB      18      /* work to be done for DVB */
 #define CX18_F_I_INITED                        21      /* set after first open */
 #define CX18_F_I_FAILED                        22      /* set if first open failed */
-#define CX18_F_I_WORK_INITED           23      /* worker thread initialized */
 
 /* These are the VBI types as they appear in the embedded VBI private packets. */
 #define CX18_SLICED_TYPE_TELETEXT_B     (1)
@@ -435,7 +434,6 @@ struct cx18 {
        /* when the current DMA is finished this queue is woken up */
        wait_queue_head_t dma_waitq;
 
-       struct workqueue_struct *work_queue;
        struct work_struct work;
 
        /* i2c */
index 4542e2e5e3d76323668ee9b1f3b5132dfeaf090c..4845f732ef486a12cd249506f754e4af594eaa27 100644 (file)
@@ -109,20 +109,23 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
        if (!demux->dmx.frontend)
                return -EINVAL;
 
-       if (stream) {
-               mutex_lock(&stream->dvb.feedlock);
-               if (stream->dvb.feeding++ == 0) {
-                       CX18_DEBUG_INFO("Starting Transport DMA\n");
-                       ret = cx18_start_v4l2_encode_stream(stream);
-                       if (ret < 0) {
-                               CX18_DEBUG_INFO(
-                                       "Failed to start Transport DMA\n");
-                               stream->dvb.feeding--;
-                       }
-               } else
-                       ret = 0;
-               mutex_unlock(&stream->dvb.feedlock);
-       }
+       if (!stream)
+               return -EINVAL;
+
+       mutex_lock(&stream->dvb.feedlock);
+       if (stream->dvb.feeding++ == 0) {
+               CX18_DEBUG_INFO("Starting Transport DMA\n");
+               set_bit(CX18_F_S_STREAMING, &stream->s_flags);
+               ret = cx18_start_v4l2_encode_stream(stream);
+               if (ret < 0) {
+                       CX18_DEBUG_INFO("Failed to start Transport DMA\n");
+                       stream->dvb.feeding--;
+                       if (stream->dvb.feeding == 0)
+                               clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
+               }
+       } else
+               ret = 0;
+       mutex_unlock(&stream->dvb.feedlock);
 
        return ret;
 }
@@ -313,9 +316,11 @@ void cx18_dvb_work_handler(struct cx18 *cx)
                        dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
                                         buf->bytesused);
 
-               cx18_enqueue(s, buf, &s->q_free);
                cx18_buf_sync_for_device(s, buf);
-               if (s->handle == CX18_INVALID_TASK_HANDLE) /* FIXME: improve */
+               cx18_enqueue(s, buf, &s->q_free);
+
+               if (s->handle == CX18_INVALID_TASK_HANDLE ||
+                   !test_bit(CX18_F_S_STREAMING, &s->s_flags))
                        continue;
 
                cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
index 5fbfbd0f14935eff36a19d27c8d852d8df2af483..33f56c61ca74cf01fb8cba9a8ac8b86f55311458 100644 (file)
 void cx18_work_handler(struct work_struct *work)
 {
        struct cx18 *cx = container_of(work, struct cx18, work);
-       if (test_and_clear_bit(CX18_F_I_WORK_INITED, &cx->i_flags)) {
-               struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
-               /* This thread must use the FIFO scheduler as it
-                * is realtime sensitive. */
-               sched_setscheduler(current, SCHED_FIFO, &param);
-       }
        if (test_and_clear_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags))
                cx18_dvb_work_handler(cx);
 }
@@ -194,7 +188,7 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
                epu_cmd(cx, sw1);
 
        if (test_and_clear_bit(CX18_F_I_HAVE_WORK, &cx->i_flags))
-               queue_work(cx->work_queue, &cx->work);
+               schedule_work(&cx->work);
 
        return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
 }
index e5ff7705b7a134c8495566b264c1621b65071f32..c7d431f4923804ff1144ff79fef4b40d7ebdf48d 100644 (file)
@@ -560,9 +560,6 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
                CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
        }
 
-       /* Tell the CX23418 it can't use our buffers anymore */
-       cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
-
        if (s->type != CX18_ENC_STREAM_TYPE_TS)
                atomic_dec(&cx->ana_capturing);
        atomic_dec(&cx->tot_capturing);
@@ -570,6 +567,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
        /* Clear capture and no-read bits */
        clear_bit(CX18_F_S_STREAMING, &s->s_flags);
 
+       /* Tell the CX23418 it can't use our buffers anymore */
+       cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+
        cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
        s->handle = CX18_INVALID_TASK_HANDLE;