media: dvb: mpq: Limit number of TS packets on secure demux input

Limit number of TS packets available to secure demux for processing
in any single processing session. This is done in order to prevent
large input buffer that require a long processing time and may cause
latency and overflow situations.
The limit can be fine-tuned as it is a module parameter.

Change-Id: I36f007da1b8152be27885ba4674bf42e6eb86ffa
Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
index c687930..806f2ab 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.c
@@ -25,6 +25,8 @@
 
 #define MAX_PES_LENGTH	(SZ_64K)
 
+#define MAX_TS_PACKETS_FOR_SDMX_PROCESS	(500)
+
 /*
  * PES header length field is 8 bits so PES header length after this field
  * can be up to 256 bytes.
@@ -87,6 +89,11 @@
 static int mpq_bypass_sdmx = 1;
 module_param(mpq_bypass_sdmx, int, S_IRUGO | S_IWUSR);
 
+/* Max number of TS packets allowed as input for a single sdmx process */
+static int mpq_sdmx_proc_limit = MAX_TS_PACKETS_FOR_SDMX_PROCESS;
+module_param(mpq_sdmx_proc_limit, int, S_IRUGO | S_IWUSR);
+
+
 /**
  * Maximum allowed framing pattern size
  */
@@ -4303,7 +4310,7 @@
 	}
 }
 
-int mpq_sdmx_process(struct mpq_demux *mpq_demux,
+static int mpq_sdmx_process_buffer(struct mpq_demux *mpq_demux,
 	struct sdmx_buff_descr *input,
 	u32 fill_count,
 	u32 read_offset)
@@ -4399,6 +4406,41 @@
 
 	return bytes_read;
 }
+
+int mpq_sdmx_process(struct mpq_demux *mpq_demux,
+	struct sdmx_buff_descr *input,
+	u32 fill_count,
+	u32 read_offset)
+{
+	int ret;
+	int todo;
+	int total_bytes_read = 0;
+	int limit = mpq_sdmx_proc_limit * mpq_demux->demux.ts_packet_size;
+
+	do {
+		todo = fill_count > limit ? limit : fill_count;
+		ret = mpq_sdmx_process_buffer(mpq_demux, input, todo,
+			read_offset);
+		if (ret > 0) {
+			total_bytes_read += ret;
+			fill_count -= ret;
+			read_offset += ret;
+			if (read_offset >= input->size)
+				read_offset -= input->size;
+		} else if (ret == 0) {
+			/* Not enough data to read (less than 1 TS packet) */
+			break;
+		} else {
+			/* Some error occurred */
+			MPQ_DVB_ERR_PRINT(
+				"%s: mpq_sdmx_process_buffer failed, returned %d\n",
+				__func__, ret);
+			break;
+		}
+	} while (fill_count > 0);
+
+	return total_bytes_read;
+}
 EXPORT_SYMBOL(mpq_sdmx_process);
 
 static int mpq_sdmx_write(struct mpq_demux *mpq_demux,