diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-09-20 09:06:29 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-05 22:06:05 -0300 |
commit | 5be452c343331dadf237bed0053fdc7d623e8049 (patch) | |
tree | 01bae823e42146340875112e31c7d02120ab63e1 /drivers/media | |
parent | 01b1d975597dd051515fe90e5b0b09cc700e6aa0 (diff) |
[media] vpif_capture: fix cleanup code
The cleanup sequence was incorrect and could cause a kernel oops.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Lad, Prabhakar <prabhakar.lad@ti.com>
Tested-by: Lad, Prabhakar <prabhakar.lad@ti.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/platform/davinci/vpif_capture.c | 44 |
1 files changed, 22 insertions, 22 deletions
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 00fdb177d2fc..bcd2a78d3850 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -2060,7 +2060,8 @@ static __init int vpif_probe(struct platform_device *pdev) { struct vpif_subdev_info *subdevdata; struct vpif_capture_config *config; - int i, j, k, m, q, err; + int i, j, k, err; + int res_idx = 0; struct i2c_adapter *i2c_adap; struct channel_obj *ch; struct common_obj *common; @@ -2083,18 +2084,19 @@ static __init int vpif_probe(struct platform_device *pdev) return err; } - k = 0; - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { + while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { for (i = res->start; i <= res->end; i++) { if (request_irq(i, vpif_channel_isr, IRQF_SHARED, - "VPIF_Capture", - (void *)(&vpif_obj.dev[k]->channel_id))) { + "VPIF_Capture", (void *) + (&vpif_obj.dev[res_idx]->channel_id))) { err = -EBUSY; - i--; + for (j = 0; j < i; j++) + free_irq(j, (void *) + (&vpif_obj.dev[res_idx]->channel_id)); goto vpif_int_err; } } - k++; + res_idx++; } for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { @@ -2108,7 +2110,7 @@ static __init int vpif_probe(struct platform_device *pdev) video_device_release(ch->video_dev); } err = -ENOMEM; - goto vpif_dev_alloc_err; + goto vpif_int_err; } /* Initialize field of video device */ @@ -2148,7 +2150,7 @@ static __init int vpif_probe(struct platform_device *pdev) if (vpif_obj.sd == NULL) { vpif_err("unable to allocate memory for subdevice pointers\n"); err = -ENOMEM; - goto vpif_dev_alloc_err; + goto vpif_sd_error; } for (i = 0; i < subdev_count; i++) { @@ -2197,21 +2199,19 @@ probe_subdev_out: /* free sub devices memory */ kfree(vpif_obj.sd); -vpif_dev_alloc_err: - k = VPIF_CAPTURE_MAX_DEVICES-1; - res = platform_get_resource(pdev, IORESOURCE_IRQ, k); - i = res->end; - -vpif_int_err: - for (q = k; q >= 0; q--) { - for (m = i; m >= (int)res->start; m--) - free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id)); - - res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1); - if (res) - i = res->end; +vpif_sd_error: + for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { + ch = vpif_obj.dev[i]; + /* Note: does nothing if ch->video_dev == NULL */ + video_device_release(ch->video_dev); } +vpif_int_err: v4l2_device_unregister(&vpif_obj.v4l2_dev); + for (i = 0; i < res_idx; i++) { + res = platform_get_resource(pdev, IORESOURCE_IRQ, i); + for (j = res->start; j <= res->end; j++) + free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); + } return err; } |