V4L/DVB (9592): cx18: Use default kernel work queue; fix streaming flag for work handler

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>
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index d7879fb..6799eab 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -449,12 +449,6 @@
 
 	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_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 @@
 
 	cx18_halt_firmware(cx);
 
-	flush_workqueue(cx->work_queue);
-	destroy_workqueue(cx->work_queue);
+	flush_scheduled_work();
 
 	cx18_streams_cleanup(cx, 1);
 
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index fe9e5bb..04f1c62 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -207,7 +207,6 @@
 #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 @@
 	/* 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 */
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index 4542e2e..4845f73 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -109,20 +109,23 @@
 	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 @@
 			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,
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
index 5fbfbd0..33f56c6 100644
--- a/drivers/media/video/cx18/cx18-irq.c
+++ b/drivers/media/video/cx18/cx18-irq.c
@@ -34,12 +34,6 @@
 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 @@
 		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;
 }
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index e5ff770..c7d431f 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -560,9 +560,6 @@
 		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 @@
 	/* 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;