Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b6390bd authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab
Browse files

[media] omap3isp: Fix memory leaks in initialization error paths



Make sure all modules init functions clean up after themselves in case
of error.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reported-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ed33ac8e
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -2224,15 +2224,21 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)

	ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
	if (ret < 0)
		return ret;
		goto error_video;

	/* Connect the CCDC subdev to the video node. */
	ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
			&ccdc->video_out.video.entity, 0, 0);
	if (ret < 0)
		return ret;
		goto error_link;

	return 0;

error_link:
	omap3isp_video_cleanup(&ccdc->video_out);
error_video:
	media_entity_cleanup(me);
	return ret;
}

/*
@@ -2246,6 +2252,7 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
int omap3isp_ccdc_init(struct isp_device *isp)
{
	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
	int ret;

	spin_lock_init(&ccdc->lock);
	init_waitqueue_head(&ccdc->wait);
@@ -2274,7 +2281,13 @@ int omap3isp_ccdc_init(struct isp_device *isp)
	ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
	ccdc_apply_controls(ccdc);

	return ccdc_init_entities(ccdc);
	ret = ccdc_init_entities(ccdc);
	if (ret < 0) {
		mutex_destroy(&ccdc->ioctl_lock);
		return ret;
	}

	return 0;
}

/*
+13 −9
Original line number Diff line number Diff line
@@ -1125,15 +1125,21 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2)

	ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
	if (ret < 0)
		return ret;
		goto error_video;

	/* Connect the video node to the ccp2 subdev. */
	ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
				       &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
	if (ret < 0)
		return ret;
		goto error_link;

	return 0;

error_link:
	omap3isp_video_cleanup(&ccp2->video_in);
error_video:
	media_entity_cleanup(&ccp2->subdev.entity);
	return ret;
}

/*
@@ -1171,15 +1177,13 @@ int omap3isp_ccp2_init(struct isp_device *isp)
	}

	ret = ccp2_init_entities(ccp2);
	if (ret < 0)
		goto out;
	if (ret < 0) {
		regulator_put(ccp2->vdds_csib);
		return ret;
	}

	ccp2_reset(ccp2);
out:
	if (ret)
		omap3isp_ccp2_cleanup(isp);

	return ret;
	return 0;
}

/*
+9 −6
Original line number Diff line number Diff line
@@ -1259,15 +1259,21 @@ static int csi2_init_entities(struct isp_csi2_device *csi2)

	ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
	if (ret < 0)
		return ret;
		goto error_video;

	/* Connect the CSI2 subdev to the video node. */
	ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
				       &csi2->video_out.video.entity, 0, 0);
	if (ret < 0)
		return ret;
		goto error_link;

	return 0;

error_link:
	omap3isp_video_cleanup(&csi2->video_out);
error_video:
	media_entity_cleanup(&csi2->subdev.entity);
	return ret;
}

/*
@@ -1289,7 +1295,7 @@ int omap3isp_csi2_init(struct isp_device *isp)

	ret = csi2_init_entities(csi2a);
	if (ret < 0)
		goto fail;
		return ret;

	if (isp->revision == ISP_REVISION_15_0) {
		csi2c->isp = isp;
@@ -1302,9 +1308,6 @@ int omap3isp_csi2_init(struct isp_device *isp)
	}

	return 0;
fail:
	omap3isp_csi2_cleanup(isp);
	return ret;
}

/*
+13 −14
Original line number Diff line number Diff line
@@ -2060,24 +2060,32 @@ static int preview_init_entities(struct isp_prev_device *prev)

	ret = omap3isp_video_init(&prev->video_in, "preview");
	if (ret < 0)
		return ret;
		goto error_video_in;

	ret = omap3isp_video_init(&prev->video_out, "preview");
	if (ret < 0)
		return ret;
		goto error_video_out;

	/* Connect the video nodes to the previewer subdev. */
	ret = media_entity_create_link(&prev->video_in.video.entity, 0,
			&prev->subdev.entity, PREV_PAD_SINK, 0);
	if (ret < 0)
		return ret;
		goto error_link;

	ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
			&prev->video_out.video.entity, 0, 0);
	if (ret < 0)
		return ret;
		goto error_link;

	return 0;

error_link:
	omap3isp_video_cleanup(&prev->video_out);
error_video_out:
	omap3isp_video_cleanup(&prev->video_in);
error_video_in:
	media_entity_cleanup(&prev->subdev.entity);
	return ret;
}

/*
@@ -2088,21 +2096,12 @@ static int preview_init_entities(struct isp_prev_device *prev)
int omap3isp_preview_init(struct isp_device *isp)
{
	struct isp_prev_device *prev = &isp->isp_prev;
	int ret;

	spin_lock_init(&prev->lock);
	init_waitqueue_head(&prev->wait);
	preview_init_params(prev);

	ret = preview_init_entities(prev);
	if (ret < 0)
		goto out;

out:
	if (ret)
		omap3isp_preview_cleanup(isp);

	return ret;
	return preview_init_entities(prev);
}

void omap3isp_preview_cleanup(struct isp_device *isp)
+13 −14
Original line number Diff line number Diff line
@@ -1688,24 +1688,32 @@ static int resizer_init_entities(struct isp_res_device *res)

	ret = omap3isp_video_init(&res->video_in, "resizer");
	if (ret < 0)
		return ret;
		goto error_video_in;

	ret = omap3isp_video_init(&res->video_out, "resizer");
	if (ret < 0)
		return ret;
		goto error_video_out;

	/* Connect the video nodes to the resizer subdev. */
	ret = media_entity_create_link(&res->video_in.video.entity, 0,
			&res->subdev.entity, RESZ_PAD_SINK, 0);
	if (ret < 0)
		return ret;
		goto error_link;

	ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
			&res->video_out.video.entity, 0, 0);
	if (ret < 0)
		return ret;
		goto error_link;

	return 0;

error_link:
	omap3isp_video_cleanup(&res->video_out);
error_video_out:
	omap3isp_video_cleanup(&res->video_in);
error_video_in:
	media_entity_cleanup(&res->subdev.entity);
	return ret;
}

/*
@@ -1716,19 +1724,10 @@ static int resizer_init_entities(struct isp_res_device *res)
int omap3isp_resizer_init(struct isp_device *isp)
{
	struct isp_res_device *res = &isp->isp_res;
	int ret;

	init_waitqueue_head(&res->wait);
	atomic_set(&res->stopping, 0);
	ret = resizer_init_entities(res);
	if (ret < 0)
		goto out;

out:
	if (ret)
		omap3isp_resizer_cleanup(isp);

	return ret;
	return resizer_init_entities(res);
}

void omap3isp_resizer_cleanup(struct isp_device *isp)
Loading