linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] rcar-csi2: restart CSI-2 link if error is detected
@ 2019-02-18 10:15 Niklas Söderlund
  2019-03-11 10:53 ` Hans Verkuil
  0 siblings, 1 reply; 5+ messages in thread
From: Niklas Söderlund @ 2019-02-18 10:15 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, Niklas Söderlund

Restart the CSI-2 link if the CSI-2 receiver detects an error during
reception. The driver did nothing when a link error happened and the
data flow simply stopped without the user knowing why.

Change the driver to try and recover from errors by restarting the link
and informing the user that something is not right. For obvious reasons
it's not possible to recover from all errors (video source disconnected
for example) but in such cases the user is at least informed of the
error and the same behavior of the stopped data flow is retained.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
 drivers/media/platform/rcar-vin/rcar-csi2.c | 52 ++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
index f90b380478775015..0506fe4106d5c012 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -84,6 +84,9 @@ struct rcar_csi2;
 
 /* Interrupt Enable */
 #define INTEN_REG			0x30
+#define INTEN_INT_AFIFO_OF		BIT(27)
+#define INTEN_INT_ERRSOTHS		BIT(4)
+#define INTEN_INT_ERRSOTSYNCHS		BIT(3)
 
 /* Interrupt Source Mask */
 #define INTCLOSE_REG			0x34
@@ -540,6 +543,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
 	if (mbps < 0)
 		return mbps;
 
+	/* Enable interrupts. */
+	rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
+		    | INTEN_INT_ERRSOTSYNCHS);
+
 	/* Init */
 	rcsi2_write(priv, TREF_REG, TREF_TREF);
 	rcsi2_write(priv, PHTC_REG, 0);
@@ -702,6 +709,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
 	.pad	= &rcar_csi2_pad_ops,
 };
 
+static irqreturn_t rcsi2_irq(int irq, void *data)
+{
+	struct rcar_csi2 *priv = data;
+	u32 status, err_status;
+
+	status = rcsi2_read(priv, INTSTATE_REG);
+	err_status = rcsi2_read(priv, INTERRSTATE_REG);
+
+	if (!status)
+		return IRQ_HANDLED;
+
+	rcsi2_write(priv, INTSTATE_REG, status);
+
+	if (!err_status)
+		return IRQ_HANDLED;
+
+	rcsi2_write(priv, INTERRSTATE_REG, err_status);
+
+	dev_err(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t rcsi2_irq_thread(int irq, void *data)
+{
+	struct rcar_csi2 *priv = data;
+
+	mutex_lock(&priv->lock);
+	rcsi2_stop(priv);
+	usleep_range(1000, 2000);
+	if (rcsi2_start(priv))
+		dev_err(priv->dev, "Failed to restart CSI-2 receiver\n");
+	mutex_unlock(&priv->lock);
+
+	return IRQ_HANDLED;
+}
+
 /* -----------------------------------------------------------------------------
  * Async handling and registration of subdevices and links.
  */
@@ -982,7 +1026,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
 				 struct platform_device *pdev)
 {
 	struct resource *res;
-	int irq;
+	int irq, ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->base = devm_ioremap_resource(&pdev->dev, res);
@@ -993,6 +1037,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
 	if (irq < 0)
 		return irq;
 
+	ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
+					rcsi2_irq_thread, IRQF_SHARED,
+					KBUILD_MODNAME, priv);
+	if (ret)
+		return ret;
+
 	priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
 	if (IS_ERR(priv->rstc))
 		return PTR_ERR(priv->rstc);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] rcar-csi2: restart CSI-2 link if error is detected
  2019-02-18 10:15 [PATCH] rcar-csi2: restart CSI-2 link if error is detected Niklas Söderlund
@ 2019-03-11 10:53 ` Hans Verkuil
  2019-03-12 18:58   ` Niklas Söderlund
  0 siblings, 1 reply; 5+ messages in thread
From: Hans Verkuil @ 2019-03-11 10:53 UTC (permalink / raw)
  To: Niklas Söderlund, Laurent Pinchart, linux-media; +Cc: linux-renesas-soc

On 2/18/19 11:15 AM, Niklas Söderlund wrote:
> Restart the CSI-2 link if the CSI-2 receiver detects an error during
> reception. The driver did nothing when a link error happened and the
> data flow simply stopped without the user knowing why.
> 
> Change the driver to try and recover from errors by restarting the link
> and informing the user that something is not right. For obvious reasons
> it's not possible to recover from all errors (video source disconnected
> for example) but in such cases the user is at least informed of the
> error and the same behavior of the stopped data flow is retained.

What you really would like to have is that when a CSI error is detected,
the CSI driver can ask upstream whether or not a disconnect has taken place.

If that was the case, then there is no point in restarting the CSI.

While a disconnect is very uncommon for a sensor, it is of course perfectly
normal if an HDMI-to-CSI bridge was connected to the CSI port.

Unfortunately, we don't have such functionality, but perhaps this is something
to think about?

This does mean, however, that I don't like the dev_err since it doesn't have
to be an error. I would suggest replacing the first dev_err by dev_info and
the second by dev_warn.

Regards,

	Hans

> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
>  drivers/media/platform/rcar-vin/rcar-csi2.c | 52 ++++++++++++++++++++-
>  1 file changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
> index f90b380478775015..0506fe4106d5c012 100644
> --- a/drivers/media/platform/rcar-vin/rcar-csi2.c
> +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
> @@ -84,6 +84,9 @@ struct rcar_csi2;
>  
>  /* Interrupt Enable */
>  #define INTEN_REG			0x30
> +#define INTEN_INT_AFIFO_OF		BIT(27)
> +#define INTEN_INT_ERRSOTHS		BIT(4)
> +#define INTEN_INT_ERRSOTSYNCHS		BIT(3)
>  
>  /* Interrupt Source Mask */
>  #define INTCLOSE_REG			0x34
> @@ -540,6 +543,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
>  	if (mbps < 0)
>  		return mbps;
>  
> +	/* Enable interrupts. */
> +	rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
> +		    | INTEN_INT_ERRSOTSYNCHS);
> +
>  	/* Init */
>  	rcsi2_write(priv, TREF_REG, TREF_TREF);
>  	rcsi2_write(priv, PHTC_REG, 0);
> @@ -702,6 +709,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
>  	.pad	= &rcar_csi2_pad_ops,
>  };
>  
> +static irqreturn_t rcsi2_irq(int irq, void *data)
> +{
> +	struct rcar_csi2 *priv = data;
> +	u32 status, err_status;
> +
> +	status = rcsi2_read(priv, INTSTATE_REG);
> +	err_status = rcsi2_read(priv, INTERRSTATE_REG);
> +
> +	if (!status)
> +		return IRQ_HANDLED;
> +
> +	rcsi2_write(priv, INTSTATE_REG, status);
> +
> +	if (!err_status)
> +		return IRQ_HANDLED;
> +
> +	rcsi2_write(priv, INTERRSTATE_REG, err_status);
> +
> +	dev_err(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
> +
> +	return IRQ_WAKE_THREAD;
> +}
> +
> +static irqreturn_t rcsi2_irq_thread(int irq, void *data)
> +{
> +	struct rcar_csi2 *priv = data;
> +
> +	mutex_lock(&priv->lock);
> +	rcsi2_stop(priv);
> +	usleep_range(1000, 2000);
> +	if (rcsi2_start(priv))
> +		dev_err(priv->dev, "Failed to restart CSI-2 receiver\n");
> +	mutex_unlock(&priv->lock);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  /* -----------------------------------------------------------------------------
>   * Async handling and registration of subdevices and links.
>   */
> @@ -982,7 +1026,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
>  				 struct platform_device *pdev)
>  {
>  	struct resource *res;
> -	int irq;
> +	int irq, ret;
>  
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	priv->base = devm_ioremap_resource(&pdev->dev, res);
> @@ -993,6 +1037,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
>  	if (irq < 0)
>  		return irq;
>  
> +	ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
> +					rcsi2_irq_thread, IRQF_SHARED,
> +					KBUILD_MODNAME, priv);
> +	if (ret)
> +		return ret;
> +
>  	priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
>  	if (IS_ERR(priv->rstc))
>  		return PTR_ERR(priv->rstc);
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rcar-csi2: restart CSI-2 link if error is detected
  2019-03-11 10:53 ` Hans Verkuil
