All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Yoshihiro Kaneko <ykaneko0929@gmail.com>,
	Simon Horman <horms@verge.net.au>
Cc: linux-media@vger.kernel.org,
	Mauro Carvalho Chehab <m.chehab@samsung.com>,
	Magnus Damm <magnus.damm@gmail.com>,
	linux-sh@vger.kernel.org
Subject: Re: [PATCH/RFC] v4l: vsp1: Fix Suspend-to-RAM
Date: Wed, 29 Apr 2015 19:10:38 +0000	[thread overview]
Message-ID: <1823698.5Nvuu0NHzD@avalon> (raw)
In-Reply-To: <1426429987-3134-1-git-send-email-ykaneko0929@gmail.com>

Hello Kaneko-san,

I'm so sorry for the very late reply, I had missed your patch :-/

First of all, thank you for the patch. Please see below for a few comments.

On Sunday 15 March 2015 23:33:07 Yoshihiro Kaneko wrote:
> From: Sei Fumizono <sei.fumizono.jw@hitachi-solutions.com>
> 
> Fix Suspend-to-RAM
> so that VSP1 driver continues to work after resuming.
> 
> In detail,
>   - Fix the judgment of ref count in resuming.
>   - Add stopping VSP1 during suspend.

That's two fixes, I believe they should be split in two patches, one to fix 
the ref_count bug at resume time, and the other one to stop/restart the video 
stream.

> Signed-off-by: Sei Fumizono <sei.fumizono.jw@hitachi-solutions.com>
> Signed-off-by: Yoshifumi Hosoya <yoshifumi.hosoya.wj@renesas.com>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
> ---
> 
> This patch is based on the master branch of linuxtv.org/media_tree.git.
> 
>  drivers/media/platform/vsp1/vsp1_drv.c   | 39 +++++++++++++++++++++++++----
>  drivers/media/platform/vsp1/vsp1_video.c | 31 ++++++++++++++++++++++++-
>  drivers/media/platform/vsp1/vsp1_video.h |  5 +++-
>  3 files changed, 69 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c
> b/drivers/media/platform/vsp1/vsp1_drv.c index 913485a..b6e9cbc 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -1,7 +1,7 @@
>  /*
>   * vsp1_drv.c  --  R-Car VSP1 Driver
>   *
> - * Copyright (C) 2013-2014 Renesas Electronics Corporation
> + * Copyright (C) 2013-2015 Renesas Electronics Corporation
>   *
>   * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
>   *
> @@ -397,26 +397,57 @@ void vsp1_device_put(struct vsp1_device *vsp1)
>  static int vsp1_pm_suspend(struct device *dev)
>  {
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> +	unsigned int i = 0;

There's no need to initialize i to 0 here, the for loop takes care of it.

> +	int ret = 0;
> 
>  	WARN_ON(mutex_is_locked(&vsp1->lock));
> 
>  	if (vsp1->ref_count = 0)
>  		return 0;
> 
> +	/* Suspend pipeline */
> +	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
> +		struct vsp1_rwpf *wpf = vsp1->wpf[i];
> +		struct vsp1_pipeline *pipe;
> +
> +		if (wpf = NULL)
> +			continue;
> +
> +		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
> +		ret = vsp1_pipeline_suspend(pipe);
> +		if (ret < 0)
> +			break;
> +	}

This will stop all running pipelines sequentially, which would increase the 
system suspend time quite a bit if all pipelines are running. I would instead 
first set the state of all pipelines to VSP1_PIPELINE_STOPPING in one loop, 
and then loop over all pipelines again to wait for them to finish. Something 
like

	/* To avoid increasing the system suspend time needlessly, loop over the
	 * pipelines twice, first to set them all to the stopping state, and then
	 * to wait for the stop to complete.
	 */
	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
		struct vsp1_rwpf *wpf = vsp1->wpf[i];
		struct vsp1_pipeline *pipe;

		if (wpf = NULL)
			continue;

		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
		if (pipe = NULL)
			continue;

		spin_lock_irqsave(&pipe->irqlock, flags);
		if (pipe->state = VSP1_PIPELINE_RUNNING)
			pipe->state = VSP1_PIPELINE_STOPPING;
		spin_unlock_irqrestore(&pipe->irqlock, flags);
	}

	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
		struct vsp1_rwpf *wpf = vsp1->wpf[i];
		struct vsp1_pipeline *pipe;

		if (wpf = NULL)
			continue;

		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
		if (pipe = NULL)
			continue;

		ret = wait_event_timeout(pipe->wq,
				pipe->state = VSP1_PIPELINE_STOPPED,
                  msecs_to_jiffies(500));
		if (ret = 0)
			dev_warn(vsp1->dev, "pipeline stop timeout\n");
	}

