diff mbox

video_device: don't free_irq() an element past array vpif_obj.dev[] and fix test

Message ID 4B7EE81C.4020701@gmail.com (mailing list archive)
State Superseded
Headers show

Commit Message

Roel Kluin Feb. 19, 2010, 7:35 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
index dfddef7..ae8ca94 100644
--- a/drivers/media/video/davinci/vpif_display.c
+++ b/drivers/media/video/davinci/vpif_display.c
@@ -383,7 +383,7 @@  static int vpif_get_std_info(struct channel_obj *ch)
 	int index;
 
 	std_info->stdid = vid_ch->stdid;
-	if (!std_info)
+	if (!std_info->stdid)
 		return -1;
 
 	for (index = 0; index < ARRAY_SIZE(ch_params); index++) {
@@ -1423,7 +1423,7 @@  static __init int vpif_probe(struct platform_device *pdev)
 {
 	struct vpif_subdev_info *subdevdata;
 	struct vpif_display_config *config;
-	int i, j = 0, k, q, m, err = 0;
+	int i, j, k, err;
 	struct i2c_adapter *i2c_adap;
 	struct common_obj *common;
 	struct channel_obj *ch;
@@ -1452,12 +1452,18 @@  static __init int vpif_probe(struct platform_device *pdev)
 			if (request_irq(i, vpif_channel_isr, IRQF_DISABLED,
 					"DM646x_Display",
 				(void *)(&vpif_obj.dev[k]->channel_id))) {
+				i--;
 				err = -EBUSY;
+				vpif_err("VPIF IRQ request failed\n");
 				goto vpif_int_err;
 			}
 		}
 		k++;
+		if (k >= VPIF_DISPLAY_MAX_DEVICES)
+			break;
 	}
+	if (k == 0)
+		return -ENODEV;
 
 	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
 
@@ -1472,7 +1478,7 @@  static __init int vpif_probe(struct platform_device *pdev)
 				video_device_release(ch->video_dev);
 			}
 			err = -ENOMEM;
-			goto vpif_int_err;
+			goto alloc_vid_fail;
 		}
 
 		/* Initialize field of video device */
@@ -1489,13 +1495,13 @@  static __init int vpif_probe(struct platform_device *pdev)
 		ch->video_dev = vfd;
 	}
 
-	for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
-		ch = vpif_obj.dev[j];
+	for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
+		ch = vpif_obj.dev[i];
 		/* Initialize field of the channel objects */
 		atomic_set(&ch->usrs, 0);
-		for (k = 0; k < VPIF_NUMOBJECTS; k++) {
-			ch->common[k].numbuffers = 0;
-			common = &ch->common[k];
+		for (j = 0; j < VPIF_NUMOBJECTS; j++) {
+			ch->common[j].numbuffers = 0;
+			common = &ch->common[j];
 			common->io_usrs = 0;
 			common->started = 0;
 			spin_lock_init(&common->irqlock);
@@ -1506,12 +1512,12 @@  static __init int vpif_probe(struct platform_device *pdev)
 			common->ctop_off = common->cbtm_off = 0;
 			common->cur_frm = common->next_frm = NULL;
 			memset(&common->fmt, 0, sizeof(common->fmt));
-			common->numbuffers = config_params.numbuffers[k];
+			common->numbuffers = config_params.numbuffers[j];
 
 		}
 		ch->initialized = 0;
-		ch->channel_id = j;
-		if (j < 2)
+		ch->channel_id = i;
+		if (i < 2)
 			ch->common[VPIF_VIDEO_INDEX].numbuffers =
 			    config_params.numbuffers[ch->channel_id];
 		else
@@ -1529,7 +1535,7 @@  static __init int vpif_probe(struct platform_device *pdev)
 				(int)ch, (int)&ch->video_dev);
 
 		err = video_register_device(ch->video_dev,
-					  VFL_TYPE_GRABBER, (j ? 3 : 2));
+					  VFL_TYPE_GRABBER, (i ? 3 : 2));
 		if (err < 0)
 			goto probe_out;
 
@@ -1567,20 +1573,35 @@  static __init int vpif_probe(struct platform_device *pdev)
 probe_subdev_out:
 	kfree(vpif_obj.sd);
 probe_out:
-	for (k = 0; k < j; k++) {
-		ch = vpif_obj.dev[k];
+	for (j = 0; j < i; j++) {
+		ch = vpif_obj.dev[j];
 		video_unregister_device(ch->video_dev);
 		video_device_release(ch->video_dev);
 		ch->video_dev = NULL;
 	}
+alloc_vid_fail:
+	while (k--) {
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+		if (res != NULL)
+			break;
+		vpif_err("Couldn't get resource %d, irqs not freed.\n", k);
+	}
+	if (res == NULL) {
+		vpif_err("Couldn't get any resource.\n");
+		return err;
+	}
+
+	i = res->end;
 vpif_int_err:
 	v4l2_device_unregister(&vpif_obj.v4l2_dev);
-	vpif_err("VPIF IRQ request failed\n");
-	for (q = k; k >= 0; k--) {
-		for (m = i; m >= res->start; m--)
-			free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id));
-		res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1);
-		m = res->end;
+
+	for (j = i; j >= res->start; j--)
+		free_irq(j, (void *)(&vpif_obj.dev[k]->channel_id));
+
+	while (k--) {
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+		for (j =  res->end; j >= res->start; j--)
+			free_irq(j, (void *)(&vpif_obj.dev[k]->channel_id));
 	}
 
 	return err;