davinci: edma: provide ability to detect insufficient CC info data

This patch modifies the EDMA driver to expect the channel
controller (CC) infomation passed on by the platform as a fixed
size (EDMA_MAX_CC) array of pointers to structures.

Doing so helps catch errors of the sort where the resource
structure has information for more channel controllers than
the number channel controller info structures defined.

Such insufficient platform data would lead to illegal memory
accesses.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 8cda729..1d956bf 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -111,19 +111,21 @@
 	{-1, -1}
 };
 
-static struct edma_soc_info da830_edma_info[] = {
-	{
-		.n_channel		= 32,
-		.n_region		= 4,
-		.n_slot			= 128,
-		.n_tc			= 2,
-		.n_cc			= 1,
-		.queue_tc_mapping	= da8xx_queue_tc_mapping,
-		.queue_priority_mapping	= da8xx_queue_priority_mapping,
-	},
+static struct edma_soc_info da830_edma_cc0_info = {
+	.n_channel		= 32,
+	.n_region		= 4,
+	.n_slot			= 128,
+	.n_tc			= 2,
+	.n_cc			= 1,
+	.queue_tc_mapping	= da8xx_queue_tc_mapping,
+	.queue_priority_mapping	= da8xx_queue_priority_mapping,
 };
 
-static struct edma_soc_info da850_edma_info[] = {
+static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {
+	&da830_edma_cc0_info,
+};
+
+static struct edma_soc_info da850_edma_cc_info[] = {
 	{
 		.n_channel		= 32,
 		.n_region		= 4,
@@ -144,6 +146,11 @@
 	},
 };
 
+static struct edma_soc_info *da850_edma_info[EDMA_MAX_CC] = {
+	&da850_edma_cc_info[0],
+	&da850_edma_cc_info[1],
+};
+
 static struct resource da830_edma_resources[] = {
 	{
 		.name	= "edma_cc0",
diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 4eef6cc..2718a3a 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -69,16 +69,18 @@
 	{	-1,		-1	}
 };
 
-static struct edma_soc_info edma_info[] = {
-	{
-		.n_channel		= EDMA_TNETV107X_NUM_DMACH,
-		.n_region		= EDMA_TNETV107X_NUM_REGIONS,
-		.n_slot			= EDMA_TNETV107X_NUM_PARAMENTRY,
-		.n_tc			= EDMA_TNETV107X_NUM_TC,
-		.n_cc			= 1,
-		.queue_tc_mapping	= edma_tc_mapping,
-		.queue_priority_mapping	= edma_priority_mapping,
-	},
+static struct edma_soc_info edma_cc0_info = {
+	.n_channel		= EDMA_TNETV107X_NUM_DMACH,
+	.n_region		= EDMA_TNETV107X_NUM_REGIONS,
+	.n_slot			= EDMA_TNETV107X_NUM_PARAMENTRY,
+	.n_tc			= EDMA_TNETV107X_NUM_TC,
+	.n_cc			= 1,
+	.queue_tc_mapping	= edma_tc_mapping,
+	.queue_priority_mapping	= edma_priority_mapping,
+};
+
+static struct edma_soc_info *tnetv107x_edma_info[EDMA_MAX_CC] = {
+	&edma_cc0_info,
 };
 
 static struct resource edma_resources[] = {
@@ -117,7 +119,7 @@
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(edma_resources),
 	.resource	= edma_resources,
-	.dev.platform_data = edma_info,
+	.dev.platform_data = tnetv107x_edma_info,
 };
 
 static struct plat_serial8250_port serial_data[] = {
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 3834781..3d996b6 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -591,16 +591,18 @@
 	{-1, -1},
 };
 
-static struct edma_soc_info dm355_edma_info[] = {
-	{
-		.n_channel		= 64,
-		.n_region		= 4,
-		.n_slot			= 128,
-		.n_tc			= 2,
-		.n_cc			= 1,
-		.queue_tc_mapping	= queue_tc_mapping,
-		.queue_priority_mapping	= queue_priority_mapping,
-	},
+static struct edma_soc_info edma_cc0_info = {
+	.n_channel		= 64,
+	.n_region		= 4,
+	.n_slot			= 128,
+	.n_tc			= 2,
+	.n_cc			= 1,
+	.queue_tc_mapping	= queue_tc_mapping,
+	.queue_priority_mapping	= queue_priority_mapping,
+};
+
+static struct edma_soc_info *dm355_edma_info[EDMA_MAX_CC] = {
+       &edma_cc0_info,
 };
 
 static struct resource edma_resources[] = {
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 652f4b6..6b6f4c6 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -822,17 +822,19 @@
 	{-1, -1},
 };
 
-static struct edma_soc_info dm365_edma_info[] = {
-	{
-		.n_channel		= 64,
-		.n_region		= 4,
-		.n_slot			= 256,
-		.n_tc			= 4,
-		.n_cc			= 1,
-		.queue_tc_mapping	= dm365_queue_tc_mapping,
-		.queue_priority_mapping	= dm365_queue_priority_mapping,
-		.default_queue		= EVENTQ_3,
-	},
+static struct edma_soc_info edma_cc0_info = {
+	.n_channel		= 64,
+	.n_region		= 4,
+	.n_slot			= 256,
+	.n_tc			= 4,
+	.n_cc			= 1,
+	.queue_tc_mapping	= dm365_queue_tc_mapping,
+	.queue_priority_mapping	= dm365_queue_priority_mapping,
+	.default_queue		= EVENTQ_3,
+};
+
+static struct edma_soc_info *dm365_edma_info[EDMA_MAX_CC] = {
+	&edma_cc0_info,
 };
 
 static struct resource edma_resources[] = {
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 7ad1520..40fec31 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -492,16 +492,18 @@
 	{-1, -1},
 };
 
-static struct edma_soc_info dm644x_edma_info[] = {
-	{
-		.n_channel		= 64,
-		.n_region		= 4,
-		.n_slot			= 128,
-		.n_tc			= 2,
-		.n_cc			= 1,
-		.queue_tc_mapping	= queue_tc_mapping,
-		.queue_priority_mapping	= queue_priority_mapping,
-	},
+static struct edma_soc_info edma_cc0_info = {
+	.n_channel		= 64,
+	.n_region		= 4,
+	.n_slot			= 128,
+	.n_tc			= 2,
+	.n_cc			= 1,
+	.queue_tc_mapping	= queue_tc_mapping,
+	.queue_priority_mapping	= queue_priority_mapping,
+};
+
+static struct edma_soc_info *dm644x_edma_info[EDMA_MAX_CC] = {
+	&edma_cc0_info,
 };
 
 static struct resource edma_resources[] = {
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 9404565..bfc887e 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -529,16 +529,18 @@
 	{-1, -1},
 };
 
-static struct edma_soc_info dm646x_edma_info[] = {
-	{
-		.n_channel		= 64,
-		.n_region		= 6,	/* 0-1, 4-7 */
-		.n_slot			= 512,
-		.n_tc			= 4,
-		.n_cc			= 1,
-		.queue_tc_mapping	= dm646x_queue_tc_mapping,
-		.queue_priority_mapping	= dm646x_queue_priority_mapping,
-	},
+static struct edma_soc_info edma_cc0_info = {
+	.n_channel		= 64,
+	.n_region		= 6,	/* 0-1, 4-7 */
+	.n_slot			= 512,
+	.n_tc			= 4,
+	.n_cc			= 1,
+	.queue_tc_mapping	= dm646x_queue_tc_mapping,
+	.queue_priority_mapping	= dm646x_queue_priority_mapping,
+};
+
+static struct edma_soc_info *dm646x_edma_info[EDMA_MAX_CC] = {
+	&edma_cc0_info,
 };
 
 static struct resource edma_resources[] = {
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index d33827a..0b6c01f 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -99,8 +99,6 @@
 
 #define EDMA_MAX_DMACH           64
 #define EDMA_MAX_PARAMENTRY     512
-#define EDMA_MAX_CC               2
-
 
 /*****************************************************************************/
 
@@ -1376,7 +1374,7 @@
 
 static int __init edma_probe(struct platform_device *pdev)
 {
-	struct edma_soc_info	*info = pdev->dev.platform_data;
+	struct edma_soc_info	**info = pdev->dev.platform_data;
 	const s8		(*queue_priority_mapping)[2];
 	const s8		(*queue_tc_mapping)[2];
 	int			i, j, found = 0;
@@ -1395,7 +1393,7 @@
 		sprintf(res_name, "edma_cc%d", j);
 		r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						res_name);
-		if (!r[j]) {
+		if (!r[j] || !info[j]) {
 			if (found)
 				break;
 			else
@@ -1426,13 +1424,14 @@
 		}
 		memset(edma_cc[j], 0, sizeof(struct edma));
 
-		edma_cc[j]->num_channels = min_t(unsigned, info[j].n_channel,
+		edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
 							EDMA_MAX_DMACH);
-		edma_cc[j]->num_slots = min_t(unsigned, info[j].n_slot,
+		edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
 							EDMA_MAX_PARAMENTRY);
-		edma_cc[j]->num_cc = min_t(unsigned, info[j].n_cc, EDMA_MAX_CC);
+		edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
+							EDMA_MAX_CC);
 
-		edma_cc[j]->default_queue = info[j].default_queue;
+		edma_cc[j]->default_queue = info[j]->default_queue;
 		if (!edma_cc[j]->default_queue)
 			edma_cc[j]->default_queue = EVENTQ_1;
 
@@ -1476,8 +1475,8 @@
 		for (i = 0; i < edma_cc[j]->num_channels; i++)
 			map_dmach_queue(j, i, EVENTQ_1);
 
-		queue_tc_mapping = info[j].queue_tc_mapping;
-		queue_priority_mapping = info[j].queue_priority_mapping;
+		queue_tc_mapping = info[j]->queue_tc_mapping;
+		queue_priority_mapping = info[j]->queue_priority_mapping;
 
 		/* Event queue to TC mapping */
 		for (i = 0; queue_tc_mapping[i][0] != -1; i++)
@@ -1496,7 +1495,7 @@
 		if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
 			map_dmach_param(j);
 
-		for (i = 0; i < info[j].n_region; i++) {
+		for (i = 0; i < info[j]->n_region; i++) {
 			edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
 			edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
 			edma_write_array(j, EDMA_QRAE, i, 0x0);
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
index ced3092..9a3bcc6 100644
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -230,6 +230,8 @@
 #define EDMA_CONT_PARAMS_FIXED_EXACT	 1002
 #define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
 
+#define EDMA_MAX_CC               2
+
 /* alloc/free DMA channels and their dedicated parameter RAM slots */
 int edma_alloc_channel(int channel,
 	void (*callback)(unsigned channel, u16 ch_status, void *data),