You could move all that code to a vsp1_pipelines_suspend() function in 
vsp1_video.c.

I've only printed a warning message instead of returning an error in case the 
pipeline fails to stop, as I believe it shouldn't prevent the system from 
entering suspend.

> +
>  	clk_disable_unprepare(vsp1->clock);
> -	return 0;
> +	return ret;
>  }
> 
>  static int vsp1_pm_resume(struct device *dev)
>  {
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> +	unsigned int i = 0;

There's no need to initialize i to 0 here either.

>  	WARN_ON(mutex_is_locked(&vsp1->lock));
> 
> -	if (vsp1->ref_count)
> +	if (vsp1->ref_count = 0)
>  		return 0;
> 
> -	return clk_prepare_enable(vsp1->clock);
> +	clk_prepare_enable(vsp1->clock);
> +
> +	/* Resume pipeline */
> +	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
> +		struct vsp1_rwpf *wpf = vsp1->wpf[i];
> +		struct vsp1_pipeline *pipe;
> +
> +		if (wpf = NULL)
> +			continue;
> +
> +		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
> +		vsp1_pipeline_resume(pipe);
> +	}

If you move the suspend code to a vsp1_pipelines_suspend() function, I believe 
it would make sense to move that loop to a vsp1_pipelines_resume() function as 
well. I would then just move to code from vsp1_pipeline_resume() inside the 
loop.

Would you like to submit a new version of this patch (split in two) ? I can 
also perform the modifications myself if you prefer.

> +
> +	return 0;
>  }
>  #endif
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c
> b/drivers/media/platform/vsp1/vsp1_video.c index d91f19a..c744608 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -1,7 +1,7 @@
>  /*
>   * vsp1_video.c  --  R-Car VSP1 Video Node
>   *
> - * Copyright (C) 2013-2014 Renesas Electronics Corporation
> + * Copyright (C) 2013-2015 Renesas Electronics Corporation
>   *
>   * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
>   *
> @@ -662,6 +662,35 @@ done:
>  	spin_unlock_irqrestore(&pipe->irqlock, flags);
>  }
> 
> +int vsp1_pipeline_suspend(struct vsp1_pipeline *pipe)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	if (pipe = NULL)
> +		return 0;
> +
> +	spin_lock_irqsave(&pipe->irqlock, flags);
> +	if (pipe->state = VSP1_PIPELINE_RUNNING)
> +		pipe->state = VSP1_PIPELINE_STOPPING;
> +	spin_unlock_irqrestore(&pipe->irqlock, flags);
> +
> +	ret = wait_event_timeout(pipe->wq, pipe->state = VSP1_PIPELINE_STOPPED,
> +				 msecs_to_jiffies(500));
> +	ret = ret = 0 ? -ETIMEDOUT : 0;
> +
> +	return ret;
> +}
> +
> +void vsp1_pipeline_resume(struct vsp1_pipeline *pipe)
> +{
> +	if (pipe = NULL)
> +		return;
> +
> +	if (vsp1_pipeline_ready(pipe))
> +		vsp1_pipeline_run(pipe);
> +}
> +
>  /*
>   * Propagate the alpha value through the pipeline.
>   *
> diff --git a/drivers/media/platform/vsp1/vsp1_video.h
> b/drivers/media/platform/vsp1/vsp1_video.h index fd2851a..958a166 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.h
> +++ b/drivers/media/platform/vsp1/vsp1_video.h
> @@ -1,7 +1,7 @@
>  /*
>   * vsp1_video.h  --  R-Car VSP1 Video Node
>   *
> - * Copyright (C) 2013-2014 Renesas Electronics Corporation
> + * Copyright (C) 2013-2015 Renesas Electronics Corporation
>   *
>   * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
>   *
> @@ -149,4 +149,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline
> *pipe, struct vsp1_entity *input,
>  				   unsigned int alpha);
> 
> +int vsp1_pipeline_suspend(struct vsp1_pipeline *pipe);
> +void vsp1_pipeline_resume(struct vsp1_pipeline *pipe);
> +
>  #endif /* __VSP1_VIDEO_H__ */

-- 
Regards,

Laurent Pinchart


WARNING: multiple messages have this Message-ID (diff)
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Yoshihiro Kaneko <ykaneko0929@gmail.com>,
	Simon Horman <horms@verge.net.au>
Cc: linux-media@vger.kernel.org,
	Mauro Carvalho Chehab <m.chehab@samsung.com>,
	Magnus Damm <magnus.damm@gmail.com>,
	linux-sh@vger.kernel.org
Subject: Re: [PATCH/RFC] v4l: vsp1: Fix Suspend-to-RAM
Date: Wed, 29 Apr 2015 22:10:38 +0300	[thread overview]
Message-ID: <1823698.5Nvuu0NHzD@avalon> (raw)
In-Reply-To: <1426429987-3134-1-git-send-email-ykaneko0929@gmail.com>

Hello Kaneko-san,

I'm so sorry for the very late reply, I had missed your patch :-/

First of all, thank you for the patch. Please see below for a few comments.

On Sunday 15 March 2015 23:33:07 Yoshihiro Kaneko wrote:
> From: Sei Fumizono <sei.fumizono.jw@hitachi-solutions.com>
> 
> Fix Suspend-to-RAM
> so that VSP1 driver continues to work after resuming.
> 
> In detail,
>   - Fix the judgment of ref count in resuming.
>   - Add stopping VSP1 during suspend.

That's two fixes, I believe they should be split in two patches, one to fix 
the ref_count bug at resume time, and the other one to stop/restart the video 
stream.

> Signed-off-by: Sei Fumizono <sei.fumizono.jw@hitachi-solutions.com>
> Signed-off-by: Yoshifumi Hosoya <yoshifumi.hosoya.wj@renesas.com>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
> ---
> 
> This patch is based on the master branch of linuxtv.org/media_tree.git.
> 
>  drivers/media/platform/vsp1/vsp1_drv.c   | 39 +++++++++++++++++++++++++----
>  drivers/media/platform/vsp1/vsp1_video.c | 31 ++++++++++++++++++++++++-
>  drivers/media/platform/vsp1/vsp1_video.h |  5 +++-
>  3 files changed, 69 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c
> b/drivers/media/platform/vsp1/vsp1_drv.c index 913485a..b6e9cbc 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -1,7 +1,7 @@
>  /*
>   * vsp1_drv.c  --  R-Car VSP1 Driver
>   *
> - * Copyright (C) 2013-2014 Renesas Electronics Corporation
> + * Copyright (C) 2013-2015 Renesas Electronics Corporation
>   *
>   * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
>   *
> @@ -397,26 +397,57 @@ void vsp1_device_put(struct vsp1_device *vsp1)
>  static int vsp1_pm_suspend(struct device *dev)
>  {
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> +	unsigned int i = 0;

There's no need to initialize i to 0 here, the for loop takes care of it.

> +	int ret = 0;
> 
>  	WARN_ON(mutex_is_locked(&vsp1->lock));
> 
>  	if (vsp1->ref_count == 0)
>  		return 0;
> 
> +	/* Suspend pipeline */
> +	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
> +		struct vsp1_rwpf *wpf = vsp1->wpf[i];
> +		struct vsp1_pipeline *pipe;
> +
> +		if (wpf == NULL)
> +			continue;
> +
> +		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
> +		ret = vsp1_pipeline_suspend(pipe);
> +		if (ret < 0)
> +			break;
> +	}

This will stop all running pipelines sequentially, which would increase the 
system suspend time quite a bit if all pipelines are running. I would instead 
first set the state of all pipelines to VSP1_PIPELINE_STOPPING in one loop, 
and then loop over all pipelines again to wait for them to finish. Something 
like

	/* To avoid increasing the system suspend time needlessly, loop over the
	 * pipelines twice, first to set them all to the stopping state, and then
	 * to wait for the stop to complete.
	 */
	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
		struct vsp1_rwpf *wpf = vsp1->wpf[i];
		struct vsp1_pipeline *pipe;

		if (wpf == NULL)
			continue;

		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
		if (pipe == NULL)
			continue;

		spin_lock_irqsave(&pipe->irqlock, flags);
		if (pipe->state == VSP1_PIPELINE_RUNNING)
			pipe->state = VSP1_PIPELINE_STOPPING;
		spin_unlock_irqrestore(&pipe->irqlock, flags);
	}

	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
		struct vsp1_rwpf *wpf = vsp1->wpf[i];
		struct vsp1_pipeline *pipe;

		if (wpf == NULL)
			continue;

		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
		if (pipe == NULL)
			continue;

		ret = wait_event_timeout(pipe->wq,
				pipe->state == VSP1_PIPELINE_STOPPED,
                  msecs_to_jiffies(500));
		if (ret == 0)
			dev_warn(vsp1->dev, "pipeline stop timeout\n");
	}

You could move all that code to a vsp1_pipelines_suspend() function in 
vsp1_video.c.

I've only printed a warning message instead of returning an error in case the 
pipeline fails to stop, as I believe it shouldn't prevent the system from 
entering suspend.