@ 2019-03-12 18:58   ` Niklas Söderlund
  2019-03-12 20:22     ` Laurent Pinchart
  0 siblings, 1 reply; 5+ messages in thread
From: Niklas Söderlund @ 2019-03-12 18:58 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: Laurent Pinchart, linux-media, linux-renesas-soc

Hi Hans,

Thanks for your feedback.

On 2019-03-11 11:53:01 +0100, Hans Verkuil wrote:
> On 2/18/19 11:15 AM, Niklas Söderlund wrote:
> > Restart the CSI-2 link if the CSI-2 receiver detects an error during
> > reception. The driver did nothing when a link error happened and the
> > data flow simply stopped without the user knowing why.
> > 
> > Change the driver to try and recover from errors by restarting the link
> > and informing the user that something is not right. For obvious reasons
> > it's not possible to recover from all errors (video source disconnected
> > for example) but in such cases the user is at least informed of the
> > error and the same behavior of the stopped data flow is retained.
> 
> What you really would like to have is that when a CSI error is detected,
> the CSI driver can ask upstream whether or not a disconnect has taken place.
> 
> If that was the case, then there is no point in restarting the CSI.
> 
> While a disconnect is very uncommon for a sensor, it is of course perfectly
> normal if an HDMI-to-CSI bridge was connected to the CSI port.
> 
> Unfortunately, we don't have such functionality, but perhaps this is something
> to think about?

