[PATCH v4 2/3] media: imx: csi: Stop upstream before disabling IDMA channel

From: Steve Longerbeam
Date: Mon Jan 21 2019 - 18:36:19 EST


Move upstream stream off to just after receiving the last EOF completion
and disabling the CSI (and thus before disabling the IDMA channel) in
csi_stop(). For symmetry also move upstream stream on to beginning of
csi_start().

Doing this makes csi_s_stream() more symmetric with prp_s_stream() which
will require the same change to fix a hard lockup.

Signed-off-by: Steve Longerbeam <slongerbeam@xxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
---
drivers/staging/media/imx/imx-media-csi.c | 25 ++++++++++++-----------
1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 920e38885292..d851ca2497b4 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -753,10 +753,16 @@ static int csi_start(struct csi_priv *priv)

output_fi = &priv->frame_interval[priv->active_output_pad];

+ /* start upstream */
+ ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 1);
+ ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
+ if (ret)
+ return ret;
+
if (priv->dest == IPU_CSI_DEST_IDMAC) {
ret = csi_idmac_start(priv);
if (ret)
- return ret;
+ goto stop_upstream;
}

ret = csi_setup(priv);
@@ -784,6 +790,8 @@ static int csi_start(struct csi_priv *priv)
idmac_stop:
if (priv->dest == IPU_CSI_DEST_IDMAC)
csi_idmac_stop(priv);
+stop_upstream:
+ v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
return ret;
}

@@ -799,6 +807,9 @@ static void csi_stop(struct csi_priv *priv)
*/
ipu_csi_disable(priv->csi);

+ /* stop upstream */
+ v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
+
if (priv->dest == IPU_CSI_DEST_IDMAC) {
csi_idmac_stop(priv);

@@ -966,23 +977,13 @@ static int csi_s_stream(struct v4l2_subdev *sd, int enable)
goto update_count;

if (enable) {
- /* upstream must be started first, before starting CSI */
- ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 1);
- ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
- if (ret)
- goto out;
-
dev_dbg(priv->dev, "stream ON\n");
ret = csi_start(priv);
- if (ret) {
- v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
+ if (ret)
goto out;
- }
} else {
dev_dbg(priv->dev, "stream OFF\n");
- /* CSI must be stopped first, then stop upstream */
csi_stop(priv);
- v4l2_subdev_call(priv->src_sd, video, s_stream, 0);
}

update_count:
--
2.17.1