]>
Commit | Line | Data |
---|---|---|
4888e11d GKH |
1 | From 2e0fe66e0a136252f4d89dbbccdcb26deb867eb8 Mon Sep 17 00:00:00 2001 |
2 | From: Steve Longerbeam <slongerbeam@gmail.com> | |
3 | Date: Mon, 21 Jan 2019 21:35:50 -0200 | |
4 | Subject: media: imx: csi: Disable CSI immediately after last EOF | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | From: Steve Longerbeam <slongerbeam@gmail.com> | |
10 | ||
11 | commit 2e0fe66e0a136252f4d89dbbccdcb26deb867eb8 upstream. | |
12 | ||
13 | Disable the CSI immediately after receiving the last EOF before stream | |
14 | off (and thus before disabling the IDMA channel). Do this by moving the | |
15 | wait for EOF completion into a new function csi_idmac_wait_last_eof(). | |
16 | ||
17 | This fixes a complete system hard lockup on the SabreAuto when streaming | |
18 | from the ADV7180, by repeatedly sending a stream off immediately followed | |
19 | by stream on: | |
20 | ||
21 | while true; do v4l2-ctl -d4 --stream-mmap --stream-count=3; done | |
22 | ||
23 | Eventually this either causes the system lockup or EOF timeouts at all | |
24 | subsequent stream on, until a system reset. | |
25 | ||
26 | The lockup occurs when disabling the IDMA channel at stream off. Disabling | |
27 | the CSI before disabling the IDMA channel appears to be a reliable fix for | |
28 | the hard lockup. | |
29 | ||
30 | Fixes: 4a34ec8e470cb ("[media] media: imx: Add CSI subdev driver") | |
31 | ||
32 | Reported-by: Gaƫl PORTAY <gael.portay@collabora.com> | |
33 | Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com> | |
34 | Cc: stable@vger.kernel.org # for 4.13 and up | |
35 | Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | |
36 | Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | |
37 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
38 | ||
39 | --- | |
40 | drivers/staging/media/imx/imx-media-csi.c | 17 ++++++++++++++--- | |
41 | 1 file changed, 14 insertions(+), 3 deletions(-) | |
42 | ||
43 | --- a/drivers/staging/media/imx/imx-media-csi.c | |
44 | +++ b/drivers/staging/media/imx/imx-media-csi.c | |
45 | @@ -629,7 +629,7 @@ out_put_ipu: | |
46 | return ret; | |
47 | } | |
48 | ||
49 | -static void csi_idmac_stop(struct csi_priv *priv) | |
50 | +static void csi_idmac_wait_last_eof(struct csi_priv *priv) | |
51 | { | |
52 | unsigned long flags; | |
53 | int ret; | |
54 | @@ -646,7 +646,10 @@ static void csi_idmac_stop(struct csi_pr | |
55 | &priv->last_eof_comp, msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT)); | |
56 | if (ret == 0) | |
57 | v4l2_warn(&priv->sd, "wait last EOF timeout\n"); | |
58 | +} | |
59 | ||
60 | +static void csi_idmac_stop(struct csi_priv *priv) | |
61 | +{ | |
62 | devm_free_irq(priv->dev, priv->eof_irq, priv); | |
63 | devm_free_irq(priv->dev, priv->nfb4eof_irq, priv); | |
64 | ||
65 | @@ -758,6 +761,16 @@ idmac_stop: | |
66 | ||
67 | static void csi_stop(struct csi_priv *priv) | |
68 | { | |
69 | + if (priv->dest == IPU_CSI_DEST_IDMAC) | |
70 | + csi_idmac_wait_last_eof(priv); | |
71 | + | |
72 | + /* | |
73 | + * Disable the CSI asap, after syncing with the last EOF. | |
74 | + * Doing so after the IDMA channel is disabled has shown to | |
75 | + * create hard system-wide hangs. | |
76 | + */ | |
77 | + ipu_csi_disable(priv->csi); | |
78 | + | |
79 | if (priv->dest == IPU_CSI_DEST_IDMAC) { | |
80 | csi_idmac_stop(priv); | |
81 | ||
82 | @@ -765,8 +778,6 @@ static void csi_stop(struct csi_priv *pr | |
83 | if (priv->fim) | |
84 | imx_media_fim_set_stream(priv->fim, NULL, false); | |
85 | } | |
86 | - | |
87 | - ipu_csi_disable(priv->csi); | |
88 | } | |
89 | ||
90 | static const struct csi_skip_desc csi_skip[12] = { |