> +
>  	clk_disable_unprepare(vsp1->clock);
> -	return 0;
> +	return ret;
>  }
> 
>  static int vsp1_pm_resume(struct device *dev)
>  {
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> +	unsigned int i = 0;

There's no need to initialize i to 0 here either.

>  	WARN_ON(mutex_is_locked(&vsp1->lock));
> 
> -	if (vsp1->ref_count)
> +	if (vsp1->ref_count == 0)
>  		return 0;
> 
> -	return clk_prepare_enable(vsp1->clock);
> +	clk_prepare_enable(vsp1->clock);
> +
> +	/* Resume pipeline */
> +	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
> +		struct vsp1_rwpf *wpf = vsp1->wpf[i];
> +		struct vsp1_pipeline *pipe;
> +
> +		if (wpf == NULL)
> +			continue;
> +
> +		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
> +		vsp1_pipeline_resume(pipe);
> +	}

If you move the suspend code to a vsp1_pipelines_suspend() function, I believe 
it would make sense to move that loop to a vsp1_pipelines_resume() function as 
well. I would then just move to code from vsp1_pipeline_resume() inside the 
loop.

Would you like to submit a new version of this patch (split in two) ? I can 
also perform the modifications myself if you prefer.

> +
> +	return 0;
>  }
>  #endif
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c
> b/drivers/media/platform/vsp1/vsp1_video.c index d91f19a..c744608 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -1,7 +1,7 @@
>  /*
>   * vsp1_video.c  --  R-Car VSP1 Video Node
>   *
> - * Copyright (C) 2013-2014 Renesas Electronics Corporation
> + * Copyright (C) 2013-2015 Renesas Electronics Corporation
>   *
>   * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
>   *
> @@ -662,6 +662,35 @@ done:
>  	spin_unlock_irqrestore(&pipe->irqlock, flags);
>  }
> 
> +int vsp1_pipeline_suspend(struct vsp1_pipeline *pipe)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	if (pipe == NULL)
> +		return 0;
> +
> +	spin_lock_irqsave(&pipe->irqlock, flags);
> +	if (pipe->state == VSP1_PIPELINE_RUNNING)
> +		pipe->state = VSP1_PIPELINE_STOPPING;
> +	spin_unlock_irqrestore(&pipe->irqlock, flags);
> +
> +	ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED,
> +				 msecs_to_jiffies(500));
> +	ret = ret == 0 ? -ETIMEDOUT : 0;
> +
> +	return ret;
> +}
> +
> +void vsp1_pipeline_resume(struct vsp1_pipeline *pipe)
> +{
> +	if (pipe == NULL)
> +		return;
> +
> +	if (vsp1_pipeline_ready(pipe))
> +		vsp1_pipeline_run(pipe);
> +}
> +
>  /*
>   * Propagate the alpha value through the pipeline.
>   *
> diff --git a/drivers/media/platform/vsp1/vsp1_video.h
> b/drivers/media/platform/vsp1/vsp1_video.h index fd2851a..958a166 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.h
> +++ b/drivers/media/platform/vsp1/vsp1_video.h
> @@ -1,7 +1,7 @@
>  /*
>   * vsp1_video.h  --  R-Car VSP1 Video Node
>   *
> - * Copyright (C) 2013-2014 Renesas Electronics Corporation
> + * Copyright (C) 2013-2015 Renesas Electronics Corporation
>   *
>   * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
>   *
> @@ -149,4 +149,7 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline
> *pipe, struct vsp1_entity *input,
>  				   unsigned int alpha);
> 
> +int vsp1_pipeline_suspend(struct vsp1_pipeline *pipe);
> +void vsp1_pipeline_resume(struct vsp1_pipeline *pipe);
> +
>  #endif /* __VSP1_VIDEO_H__ */

-- 
Regards,

Laurent Pinchart


  parent reply	other threads:[~2015-04-29 19:10 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-15 14:33 [PATCH/RFC] v4l: vsp1: Fix Suspend-to-RAM Yoshihiro Kaneko
2015-03-15 14:33 ` Yoshihiro Kaneko
2015-03-29 13:17 ` Yoshihiro Kaneko
2015-03-29 13:17   ` Yoshihiro Kaneko
2015-04-29 19:10 ` Laurent Pinchart [this message]
2015-04-29 19:10   ` Laurent Pinchart

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1823698.5Nvuu0NHzD@avalon \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=horms@verge.net.au \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-sh@vger.kernel.org \
    --cc=m.chehab@samsung.com \
    --cc=magnus.damm@gmail.com \
    --cc=ykaneko0929@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.