]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
media: imx: csi: Stop upstream before disabling IDMA channel
authorSteve Longerbeam <slongerbeam@gmail.com>
Mon, 21 Jan 2019 23:35:51 +0000 (21:35 -0200)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Thu, 31 Jan 2019 11:14:19 +0000 (09:14 -0200)
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@gmail.com>
Cc: stable@vger.kernel.org # for 4.13 and up
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/staging/media/imx/imx-media-csi.c

index 920e38885292f134afefa036112e8073f546ee47..d851ca2497b4aa4d5e141cf23d369097c8e53f31 100644 (file)
@@ -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: