mirror of
https://github.com/torvalds/linux
synced 2024-10-21 18:59:26 +00:00
media: fsl-viu: fix error handling in viu_of_probe()
viu_of_probe() ignores fails in i2c_get_adapter(), tries to unlock uninitialized mutex on error path. The patch streamlining the error handling in viu_of_probe(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
b8f8e559c7
commit
662a99e145
|
@ -1414,7 +1414,7 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
sizeof(struct viu_reg), DRV_NAME)) {
|
sizeof(struct viu_reg), DRV_NAME)) {
|
||||||
dev_err(&op->dev, "Error while requesting mem region\n");
|
dev_err(&op->dev, "Error while requesting mem region\n");
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto err;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remap registers */
|
/* remap registers */
|
||||||
|
@ -1422,7 +1422,7 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
if (!viu_regs) {
|
if (!viu_regs) {
|
||||||
dev_err(&op->dev, "Can't map register set\n");
|
dev_err(&op->dev, "Can't map register set\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare our private structure */
|
/* Prepare our private structure */
|
||||||
|
@ -1430,7 +1430,7 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
if (!viu_dev) {
|
if (!viu_dev) {
|
||||||
dev_err(&op->dev, "Can't allocate private structure\n");
|
dev_err(&op->dev, "Can't allocate private structure\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
viu_dev->vr = viu_regs;
|
viu_dev->vr = viu_regs;
|
||||||
|
@ -1446,16 +1446,21 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev);
|
ret = v4l2_device_register(viu_dev->dev, &viu_dev->v4l2_dev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&op->dev, "v4l2_device_register() failed: %d\n", ret);
|
dev_err(&op->dev, "v4l2_device_register() failed: %d\n", ret);
|
||||||
goto err;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
ad = i2c_get_adapter(0);
|
ad = i2c_get_adapter(0);
|
||||||
|
if (!ad) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
dev_err(&op->dev, "couldn't get i2c adapter\n");
|
||||||
|
goto err_v4l2;
|
||||||
|
}
|
||||||
|
|
||||||
v4l2_ctrl_handler_init(&viu_dev->hdl, 5);
|
v4l2_ctrl_handler_init(&viu_dev->hdl, 5);
|
||||||
if (viu_dev->hdl.error) {
|
if (viu_dev->hdl.error) {
|
||||||
ret = viu_dev->hdl.error;
|
ret = viu_dev->hdl.error;
|
||||||
dev_err(&op->dev, "couldn't register control\n");
|
dev_err(&op->dev, "couldn't register control\n");
|
||||||
goto err_vdev;
|
goto err_i2c;
|
||||||
}
|
}
|
||||||
/* This control handler will inherit the control(s) from the
|
/* This control handler will inherit the control(s) from the
|
||||||
sub-device(s). */
|
sub-device(s). */
|
||||||
|
@ -1471,7 +1476,7 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
vdev = video_device_alloc();
|
vdev = video_device_alloc();
|
||||||
if (vdev == NULL) {
|
if (vdev == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_vdev;
|
goto err_hdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*vdev = viu_template;
|
*vdev = viu_template;
|
||||||
|
@ -1492,7 +1497,7 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
ret = video_register_device(viu_dev->vdev, VFL_TYPE_GRABBER, -1);
|
ret = video_register_device(viu_dev->vdev, VFL_TYPE_GRABBER, -1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
video_device_release(viu_dev->vdev);
|
video_device_release(viu_dev->vdev);
|
||||||
goto err_vdev;
|
goto err_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable VIU clock */
|
/* enable VIU clock */
|
||||||
|
@ -1500,12 +1505,12 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
if (IS_ERR(clk)) {
|
if (IS_ERR(clk)) {
|
||||||
dev_err(&op->dev, "failed to lookup the clock!\n");
|
dev_err(&op->dev, "failed to lookup the clock!\n");
|
||||||
ret = PTR_ERR(clk);
|
ret = PTR_ERR(clk);
|
||||||
goto err_clk;
|
goto err_vdev;
|
||||||
}
|
}
|
||||||
ret = clk_prepare_enable(clk);
|
ret = clk_prepare_enable(clk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&op->dev, "failed to enable the clock!\n");
|
dev_err(&op->dev, "failed to enable the clock!\n");
|
||||||
goto err_clk;
|
goto err_vdev;
|
||||||
}
|
}
|
||||||
viu_dev->clk = clk;
|
viu_dev->clk = clk;
|
||||||
|
|
||||||
|
@ -1516,7 +1521,7 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
if (request_irq(viu_dev->irq, viu_intr, 0, "viu", (void *)viu_dev)) {
|
if (request_irq(viu_dev->irq, viu_intr, 0, "viu", (void *)viu_dev)) {
|
||||||
dev_err(&op->dev, "Request VIU IRQ failed.\n");
|
dev_err(&op->dev, "Request VIU IRQ failed.\n");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_irq;
|
goto err_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&viu_dev->lock);
|
mutex_unlock(&viu_dev->lock);
|
||||||
|
@ -1524,16 +1529,19 @@ static int viu_of_probe(struct platform_device *op)
|
||||||
dev_info(&op->dev, "Freescale VIU Video Capture Board\n");
|
dev_info(&op->dev, "Freescale VIU Video Capture Board\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_irq:
|
|
||||||
clk_disable_unprepare(viu_dev->clk);
|
|
||||||
err_clk:
|
err_clk:
|
||||||
video_unregister_device(viu_dev->vdev);
|
clk_disable_unprepare(viu_dev->clk);
|
||||||
err_vdev:
|
err_vdev:
|
||||||
v4l2_ctrl_handler_free(&viu_dev->hdl);
|
video_unregister_device(viu_dev->vdev);
|
||||||
|
err_unlock:
|
||||||
mutex_unlock(&viu_dev->lock);
|
mutex_unlock(&viu_dev->lock);
|
||||||
|
err_hdl:
|
||||||
|
v4l2_ctrl_handler_free(&viu_dev->hdl);
|
||||||
|
err_i2c:
|
||||||
i2c_put_adapter(ad);
|
i2c_put_adapter(ad);
|
||||||
|
err_v4l2:
|
||||||
v4l2_device_unregister(&viu_dev->v4l2_dev);
|
v4l2_device_unregister(&viu_dev->v4l2_dev);
|
||||||
err:
|
err_irq:
|
||||||
irq_dispose_mapping(viu_irq);
|
irq_dispose_mapping(viu_irq);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue