Commit 2a4558c6 authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Mauro Carvalho Chehab
Browse files

media: imx: Move pads init to probe



If a subdevice is unregistered and then registered again without the
driver being removed and re-probed (which will happen when the media
device is removed and re-probed without also removing/re-probing the
subdevice), media_device_register_entity() is called with a non-zero
entity->num_pads, and then the subdevice's .registered callback calls
media_entity_pads_init(). Thus the subdevice's pad objects are added
to the media device pad list twice, causing list corruption.

One way to fix this would be to create media_entity_pads_destroy(),
and call it in the subdevice's .unregistered callback. But calling
media_entity_pads_init() in the .registered callbacks was done for
legacy reasons and is no longer necessary, so move the call to
media_entity_pads_init() into the subdevice's probe functions. This
fixes the duplicate pad obejcts in the media device pad list.

Signed-off-by: default avatarSteve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 1f464246
Loading
Loading
Loading
Loading
+9 −16
Original line number Diff line number Diff line
@@ -428,32 +428,19 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
	return 0;
}

/*
 * retrieve our pads parsed from the OF graph by the media device
 */
static int prp_registered(struct v4l2_subdev *sd)
{
	struct prp_priv *priv = sd_to_priv(sd);
	int i, ret;
	u32 code;

	for (i = 0; i < PRP_NUM_PADS; i++) {
		priv->pad[i].flags = (i == PRP_SINK_PAD) ?
			MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
	}

	/* init default frame interval */
	priv->frame_interval.numerator = 1;
	priv->frame_interval.denominator = 30;

	/* set a default mbus format  */
	imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
	ret = imx_media_init_mbus_fmt(&priv->format_mbus, 640, 480, code,
	return imx_media_init_mbus_fmt(&priv->format_mbus, 640, 480, code,
				       V4L2_FIELD_NONE, NULL);
	if (ret)
		return ret;

	return media_entity_pads_init(&sd->entity, PRP_NUM_PADS, priv->pad);
}

static const struct v4l2_subdev_pad_ops prp_pad_ops = {
@@ -487,6 +474,7 @@ static const struct v4l2_subdev_internal_ops prp_internal_ops = {
static int prp_init(struct imx_ic_priv *ic_priv)
{
	struct prp_priv *priv;
	int i;

	priv = devm_kzalloc(ic_priv->ipu_dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
@@ -496,7 +484,12 @@ static int prp_init(struct imx_ic_priv *ic_priv)
	ic_priv->task_priv = priv;
	priv->ic_priv = ic_priv;

	return 0;
	for (i = 0; i < PRP_NUM_PADS; i++)
		priv->pad[i].flags = (i == PRP_SINK_PAD) ?
			MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;

	return media_entity_pads_init(&ic_priv->sd.entity, PRP_NUM_PADS,
				      priv->pad);
}

static void prp_remove(struct imx_ic_priv *ic_priv)
+14 −14
Original line number Diff line number Diff line
@@ -1240,9 +1240,6 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
	return 0;
}

/*
 * retrieve our pads parsed from the OF graph by the media device
 */
static int prp_registered(struct v4l2_subdev *sd)
{
	struct prp_priv *priv = sd_to_priv(sd);
@@ -1250,12 +1247,9 @@ static int prp_registered(struct v4l2_subdev *sd)
	int i, ret;
	u32 code;

	for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
		priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ?
			MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;

	/* set a default mbus format  */
	imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
	for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
		ret = imx_media_init_mbus_fmt(&priv->format_mbus[i],
					      640, 480, code, V4L2_FIELD_NONE,
					      &priv->cc[i]);
@@ -1267,11 +1261,6 @@ static int prp_registered(struct v4l2_subdev *sd)
	priv->frame_interval.numerator = 1;
	priv->frame_interval.denominator = 30;

	ret = media_entity_pads_init(&sd->entity, PRPENCVF_NUM_PADS,
				     priv->pad);
	if (ret)
		return ret;

	priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev,
						   &ic_priv->sd,
						   PRPENCVF_SRC_PAD);
@@ -1337,6 +1326,7 @@ static const struct v4l2_subdev_internal_ops prp_internal_ops = {
static int prp_init(struct imx_ic_priv *ic_priv)
{
	struct prp_priv *priv;
	int i, ret;

	priv = devm_kzalloc(ic_priv->ipu_dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
@@ -1350,7 +1340,17 @@ static int prp_init(struct imx_ic_priv *ic_priv)

	mutex_init(&priv->lock);

	return 0;
	for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
		priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ?
			MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
	}

	ret = media_entity_pads_init(&ic_priv->sd.entity, PRPENCVF_NUM_PADS,
				     priv->pad);
	if (ret)
		mutex_destroy(&priv->lock);

	return ret;
}

static void prp_remove(struct imx_ic_priv *ic_priv)
+8 −7
Original line number Diff line number Diff line
@@ -765,13 +765,6 @@ int imx_media_capture_device_register(struct imx_media_video_dev *vdev)

	INIT_LIST_HEAD(&priv->ready_q);

	priv->vdev_pad.flags = MEDIA_PAD_FL_SINK;
	ret = media_entity_pads_init(&vfd->entity, 1, &priv->vdev_pad);
	if (ret) {
		v4l2_err(sd, "failed to init dev pad\n");
		goto unreg;
	}

	/* create the link from the src_sd devnode pad to device node */
	ret = media_create_pad_link(&sd->entity, priv->src_sd_pad,
				    &vfd->entity, 0, 0);
@@ -834,6 +827,7 @@ imx_media_capture_device_init(struct device *dev, struct v4l2_subdev *src_sd,
{
	struct capture_priv *priv;
	struct video_device *vfd;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
@@ -858,6 +852,13 @@ imx_media_capture_device_init(struct device *dev, struct v4l2_subdev *src_sd,
	vfd->queue = &priv->q;
	priv->vdev.vfd = vfd;

	priv->vdev_pad.flags = MEDIA_PAD_FL_SINK;
	ret = media_entity_pads_init(&vfd->entity, 1, &priv->vdev_pad);
	if (ret) {
		video_device_release(vfd);
		return ERR_PTR(ret);
	}

	INIT_LIST_HEAD(&priv->vdev.list);

	video_set_drvdata(vfd, priv);
+10 −11
Original line number Diff line number Diff line
@@ -1740,9 +1740,6 @@ static int csi_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
	return v4l2_event_unsubscribe(fh, sub);
}

/*
 * retrieve our pads parsed from the OF graph by the media device
 */
static int csi_registered(struct v4l2_subdev *sd)
{
	struct csi_priv *priv = v4l2_get_subdevdata(sd);
@@ -1759,9 +1756,6 @@ static int csi_registered(struct v4l2_subdev *sd)
	priv->csi = csi;

	for (i = 0; i < CSI_NUM_PADS; i++) {
		priv->pad[i].flags = (i == CSI_SINK_PAD) ?
			MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;

		code = 0;
		if (i != CSI_SINK_PAD)
			imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
@@ -1793,10 +1787,6 @@ static int csi_registered(struct v4l2_subdev *sd)
		goto put_csi;
	}

	ret = media_entity_pads_init(&sd->entity, CSI_NUM_PADS, priv->pad);
	if (ret)
		goto free_fim;

	priv->vdev = imx_media_capture_device_init(priv->sd.dev,
						   &priv->sd,
						   CSI_SRC_PAD_IDMAC);
@@ -1934,7 +1924,7 @@ static int imx_csi_probe(struct platform_device *pdev)
	struct ipu_client_platformdata *pdata;
	struct pinctrl *pinctrl;
	struct csi_priv *priv;
	int ret;
	int i, ret;

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
@@ -1974,6 +1964,15 @@ static int imx_csi_probe(struct platform_device *pdev)
	imx_media_grp_id_to_sd_name(priv->sd.name, sizeof(priv->sd.name),
				    priv->sd.grp_id, ipu_get_num(priv->ipu));

	for (i = 0; i < CSI_NUM_PADS; i++)
		priv->pad[i].flags = (i == CSI_SINK_PAD) ?
			MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;

	ret = media_entity_pads_init(&priv->sd.entity, CSI_NUM_PADS,
				     priv->pad);
	if (ret)
		return ret;

	mutex_init(&priv->lock);

	v4l2_ctrl_handler_init(&priv->ctrl_hdlr, 0);
+11 −16
Original line number Diff line number Diff line
@@ -841,9 +841,6 @@ static int vdic_s_frame_interval(struct v4l2_subdev *sd,
	return ret;
}

/*
 * retrieve our pads parsed from the OF graph by the media device
 */
static int vdic_registered(struct v4l2_subdev *sd)
{
	struct vdic_priv *priv = v4l2_get_subdevdata(sd);
@@ -851,9 +848,6 @@ static int vdic_registered(struct v4l2_subdev *sd)
	u32 code;

	for (i = 0; i < VDIC_NUM_PADS; i++) {
		priv->pad[i].flags = (i == VDIC_SRC_PAD_DIRECT) ?
			MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;

		code = 0;
		if (i != VDIC_SINK_PAD_IDMAC)
			imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV);
@@ -874,15 +868,7 @@ static int vdic_registered(struct v4l2_subdev *sd)

	priv->active_input_pad = VDIC_SINK_PAD_DIRECT;

	ret = vdic_init_controls(priv);
	if (ret)
		return ret;

	ret = media_entity_pads_init(&sd->entity, VDIC_NUM_PADS, priv->pad);
	if (ret)
		v4l2_ctrl_handler_free(&priv->ctrl_hdlr);

	return ret;
	return vdic_init_controls(priv);
}

static void vdic_unregistered(struct v4l2_subdev *sd)
@@ -927,7 +913,7 @@ struct v4l2_subdev *imx_media_vdic_register(struct v4l2_device *v4l2_dev,
					    u32 grp_id)
{
	struct vdic_priv *priv;
	int ret;
	int i, ret;

	priv = devm_kzalloc(ipu_dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
@@ -949,6 +935,15 @@ struct v4l2_subdev *imx_media_vdic_register(struct v4l2_device *v4l2_dev,

	mutex_init(&priv->lock);

	for (i = 0; i < VDIC_NUM_PADS; i++)
		priv->pad[i].flags = (i == VDIC_SRC_PAD_DIRECT) ?
			MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;

	ret = media_entity_pads_init(&priv->sd.entity, VDIC_NUM_PADS,
				     priv->pad);
	if (ret)
		goto free;

	ret = v4l2_device_register_subdev(v4l2_dev, &priv->sd);
	if (ret)
		goto free;
Loading