I think your idea sounds good and that such a functionality could be 
useful. I have a  feeling such a functionality could be related to 
notifications?

> 
> This does mean, however, that I don't like the dev_err since it doesn't have
> to be an error. I would suggest replacing the first dev_err by dev_info and
> the second by dev_warn.

With the background you provides I agree that they should not be 
dev_err. I will update as you suggest for the next version, thanks.

> 
> Regards,
> 
> 	Hans
> 
> > 
> > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> > ---
> >  drivers/media/platform/rcar-vin/rcar-csi2.c | 52 ++++++++++++++++++++-
> >  1 file changed, 51 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
> > index f90b380478775015..0506fe4106d5c012 100644
> > --- a/drivers/media/platform/rcar-vin/rcar-csi2.c
> > +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
> > @@ -84,6 +84,9 @@ struct rcar_csi2;
> >  
> >  /* Interrupt Enable */
> >  #define INTEN_REG			0x30
> > +#define INTEN_INT_AFIFO_OF		BIT(27)
> > +#define INTEN_INT_ERRSOTHS		BIT(4)
> > +#define INTEN_INT_ERRSOTSYNCHS		BIT(3)
> >  
> >  /* Interrupt Source Mask */
> >  #define INTCLOSE_REG			0x34
> > @@ -540,6 +543,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
> >  	if (mbps < 0)
> >  		return mbps;
> >  
> > +	/* Enable interrupts. */
> > +	rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
> > +		    | INTEN_INT_ERRSOTSYNCHS);
> > +
> >  	/* Init */
> >  	rcsi2_write(priv, TREF_REG, TREF_TREF);
> >  	rcsi2_write(priv, PHTC_REG, 0);
> > @@ -702,6 +709,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
> >  	.pad	= &rcar_csi2_pad_ops,
> >  };
> >  
> > +static irqreturn_t rcsi2_irq(int irq, void *data)
> > +{
> > +	struct rcar_csi2 *priv = data;
> > +	u32 status, err_status;
> > +
> > +	status = rcsi2_read(priv, INTSTATE_REG);
> > +	err_status = rcsi2_read(priv, INTERRSTATE_REG);
> > +
> > +	if (!status)
> > +		return IRQ_HANDLED;
> > +
> > +	rcsi2_write(priv, INTSTATE_REG, status);
> > +
> > +	if (!err_status)
> > +		return IRQ_HANDLED;
> > +
> > +	rcsi2_write(priv, INTERRSTATE_REG, err_status);
> > +
> > +	dev_err(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
> > +
> > +	return IRQ_WAKE_THREAD;
> > +}
> > +
> > +static irqreturn_t rcsi2_irq_thread(int irq, void *data)
> > +{
> > +	struct rcar_csi2 *priv = data;
> > +
> > +	mutex_lock(&priv->lock);
> > +	rcsi2_stop(priv);
> > +	usleep_range(1000, 2000);
> > +	if (rcsi2_start(priv))
> > +		dev_err(priv->dev, "Failed to restart CSI-2 receiver\n");
> > +	mutex_unlock(&priv->lock);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> >  /* -----------------------------------------------------------------------------
> >   * Async handling and registration of subdevices and links.
> >   */
> > @@ -982,7 +1026,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
> >  				 struct platform_device *pdev)
> >  {
> >  	struct resource *res;
> > -	int irq;
> > +	int irq, ret;
> >  
> >  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >  	priv->base = devm_ioremap_resource(&pdev->dev, res);
> > @@ -993,6 +1037,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
> >  	if (irq < 0)
> >  		return irq;
> >  
> > +	ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
> > +					rcsi2_irq_thread, IRQF_SHARED,
> > +					KBUILD_MODNAME, priv);
> > +	if (ret)
> > +		return ret;
> > +
> >  	priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
> >  	if (IS_ERR(priv->rstc))
> >  		return PTR_ERR(priv->rstc);
> > 
> 

-- 
Regards,
Niklas Söderlund

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rcar-csi2: restart CSI-2 link if error is detected
  2019-03-12 18:58   ` Niklas Söderlund
@ 2019-03-12 20:22     ` Laurent Pinchart
  2019-03-12 21:37       ` Niklas Söderlund
  0 siblings, 1 reply; 5+ messages in thread
From: Laurent Pinchart @ 2019-03-12 20:22 UTC (permalink / raw)
  To: Niklas Söderlund; +Cc: Hans Verkuil, linux-media, linux-renesas-soc

Hello Niklas,

On Tue, Mar 12, 2019 at 07:58:13PM +0100, Niklas Söderlund wrote:
> On 2019-03-11 11:53:01 +0100, Hans Verkuil wrote:
> > On 2/18/19 11:15 AM, Niklas Söderlund wrote:
> >> Restart the CSI-2 link if the CSI-2 receiver detects an error during
> >> reception. The driver did nothing when a link error happened and the
> >> data flow simply stopped without the user knowing why.
> >> 
> >> Change the driver to try and recover from errors by restarting the link
> >> and informing the user that something is not right. For obvious reasons
> >> it's not possible to recover from all errors (video source disconnected
> >> for example) but in such cases the user is at least informed of the
> >> error and the same behavior of the stopped data flow is retained.

What error causes have you noticed in practice that would benefit from
this ?

> > What you really would like to have is that when a CSI error is detected,
> > the CSI driver can ask upstream whether or not a disconnect has taken place.
> > 
> > If that was the case, then there is no point in restarting the CSI.
> > 
> > While a disconnect is very uncommon for a sensor, it is of course perfectly
> > normal if an HDMI-to-CSI bridge was connected to the CSI port.

Note that this may not always result in a CSI-2 error, the HDMI to CSI-2
bridge may continue sending valid timings with dummy (or random) data.

> > Unfortunately, we don't have such functionality, but perhaps this is something
> > to think about?
> 
> I think your idea sounds good and that such a functionality could be 
> useful. I have a  feeling such a functionality could be related to 
> notifications?
> 
> > This does mean, however, that I don't like the dev_err since it doesn't have
> > to be an error. I would suggest replacing the first dev_err by dev_info and
> > the second by dev_warn.
> 
> With the background you provides I agree that they should not be 
> dev_err. I will update as you suggest for the next version, thanks.
> 
> >> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> >> ---
> >>  drivers/media/platform/rcar-vin/rcar-csi2.c | 52 ++++++++++++++++++++-
> >>  1 file changed, 51 insertions(+), 1 deletion(-)
> >> 
> >> diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
> >> index f90b380478775015..0506fe4106d5c012 100644
> >> --- a/drivers/media/platform/rcar-vin/rcar-csi2.c
> >> +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
> >> @@ -84,6 +84,9 @@ struct rcar_csi2;
> >>  
> >>  /* Interrupt Enable */
> >>  #define INTEN_REG			0x30
> >> +#define INTEN_INT_AFIFO_OF		BIT(27)
> >> +#define INTEN_INT_ERRSOTHS		BIT(4)
> >> +#define INTEN_INT_ERRSOTSYNCHS		BIT(3)
> >>  
> >>  /* Interrupt Source Mask */
> >>  #define INTCLOSE_REG			0x34
> >> @@ -540,6 +543,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
> >>  	if (mbps < 0)
> >>  		return mbps;
> >>  
> >> +	/* Enable interrupts. */
> >> +	rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
> >> +		    | INTEN_INT_ERRSOTSYNCHS);
> >> +
> >>  	/* Init */
> >>  	rcsi2_write(priv, TREF_REG, TREF_TREF);
> >>  	rcsi2_write(priv, PHTC_REG, 0);
> >> @@ -702,6 +709,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
> >>  	.pad	= &rcar_csi2_pad_ops,
> >>  };
> >>  
> >> +static irqreturn_t rcsi2_irq(int irq, void *data)
> >> +{
> >> +	struct rcar_csi2 *priv = data;
> >> +	u32 status, err_status;
> >> +
> >> +	status = rcsi2_read(priv, INTSTATE_REG);
> >> +	err_status = rcsi2_read(priv, INTERRSTATE_REG);
> >> +
> >> +	if (!status)
> >> +		return IRQ_HANDLED;
> >> +
> >> +	rcsi2_write(priv, INTSTATE_REG, status);
> >> +
> >> +	if (!err_status)
> >> +		return IRQ_HANDLED;
> >> +
> >> +	rcsi2_write(priv, INTERRSTATE_REG, err_status);
> >> +
> >> +	dev_err(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
> >> +
> >> +	return IRQ_WAKE_THREAD;
> >> +}
> >> +
> >> +static irqreturn_t rcsi2_irq_thread(int irq, void *data)
> >> +{
> >> +	struct rcar_csi2 *priv = data;
> >> +
> >> +	mutex_lock(&priv->lock);
> >> +	rcsi2_stop(priv);
> >> +	usleep_range(1000, 2000);
> >> +	if (rcsi2_start(priv))
> >> +		dev_err(priv->dev, "Failed to restart CSI-2 receiver\n");
> >> +	mutex_unlock(&priv->lock);
> >> +
> >> +	return IRQ_HANDLED;
> >> +}
> >> +
> >>  /* -----------------------------------------------------------------------------
> >>   * Async handling and registration of subdevices and links.
> >>   */
> >> @@ -982,7 +1026,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
> >>  				 struct platform_device *pdev)
> >>  {
> >>  	struct resource *res;
> >> -	int irq;
> >> +	int irq, ret;
> >>  
> >>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >>  	priv->base = devm_ioremap_resource(&pdev->dev, res);
> >> @@ -993,6 +1037,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
> >>  	if (irq < 0)
> >>  		return irq;
> >>  
> >> +	ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
> >> +					rcsi2_irq_thread, IRQF_SHARED,
> >> +					KBUILD_MODNAME, priv);
> >> +	if (ret)
> >> +		return ret;
> >> +
> >>  	priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
> >>  	if (IS_ERR(priv->rstc))
> >>  		return PTR_ERR(priv->rstc);

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] rcar-csi2: restart CSI-2 link if error is detected
  2019-03-12 20:22     ` Laurent Pinchart
@ 2019-03-12 21:37       ` Niklas Söderlund
  0 siblings, 0 replies; 5+ messages in thread
From: Niklas Söderlund @ 2019-03-12 21:37 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Hans Verkuil, linux-media, linux-renesas-soc

Hi Laurent,

On 2019-03-12 22:22:01 +0200, Laurent Pinchart wrote:
> Hello Niklas,
> 
> On Tue, Mar 12, 2019 at 07:58:13PM +0100, Niklas Söderlund wrote:
> > On 2019-03-11 11:53:01 +0100, Hans Verkuil wrote:
> > > On 2/18/19 11:15 AM, Niklas Söderlund wrote:
> > >> Restart the CSI-2 link if the CSI-2 receiver detects an error during
> > >> reception. The driver did nothing when a link error happened and the
> > >> data flow simply stopped without the user knowing why.
> > >> 
> > >> Change the driver to try and recover from errors by restarting the link
> > >> and informing the user that something is not right. For obvious reasons
> > >> it's not possible to recover from all errors (video source disconnected
> > >> for example) but in such cases the user is at least informed of the
> > >> error and the same behavior of the stopped data flow is retained.
> 
> What error causes have you noticed in practice that would benefit from
> this ?

In practice I have not manage to produce this error using the ADV748x 
which would match a real world use-case. I have however demonstrated 
that it works by introducing a small delay between the bottom and top 
half of the irq handler and unplugging / replugging the HDMI cable to 
trigger the issue and see that it recovers.

> 
> > > What you really would like to have is that when a CSI error is detected,
> > > the CSI driver can ask upstream whether or not a disconnect has taken place.
> > > 
> > > If that was the case, then there is no point in restarting the CSI.
> > > 
> > > While a disconnect is very uncommon for a sensor, it is of course perfectly
> > > normal if an HDMI-to-CSI bridge was connected to the CSI port.
> 
> Note that this may not always result in a CSI-2 error, the HDMI to CSI-2
> bridge may continue sending valid timings with dummy (or random) data.
> 
> > > Unfortunately, we don't have such functionality, but perhaps this is something
> > > to think about?
> > 
> > I think your idea sounds good and that such a functionality could be 
> > useful. I have a  feeling such a functionality could be related to 
> > notifications?
> > 
> > > This does mean, however, that I don't like the dev_err since it doesn't have
> > > to be an error. I would suggest replacing the first dev_err by dev_info and
> > > the second by dev_warn.
> > 
> > With the background you provides I agree that they should not be 
> > dev_err. I will update as you suggest for the next version, thanks.
> > 
> > >> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> > >> ---
> > >>  drivers/media/platform/rcar-vin/rcar-csi2.c | 52 ++++++++++++++++++++-
> > >>  1 file changed, 51 insertions(+), 1 deletion(-)
> > >> 
> > >> diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c
> > >> index f90b380478775015..0506fe4106d5c012 100644
> > >> --- a/drivers/media/platform/rcar-vin/rcar-csi2.c
> > >> +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
> > >> @@ -84,6 +84,9 @@ struct rcar_csi2;
> > >>  
> > >>  /* Interrupt Enable */
> > >>  #define INTEN_REG			0x30
> > >> +#define INTEN_INT_AFIFO_OF		BIT(27)
> > >> +#define INTEN_INT_ERRSOTHS		BIT(4)
> > >> +#define INTEN_INT_ERRSOTSYNCHS		BIT(3)
> > >>  
> > >>  /* Interrupt Source Mask */
> > >>  #define INTCLOSE_REG			0x34
> > >> @@ -540,6 +543,10 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
> > >>  	if (mbps < 0)
> > >>  		return mbps;
> > >>  
> > >> +	/* Enable interrupts. */
> > >> +	rcsi2_write(priv, INTEN_REG, INTEN_INT_AFIFO_OF | INTEN_INT_ERRSOTHS
> > >> +		    | INTEN_INT_ERRSOTSYNCHS);
> > >> +
> > >>  	/* Init */
> > >>  	rcsi2_write(priv, TREF_REG, TREF_TREF);
> > >>  	rcsi2_write(priv, PHTC_REG, 0);
> > >> @@ -702,6 +709,43 @@ static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
> > >>  	.pad	= &rcar_csi2_pad_ops,
> > >>  };
> > >>  
> > >> +static irqreturn_t rcsi2_irq(int irq, void *data)
> > >> +{
> > >> +	struct rcar_csi2 *priv = data;
> > >> +	u32 status, err_status;
> > >> +
> > >> +	status = rcsi2_read(priv, INTSTATE_REG);
> > >> +	err_status = rcsi2_read(priv, INTERRSTATE_REG);
> > >> +
> > >> +	if (!status)
> > >> +		return IRQ_HANDLED;
> > >> +
> > >> +	rcsi2_write(priv, INTSTATE_REG, status);
> > >> +
> > >> +	if (!err_status)
> > >> +		return IRQ_HANDLED;
> > >> +
> > >> +	rcsi2_write(priv, INTERRSTATE_REG, err_status);
> > >> +
> > >> +	dev_err(priv->dev, "Transfer error, restarting CSI-2 receiver\n");
> > >> +
> > >> +	return IRQ_WAKE_THREAD;
> > >> +}
> > >> +
> > >> +static irqreturn_t rcsi2_irq_thread(int irq, void *data)
> > >> +{
> > >> +	struct rcar_csi2 *priv = data;
> > >> +
> > >> +	mutex_lock(&priv->lock);
> > >> +	rcsi2_stop(priv);
> > >> +	usleep_range(1000, 2000);
> > >> +	if (rcsi2_start(priv))
> > >> +		dev_err(priv->dev, "Failed to restart CSI-2 receiver\n");
> > >> +	mutex_unlock(&priv->lock);
> > >> +
> > >> +	return IRQ_HANDLED;
> > >> +}
> > >> +
> > >>  /* -----------------------------------------------------------------------------
> > >>   * Async handling and registration of subdevices and links.
> > >>   */
> > >> @@ -982,7 +1026,7 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
> > >>  				 struct platform_device *pdev)
> > >>  {
> > >>  	struct resource *res;
> > >> -	int irq;
> > >> +	int irq, ret;
> > >>  
> > >>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > >>  	priv->base = devm_ioremap_resource(&pdev->dev, res);
> > >> @@ -993,6 +1037,12 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv,
> > >>  	if (irq < 0)
> > >>  		return irq;
> > >>  
> > >> +	ret = devm_request_threaded_irq(&pdev->dev, irq, rcsi2_irq,
> > >> +					rcsi2_irq_thread, IRQF_SHARED,
> > >> +					KBUILD_MODNAME, priv);
> > >> +	if (ret)
> > >> +		return ret;
> > >> +
> > >>  	priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
> > >>  	if (IS_ERR(priv->rstc))
> > >>  		return PTR_ERR(priv->rstc);
> 
> -- 
> Regards,
> 
> Laurent Pinchart

-- 
Regards,
Niklas Söderlund

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-03-12 21:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-18 10:15 [PATCH] rcar-csi2: restart CSI-2 link if error is detected Niklas Söderlund
2019-03-11 10:53 ` Hans Verkuil
2019-03-12 18:58   ` Niklas Söderlund
2019-03-12 20:22     ` Laurent Pinchart
2019-03-12 21:37       ` Niklas Söderlund

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).