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: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
Hans Verkuil 2019-03-05 03:36:20 -05:00 коммит произвёл Mauro Carvalho Chehab
Родитель 3650a23eda
Коммит 2b177f2849
5 изменённых файлов: 46 добавлений и 9 удалений

Просмотреть файл

@ -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);

Просмотреть файл

@ -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);
/**

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;