From 87116159517ecf6b9cf62a136f2935a63833c485 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 13 Apr 2009 22:42:43 -0300 Subject: V4L/DVB (11616): cx18: Add a work queue for deferring empty buffer handoffs to the firmware This change defers sending all CX18_CPU_DE_SET_MDL commands, for a stream with an ongoing capture, by adding a work queue to handle sending such commands when needed. This prevents any sleeps, caused by notifying the firmware of new usable buffers, when a V4L2 application read() is being satisfied or when an incoming buffer is processed by the cx18-NN-in work queue thread. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'drivers/media/video/cx18/cx18-driver.h') diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index e6f42d0cb2b3..62dca432fdbb 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -254,6 +254,7 @@ struct cx18_options { #define CX18_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */ #define CX18_F_S_STREAMOFF 7 /* signal end of stream EOS */ #define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */ +#define CX18_F_S_STOPPING 9 /* telling the fw to stop capturing */ /* per-cx18, i_flags */ #define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */ @@ -324,6 +325,33 @@ struct cx18_in_work_order { char *str; }; +/* + * There are 2 types of deferrable tasks that send messages out to the firmware: + * 1. Sending individual buffers back to the firmware + * 2. Sending as many free buffers for a stream from q_free as we can to the fw + * + * The worst case scenario for multiple simultaneous streams is + * TS, YUV, PCM, VBI, MPEG, and IDX all going at once. + * + * We try to load the firmware queue with as many free buffers as possible, + * whenever we get a buffer back for a stream. For the TS we return the single + * buffer to the firmware at that time as well. For all other streams, we + * return single buffers to the firmware as the application drains them. + * + * 6 streams * 2 sets of orders * (1 single buf + 1 load fw from q_free) + * = 24 work orders should cover our needs, provided the applications read + * at a fairly steady rate. If apps don't, we fall back to non-deferred + * operation, when no cx18_out_work_orders are available for use. + */ +#define CX18_MAX_OUT_WORK_ORDERS (24) + +struct cx18_out_work_order { + struct work_struct work; + atomic_t pending; + struct cx18_stream *s; + struct cx18_buffer *buf; /* buf == NULL, means load fw from q_free */ +}; + #define CX18_INVALID_TASK_HANDLE 0xffffffff struct cx18_stream { @@ -573,6 +601,10 @@ struct cx18 { struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ + struct workqueue_struct *out_work_queue; + char out_workq_name[12]; /* "cx18-NN-out" */ + struct cx18_out_work_order out_work_order[CX18_MAX_OUT_WORK_ORDERS]; + /* i2c */ struct i2c_adapter i2c_adap[2]; struct i2c_algo_bit_data i2c_algo[2]; -- cgit v1.2.3