Commit 2b177f28 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

media: vimc: use new release op



Use the new v4l2_subdev_internal_ops release op to free the
subdev memory only when the last user closed the file handle.

Move v4l2_device_unregister_subdev() to the end of the
vimc_ent_sd_unregister() function since now the unregister_subdev()
call may free the vimc_ent_device struct which is used after the
unregister_subdev() call. So this now has to be done last.

Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 3650a23e
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -380,6 +380,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,
			 u32 function,
			 u16 num_pads,
			 const unsigned long *pads_flag,
			 const struct v4l2_subdev_internal_ops *sd_int_ops,
			 const struct v4l2_subdev_ops *sd_ops)
{
	int ret;
@@ -394,6 +395,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,

	/* Initialize the subdev */
	v4l2_subdev_init(sd, sd_ops);
	sd->internal_ops = sd_int_ops;
	sd->entity.function = function;
	sd->entity.ops = &vimc_ent_sd_mops;
	sd->owner = THIS_MODULE;
@@ -431,9 +433,9 @@ EXPORT_SYMBOL_GPL(vimc_ent_sd_register);

void vimc_ent_sd_unregister(struct vimc_ent_device *ved, struct v4l2_subdev *sd)
{
	v4l2_device_unregister_subdev(sd);
	media_entity_cleanup(ved->ent);
	vimc_pads_cleanup(ved->pads);
	v4l2_device_unregister_subdev(sd);
}
EXPORT_SYMBOL_GPL(vimc_ent_sd_unregister);

+2 −0
Original line number Diff line number Diff line
@@ -187,6 +187,7 @@ const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat);
 * @function:	media entity function defined by MEDIA_ENT_F_* macros
 * @num_pads:	number of pads to initialize
 * @pads_flag:	flags to use in each pad
 * @sd_int_ops:	pointer to &struct v4l2_subdev_internal_ops
 * @sd_ops:	pointer to &struct v4l2_subdev_ops.
 *
 * Helper function initialize and register the struct vimc_ent_device and struct
@@ -199,6 +200,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved,
			 u32 function,
			 u16 num_pads,
			 const unsigned long *pads_flag,
			 const struct v4l2_subdev_internal_ops *sd_int_ops,
			 const struct v4l2_subdev_ops *sd_ops);

/**
+13 −2
Original line number Diff line number Diff line
@@ -489,6 +489,18 @@ static void *vimc_deb_process_frame(struct vimc_ent_device *ved,

}

static void vimc_deb_release(struct v4l2_subdev *sd)
{
	struct vimc_deb_device *vdeb =
				container_of(sd, struct vimc_deb_device, sd);

	kfree(vdeb);
}

static const struct v4l2_subdev_internal_ops vimc_deb_int_ops = {
	.release = vimc_deb_release,
};

static void vimc_deb_comp_unbind(struct device *comp, struct device *master,
				 void *master_data)
{
@@ -497,7 +509,6 @@ static void vimc_deb_comp_unbind(struct device *comp, struct device *master,
						    ved);

	vimc_ent_sd_unregister(ved, &vdeb->sd);
	kfree(vdeb);
}

static int vimc_deb_comp_bind(struct device *comp, struct device *master,
@@ -519,7 +530,7 @@ static int vimc_deb_comp_bind(struct device *comp, struct device *master,
				   MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2,
				   (const unsigned long[2]) {MEDIA_PAD_FL_SINK,
				   MEDIA_PAD_FL_SOURCE},
				   &vimc_deb_ops);
				   &vimc_deb_int_ops, &vimc_deb_ops);
	if (ret) {
		kfree(vdeb);
		return ret;
+13 −2
Original line number Diff line number Diff line
@@ -348,6 +348,18 @@ static void *vimc_sca_process_frame(struct vimc_ent_device *ved,
	return vsca->src_frame;
};

static void vimc_sca_release(struct v4l2_subdev *sd)
{
	struct vimc_sca_device *vsca =
				container_of(sd, struct vimc_sca_device, sd);

	kfree(vsca);
}

static const struct v4l2_subdev_internal_ops vimc_sca_int_ops = {
	.release = vimc_sca_release,
};

static void vimc_sca_comp_unbind(struct device *comp, struct device *master,
				 void *master_data)
{
@@ -356,7 +368,6 @@ static void vimc_sca_comp_unbind(struct device *comp, struct device *master,
						    ved);

	vimc_ent_sd_unregister(ved, &vsca->sd);
	kfree(vsca);
}


@@ -379,7 +390,7 @@ static int vimc_sca_comp_bind(struct device *comp, struct device *master,
				   MEDIA_ENT_F_PROC_VIDEO_SCALER, 2,
				   (const unsigned long[2]) {MEDIA_PAD_FL_SINK,
				   MEDIA_PAD_FL_SOURCE},
				   &vimc_sca_ops);
				   &vimc_sca_int_ops, &vimc_sca_ops);
	if (ret) {
		kfree(vsca);
		return ret;
+15 −4
Original line number Diff line number Diff line
@@ -301,6 +301,20 @@ static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = {
	.s_ctrl = vimc_sen_s_ctrl,
};

static void vimc_sen_release(struct v4l2_subdev *sd)
{
	struct vimc_sen_device *vsen =
				container_of(sd, struct vimc_sen_device, sd);

	v4l2_ctrl_handler_free(&vsen->hdl);
	tpg_free(&vsen->tpg);
	kfree(vsen);
}

static const struct v4l2_subdev_internal_ops vimc_sen_int_ops = {
	.release = vimc_sen_release,
};

static void vimc_sen_comp_unbind(struct device *comp, struct device *master,
				 void *master_data)
{
@@ -309,9 +323,6 @@ static void vimc_sen_comp_unbind(struct device *comp, struct device *master,
				container_of(ved, struct vimc_sen_device, ved);

	vimc_ent_sd_unregister(ved, &vsen->sd);
	v4l2_ctrl_handler_free(&vsen->hdl);
	tpg_free(&vsen->tpg);
	kfree(vsen);
}

/* Image Processing Controls */
@@ -371,7 +382,7 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master,
				   pdata->entity_name,
				   MEDIA_ENT_F_CAM_SENSOR, 1,
				   (const unsigned long[1]) {MEDIA_PAD_FL_SOURCE},
				   &vimc_sen_ops);
				   &vimc_sen_int_ops, &vimc_sen_ops);
	if (ret)
		goto err_free_hdl;