4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Steve Longerbeam <slongerbeam@xxxxxxxxx> commit 4bc1ab41eee9d02ad2483bf8f51a7b72e3504eba upstream. 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 # for 4.13 and up Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/media/imx/imx-media-csi.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -648,10 +648,16 @@ static int csi_start(struct csi_priv *pr usleep_range(delay_usec, delay_usec + 1000); } + /* 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); @@ -679,6 +685,8 @@ fim_off: 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; } @@ -694,6 +702,9 @@ static void csi_stop(struct csi_priv *pr */ 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); @@ -861,23 +872,13 @@ static int csi_s_stream(struct v4l2_subd 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: